From 6627fa662e86c400284b64c13661fdf6bff05983 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 9 Jan 2006 13:50:57 -0800 Subject: [PATCH 001/465] IB/mthca: fix page shift calculation in mthca_reg_phys_mr() For all pages except possibly the last one, the byte beyond the buffer end must be page aligned. Therefore, when computing the page shift to use, OR the end addresses of the buffers as well as the start addresses into the mask we check. Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_provider.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index 4cc7e2846df..30b67c20026 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c @@ -783,24 +783,20 @@ static struct ib_mr *mthca_reg_phys_mr(struct ib_pd *pd, if ((*iova_start & ~PAGE_MASK) != (buffer_list[0].addr & ~PAGE_MASK)) return ERR_PTR(-EINVAL); - if (num_phys_buf > 1 && - ((buffer_list[0].addr + buffer_list[0].size) & ~PAGE_MASK)) - return ERR_PTR(-EINVAL); - mask = 0; total_size = 0; for (i = 0; i < num_phys_buf; ++i) { - if (i != 0 && buffer_list[i].addr & ~PAGE_MASK) - return ERR_PTR(-EINVAL); - if (i != 0 && i != num_phys_buf - 1 && - (buffer_list[i].size & ~PAGE_MASK)) - return ERR_PTR(-EINVAL); + if (i != 0) + mask |= buffer_list[i].addr; + if (i != num_phys_buf - 1) + mask |= buffer_list[i].addr + buffer_list[i].size; total_size += buffer_list[i].size; - if (i > 0) - mask |= buffer_list[i].addr; } + if (mask & ~PAGE_MASK) + return ERR_PTR(-EINVAL); + /* Find largest page shift we can use to cover buffers */ for (shift = PAGE_SHIFT; shift < 31; ++shift) if (num_phys_buf > 1) { -- GitLab From 92898522e3ee1a0ba54140aad1974d9e868f74ae Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 9 Jan 2006 14:04:40 -0800 Subject: [PATCH 002/465] IB/mthca: prevent event queue overrun I am seeing EQ overruns in SDP stress tests: if the CQ completion handler arms a CQ, this could generate more EQEs, so that EQ will never get empty and consumer index will never get updated. This is similiar to what we have with command interface: /* * cmd_event() may add more commands. * The card will think the queue has overflowed if * we don't tell it we've been processing events. */ However, for completion events, we *don't* want to update the consumer index on each event. So, perform EQ doorbell coalescing: allocate EQs with some spare EQEs, and update once we run out of them. The value 0x80 was selected to avoid any performance impact. Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_eq.c | 28 ++++++++++++++------------ 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c index e8a948f087c..2eabb27804c 100644 --- a/drivers/infiniband/hw/mthca/mthca_eq.c +++ b/drivers/infiniband/hw/mthca/mthca_eq.c @@ -45,6 +45,7 @@ enum { MTHCA_NUM_ASYNC_EQE = 0x80, MTHCA_NUM_CMD_EQE = 0x80, + MTHCA_NUM_SPARE_EQE = 0x80, MTHCA_EQ_ENTRY_SIZE = 0x20 }; @@ -277,11 +278,10 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq) { struct mthca_eqe *eqe; int disarm_cqn; - int eqes_found = 0; + int eqes_found = 0; + int set_ci = 0; while ((eqe = next_eqe_sw(eq))) { - int set_ci = 0; - /* * Make sure we read EQ entry contents after we've * checked the ownership bit. @@ -345,12 +345,6 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq) be16_to_cpu(eqe->event.cmd.token), eqe->event.cmd.status, be64_to_cpu(eqe->event.cmd.out_param)); - /* - * cmd_event() may add more commands. - * The card will think the queue has overflowed if - * we don't tell it we've been processing events. - */ - set_ci = 1; break; case MTHCA_EVENT_TYPE_PORT_CHANGE: @@ -385,8 +379,16 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq) set_eqe_hw(eqe); ++eq->cons_index; eqes_found = 1; + ++set_ci; - if (unlikely(set_ci)) { + /* + * The HCA will think the queue has overflowed if we + * don't tell it we've been processing events. We + * create our EQs with MTHCA_NUM_SPARE_EQE extra + * entries, so we must update our consumer index at + * least that often. + */ + if (unlikely(set_ci >= MTHCA_NUM_SPARE_EQE)) { /* * Conditional on hca_type is OK here because * this is a rare case, not the fast path. @@ -862,19 +864,19 @@ int __devinit mthca_init_eq_table(struct mthca_dev *dev) intr = (dev->mthca_flags & MTHCA_FLAG_MSI) ? 128 : dev->eq_table.inta_pin; - err = mthca_create_eq(dev, dev->limits.num_cqs, + err = mthca_create_eq(dev, dev->limits.num_cqs + MTHCA_NUM_SPARE_EQE, (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 128 : intr, &dev->eq_table.eq[MTHCA_EQ_COMP]); if (err) goto err_out_unmap; - err = mthca_create_eq(dev, MTHCA_NUM_ASYNC_EQE, + err = mthca_create_eq(dev, MTHCA_NUM_ASYNC_EQE + MTHCA_NUM_SPARE_EQE, (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 129 : intr, &dev->eq_table.eq[MTHCA_EQ_ASYNC]); if (err) goto err_out_comp; - err = mthca_create_eq(dev, MTHCA_NUM_CMD_EQE, + err = mthca_create_eq(dev, MTHCA_NUM_CMD_EQE + MTHCA_NUM_SPARE_EQE, (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 130 : intr, &dev->eq_table.eq[MTHCA_EQ_CMD]); if (err) -- GitLab From 105e50a5e8f184af31daffce4d7bfd7771fe213f Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 9 Jan 2006 15:21:21 -0800 Subject: [PATCH 003/465] IB/mthca: kzalloc conversions Convert kmalloc()/memset(,0,) pairs to kzalloc(). Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_provider.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index 30b67c20026..0ae27fa26c7 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c @@ -55,7 +55,7 @@ static int mthca_query_device(struct ib_device *ibdev, u8 status; - in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL); + in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); if (!in_mad || !out_mad) goto out; @@ -64,7 +64,6 @@ static int mthca_query_device(struct ib_device *ibdev, props->fw_ver = mdev->fw_ver; - memset(in_mad, 0, sizeof *in_mad); in_mad->base_version = 1; in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; in_mad->class_version = 1; @@ -128,14 +127,13 @@ static int mthca_query_port(struct ib_device *ibdev, int err = -ENOMEM; u8 status; - in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL); + in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); if (!in_mad || !out_mad) goto out; memset(props, 0, sizeof *props); - memset(in_mad, 0, sizeof *in_mad); in_mad->base_version = 1; in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; in_mad->class_version = 1; @@ -220,12 +218,11 @@ static int mthca_query_pkey(struct ib_device *ibdev, int err = -ENOMEM; u8 status; - in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL); + in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); if (!in_mad || !out_mad) goto out; - memset(in_mad, 0, sizeof *in_mad); in_mad->base_version = 1; in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; in_mad->class_version = 1; @@ -259,12 +256,11 @@ static int mthca_query_gid(struct ib_device *ibdev, u8 port, int err = -ENOMEM; u8 status; - in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL); + in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); if (!in_mad || !out_mad) goto out; - memset(in_mad, 0, sizeof *in_mad); in_mad->base_version = 1; in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; in_mad->class_version = 1; -- GitLab From 87635b71b544563f29050a9cecaa12b5d2a3e34a Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 9 Jan 2006 15:29:53 -0800 Subject: [PATCH 004/465] IB/mthca: Factor common MAD initialization code Factor out common code for initializing MAD packets, which is shared by many query routines in mthca_provider.c, into init_query_mad(). add/remove: 1/0 grow/shrink: 0/4 up/down: 16/-44 (-28) function old new delta init_query_mad - 16 +16 mthca_query_port 521 518 -3 mthca_query_pkey 301 294 -7 mthca_query_device 648 641 -7 mthca_query_gid 453 426 -27 Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_provider.c | 52 +++++++++----------- 1 file changed, 22 insertions(+), 30 deletions(-) diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index 0ae27fa26c7..488757766a5 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c @@ -45,6 +45,14 @@ #include "mthca_user.h" #include "mthca_memfree.h" +static void init_query_mad(struct ib_smp *mad) +{ + mad->base_version = 1; + mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; + mad->class_version = 1; + mad->method = IB_MGMT_METHOD_GET; +} + static int mthca_query_device(struct ib_device *ibdev, struct ib_device_attr *props) { @@ -64,11 +72,8 @@ static int mthca_query_device(struct ib_device *ibdev, props->fw_ver = mdev->fw_ver; - in_mad->base_version = 1; - in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; - in_mad->class_version = 1; - in_mad->method = IB_MGMT_METHOD_GET; - in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; + init_query_mad(in_mad); + in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; err = mthca_MAD_IFC(mdev, 1, 1, 1, NULL, NULL, in_mad, out_mad, @@ -134,12 +139,9 @@ static int mthca_query_port(struct ib_device *ibdev, memset(props, 0, sizeof *props); - in_mad->base_version = 1; - in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; - in_mad->class_version = 1; - in_mad->method = IB_MGMT_METHOD_GET; - in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; - in_mad->attr_mod = cpu_to_be32(port); + init_query_mad(in_mad); + in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; + in_mad->attr_mod = cpu_to_be32(port); err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad, @@ -223,12 +225,9 @@ static int mthca_query_pkey(struct ib_device *ibdev, if (!in_mad || !out_mad) goto out; - in_mad->base_version = 1; - in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; - in_mad->class_version = 1; - in_mad->method = IB_MGMT_METHOD_GET; - in_mad->attr_id = IB_SMP_ATTR_PKEY_TABLE; - in_mad->attr_mod = cpu_to_be32(index / 32); + init_query_mad(in_mad); + in_mad->attr_id = IB_SMP_ATTR_PKEY_TABLE; + in_mad->attr_mod = cpu_to_be32(index / 32); err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad, @@ -261,12 +260,9 @@ static int mthca_query_gid(struct ib_device *ibdev, u8 port, if (!in_mad || !out_mad) goto out; - in_mad->base_version = 1; - in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; - in_mad->class_version = 1; - in_mad->method = IB_MGMT_METHOD_GET; - in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; - in_mad->attr_mod = cpu_to_be32(port); + init_query_mad(in_mad); + in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; + in_mad->attr_mod = cpu_to_be32(port); err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad, @@ -280,13 +276,9 @@ static int mthca_query_gid(struct ib_device *ibdev, u8 port, memcpy(gid->raw, out_mad->data + 8, 8); - memset(in_mad, 0, sizeof *in_mad); - in_mad->base_version = 1; - in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; - in_mad->class_version = 1; - in_mad->method = IB_MGMT_METHOD_GET; - in_mad->attr_id = IB_SMP_ATTR_GUID_INFO; - in_mad->attr_mod = cpu_to_be32(index / 8); + init_query_mad(in_mad); + in_mad->attr_id = IB_SMP_ATTR_GUID_INFO; + in_mad->attr_mod = cpu_to_be32(index / 8); err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad, -- GitLab From cf311cd49a78f1e431787068cc31d29d06a415e6 Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Tue, 10 Jan 2006 07:39:34 -0800 Subject: [PATCH 005/465] IB: Add node_guid to struct ib_device Add a node_guid field to struct ib_device. It is the responsibility of the low-level driver to initialize this field before registering a device with the midlayer. Convert everyone to looking at this field instead of calling ib_query_device() when all they want is the node GUID, and remove the node_guid field from struct ib_device_attr. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cm.c | 29 +++----------- drivers/infiniband/core/sysfs.c | 22 +++-------- drivers/infiniband/core/uverbs_cmd.c | 2 +- drivers/infiniband/hw/mthca/mthca_provider.c | 40 +++++++++++++++++++- drivers/infiniband/ulp/srp/ib_srp.c | 23 ++--------- include/rdma/ib_verbs.h | 2 +- 6 files changed, 54 insertions(+), 64 deletions(-) diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 3a611fe5497..c06b18102b6 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -3163,22 +3163,6 @@ int ib_cm_init_qp_attr(struct ib_cm_id *cm_id, } EXPORT_SYMBOL(ib_cm_init_qp_attr); -static __be64 cm_get_ca_guid(struct ib_device *device) -{ - struct ib_device_attr *device_attr; - __be64 guid; - int ret; - - device_attr = kmalloc(sizeof *device_attr, GFP_KERNEL); - if (!device_attr) - return 0; - - ret = ib_query_device(device, device_attr); - guid = ret ? 0 : device_attr->node_guid; - kfree(device_attr); - return guid; -} - static void cm_add_one(struct ib_device *device) { struct cm_device *cm_dev; @@ -3200,9 +3184,7 @@ static void cm_add_one(struct ib_device *device) return; cm_dev->device = device; - cm_dev->ca_guid = cm_get_ca_guid(device); - if (!cm_dev->ca_guid) - goto error1; + cm_dev->ca_guid = device->node_guid; set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask); for (i = 1; i <= device->phys_port_cnt; i++) { @@ -3217,11 +3199,11 @@ static void cm_add_one(struct ib_device *device) cm_recv_handler, port); if (IS_ERR(port->mad_agent)) - goto error2; + goto error1; ret = ib_modify_port(device, i, 0, &port_modify); if (ret) - goto error3; + goto error2; } ib_set_client_data(device, &cm_client, cm_dev); @@ -3230,9 +3212,9 @@ static void cm_add_one(struct ib_device *device) write_unlock_irqrestore(&cm.device_lock, flags); return; -error3: - ib_unregister_mad_agent(port->mad_agent); error2: + ib_unregister_mad_agent(port->mad_agent); +error1: port_modify.set_port_cap_mask = 0; port_modify.clr_port_cap_mask = IB_PORT_CM_SUP; while (--i) { @@ -3240,7 +3222,6 @@ error2: ib_modify_port(device, port->port_num, 0, &port_modify); ib_unregister_mad_agent(port->mad_agent); } -error1: kfree(cm_dev); } diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index 1f1743c5c9a..5982d687a00 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c @@ -445,13 +445,7 @@ static int ib_device_uevent(struct class_device *cdev, char **envp, return -ENOMEM; /* - * It might be nice to pass the node GUID with the event, but - * right now the only way to get it is to query the device - * provider, and this can crash during device removal because - * we are will be running after driver removal has started. - * We could add a node_guid field to struct ib_device, or we - * could just let userspace read the node GUID from sysfs when - * devices are added. + * It would be nice to pass the node GUID with the event... */ envp[i] = NULL; @@ -623,21 +617,15 @@ static ssize_t show_sys_image_guid(struct class_device *cdev, char *buf) static ssize_t show_node_guid(struct class_device *cdev, char *buf) { struct ib_device *dev = container_of(cdev, struct ib_device, class_dev); - struct ib_device_attr attr; - ssize_t ret; if (!ibdev_is_alive(dev)) return -ENODEV; - ret = ib_query_device(dev, &attr); - if (ret) - return ret; - return sprintf(buf, "%04x:%04x:%04x:%04x\n", - be16_to_cpu(((__be16 *) &attr.node_guid)[0]), - be16_to_cpu(((__be16 *) &attr.node_guid)[1]), - be16_to_cpu(((__be16 *) &attr.node_guid)[2]), - be16_to_cpu(((__be16 *) &attr.node_guid)[3])); + be16_to_cpu(((__be16 *) &dev->node_guid)[0]), + be16_to_cpu(((__be16 *) &dev->node_guid)[1]), + be16_to_cpu(((__be16 *) &dev->node_guid)[2]), + be16_to_cpu(((__be16 *) &dev->node_guid)[3])); } static CLASS_DEVICE_ATTR(node_type, S_IRUGO, show_node_type, NULL); diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index a02c5a05c98..554c2057b7c 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -157,7 +157,7 @@ ssize_t ib_uverbs_query_device(struct ib_uverbs_file *file, memset(&resp, 0, sizeof resp); resp.fw_ver = attr.fw_ver; - resp.node_guid = attr.node_guid; + resp.node_guid = file->device->ib_dev->node_guid; resp.sys_image_guid = attr.sys_image_guid; resp.max_mr_size = attr.max_mr_size; resp.page_size_cap = attr.page_size_cap; diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index 488757766a5..db35690c91d 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c @@ -33,7 +33,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * - * $Id: mthca_provider.c 1397 2004-12-28 05:09:00Z roland $ + * $Id: mthca_provider.c 4859 2006-01-09 21:55:10Z roland $ */ #include @@ -91,7 +91,6 @@ static int mthca_query_device(struct ib_device *ibdev, props->vendor_part_id = be16_to_cpup((__be16 *) (out_mad->data + 30)); props->hw_ver = be32_to_cpup((__be32 *) (out_mad->data + 32)); memcpy(&props->sys_image_guid, out_mad->data + 4, 8); - memcpy(&props->node_guid, out_mad->data + 12, 8); props->max_mr_size = ~0ull; props->page_size_cap = mdev->limits.page_size_cap; @@ -1054,11 +1053,48 @@ static struct class_device_attribute *mthca_class_attributes[] = { &class_device_attr_board_id }; +static int mthca_init_node_data(struct mthca_dev *dev) +{ + struct ib_smp *in_mad = NULL; + struct ib_smp *out_mad = NULL; + int err = -ENOMEM; + u8 status; + + in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); + out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); + if (!in_mad || !out_mad) + goto out; + + init_query_mad(in_mad); + in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; + + err = mthca_MAD_IFC(dev, 1, 1, + 1, NULL, NULL, in_mad, out_mad, + &status); + if (err) + goto out; + if (status) { + err = -EINVAL; + goto out; + } + + memcpy(&dev->ib_dev.node_guid, out_mad->data + 12, 8); + +out: + kfree(in_mad); + kfree(out_mad); + return err; +} + int mthca_register_device(struct mthca_dev *dev) { int ret; int i; + ret = mthca_init_node_data(dev); + if (ret) + return ret; + strlcpy(dev->ib_dev.name, "mthca%d", IB_DEVICE_NAME_MAX); dev->ib_dev.owner = THIS_MODULE; diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index dd488d3cffa..31207e66414 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -1516,8 +1516,7 @@ static ssize_t show_port(struct class_device *class_dev, char *buf) static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL); -static struct srp_host *srp_add_port(struct ib_device *device, - __be64 node_guid, u8 port) +static struct srp_host *srp_add_port(struct ib_device *device, u8 port) { struct srp_host *host; @@ -1532,7 +1531,7 @@ static struct srp_host *srp_add_port(struct ib_device *device, host->port = port; host->initiator_port_id[7] = port; - memcpy(host->initiator_port_id + 8, &node_guid, 8); + memcpy(host->initiator_port_id + 8, &device->node_guid, 8); host->pd = ib_alloc_pd(device); if (IS_ERR(host->pd)) @@ -1580,22 +1579,11 @@ static void srp_add_one(struct ib_device *device) { struct list_head *dev_list; struct srp_host *host; - struct ib_device_attr *dev_attr; int s, e, p; - dev_attr = kmalloc(sizeof *dev_attr, GFP_KERNEL); - if (!dev_attr) - return; - - if (ib_query_device(device, dev_attr)) { - printk(KERN_WARNING PFX "Couldn't query node GUID for %s.\n", - device->name); - goto out; - } - dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL); if (!dev_list) - goto out; + return; INIT_LIST_HEAD(dev_list); @@ -1608,15 +1596,12 @@ static void srp_add_one(struct ib_device *device) } for (p = s; p <= e; ++p) { - host = srp_add_port(device, dev_attr->node_guid, p); + host = srp_add_port(device, p); if (host) list_add_tail(&host->list, dev_list); } ib_set_client_data(device, &srp_client, dev_list); - -out: - kfree(dev_attr); } static void srp_remove_one(struct ib_device *device) diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index a7f4c355a91..22fc886b969 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -88,7 +88,6 @@ enum ib_atomic_cap { struct ib_device_attr { u64 fw_ver; - __be64 node_guid; __be64 sys_image_guid; u64 max_mr_size; u64 page_size_cap; @@ -951,6 +950,7 @@ struct ib_device { u64 uverbs_cmd_mask; int uverbs_abi_ver; + __be64 node_guid; u8 node_type; u8 phys_port_cnt; }; -- GitLab From 70b4c8cdc168bb5d18e23fd205c4ede1b756a8b2 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Tue, 10 Jan 2006 07:42:14 -0800 Subject: [PATCH 006/465] IPoIB: Fix error path in ipoib_mcast_dev_flush() Don't leak memory on allocation failure for broadcast mcast group. Also, print a warning to match handling for other mcast groups. Signed-off-by: Eli Cohen Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index ed0c2ead8bc..6c6db759e79 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -780,9 +780,11 @@ void ipoib_mcast_dev_flush(struct net_device *dev) &priv->multicast_tree); list_add_tail(&priv->broadcast->list, &remove_list); - } - - priv->broadcast = nmcast; + priv->broadcast = nmcast; + } else + ipoib_warn(priv, "could not reallocate broadcast group " + IPOIB_GID_FMT "\n", + IPOIB_GID_ARG(priv->broadcast->mcmember.mgid)); } spin_unlock_irqrestore(&priv->lock, flags); -- GitLab From 97460df37ea3335ca11562568932c9f9facfecdb Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Tue, 10 Jan 2006 07:43:02 -0800 Subject: [PATCH 007/465] IPoIB: Fix address handle refcounting for multicast groups Multiple ipoib_neigh structures on mcast->neigh_list may point to the same ah. This means that ipoib_mcast_free() can't just make a list of ah structs to free, since this might end up trying to add the same ah to the list more than once. Handle this in ipoib_multicast.c in the same way as it is handled in ipoib_main.c for struct ipoib_path. Signed-off-by: Eli Cohen Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 6c6db759e79..03b2ca64a40 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -97,8 +97,6 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast) struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_neigh *neigh, *tmp; unsigned long flags; - LIST_HEAD(ah_list); - struct ipoib_ah *ah, *tah; ipoib_dbg_mcast(netdev_priv(dev), "deleting multicast group " IPOIB_GID_FMT "\n", @@ -107,8 +105,14 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast) spin_lock_irqsave(&priv->lock, flags); list_for_each_entry_safe(neigh, tmp, &mcast->neigh_list, list) { + /* + * It's safe to call ipoib_put_ah() inside priv->lock + * here, because we know that mcast->ah will always + * hold one more reference, so ipoib_put_ah() will + * never do more than decrement the ref count. + */ if (neigh->ah) - list_add_tail(&neigh->ah->list, &ah_list); + ipoib_put_ah(neigh->ah); *to_ipoib_neigh(neigh->neighbour) = NULL; neigh->neighbour->ops->destructor = NULL; kfree(neigh); @@ -116,9 +120,6 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast) spin_unlock_irqrestore(&priv->lock, flags); - list_for_each_entry_safe(ah, tah, &ah_list, list) - ipoib_put_ah(ah); - if (mcast->ah) ipoib_put_ah(mcast->ah); -- GitLab From 78bfe0b5b67fe126ed98608e42e42fb6ed9aabd4 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 11 Jan 2006 11:47:34 -0800 Subject: [PATCH 008/465] IPoIB: Take dev->xmit_lock around mc_list accesses dev->mc_list accesses must be protected by dev->xmit_lock. Found by Eli Cohen . Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 03b2ca64a40..bf1c08cca8c 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -827,7 +827,8 @@ void ipoib_mcast_restart_task(void *dev_ptr) ipoib_mcast_stop_thread(dev, 0); - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&dev->xmit_lock, flags); + spin_lock(&priv->lock); /* * Unfortunately, the networking core only gives us a list of all of @@ -899,7 +900,9 @@ void ipoib_mcast_restart_task(void *dev_ptr) list_add_tail(&mcast->list, &remove_list); } } - spin_unlock_irqrestore(&priv->lock, flags); + + spin_unlock(&priv->lock); + spin_unlock_irqrestore(&dev->xmit_lock, flags); /* We have to cancel outside of the spinlock */ list_for_each_entry_safe(mcast, tmcast, &remove_list, list) { -- GitLab From 8e32ca49ef2eb5bfec1444b5e731cc2d35111519 Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Wed, 4 Jan 2006 14:58:43 -0700 Subject: [PATCH 009/465] [SCSI] raid_class.c - adding RAID10 and RAID10 defines Adding defines for RAID10 and RAID50 levels, in preparation of adding RAID Transport support in the mpt fusion drivers. (BTW: IME is RAID10, and IM is RAID1). Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/scsi/raid_class.c | 2 ++ include/linux/raid_class.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c index 5ec5f44602a..50c398aab55 100644 --- a/drivers/scsi/raid_class.c +++ b/drivers/scsi/raid_class.c @@ -148,9 +148,11 @@ static struct { { RAID_LEVEL_LINEAR, "linear" }, { RAID_LEVEL_0, "raid0" }, { RAID_LEVEL_1, "raid1" }, + { RAID_LEVEL_10, "raid10" }, { RAID_LEVEL_3, "raid3" }, { RAID_LEVEL_4, "raid4" }, { RAID_LEVEL_5, "raid5" }, + { RAID_LEVEL_50, "raid50" }, { RAID_LEVEL_6, "raid6" }, }; diff --git a/include/linux/raid_class.h b/include/linux/raid_class.h index 48831eac291..d0dd38b3a2f 100644 --- a/include/linux/raid_class.h +++ b/include/linux/raid_class.h @@ -31,9 +31,11 @@ enum raid_level { RAID_LEVEL_LINEAR, RAID_LEVEL_0, RAID_LEVEL_1, + RAID_LEVEL_10, RAID_LEVEL_3, RAID_LEVEL_4, RAID_LEVEL_5, + RAID_LEVEL_50, RAID_LEVEL_6, }; -- GitLab From bdd70f2cebce0f5172350aab37c057c3b66494ac Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 5 Jan 2006 23:39:18 +0100 Subject: [PATCH 010/465] [SCSI] scsi_transport_spi.c: make print_nego() static Signed-off-by: Adrian Bunk Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 46da6fe10ad..86306d681b6 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -1075,7 +1075,7 @@ static const char * const extended_msgs[] = { /* 0x04 */ "Parallel Protocol Request" }; -void print_nego(const unsigned char *msg, int per, int off, int width) +static void print_nego(const unsigned char *msg, int per, int off, int width) { if (per) { char buf[20]; -- GitLab From 455c53ec61a6c96d7b21b72ad1fa26ac89824e8e Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 6 Jan 2006 20:21:28 +0100 Subject: [PATCH 011/465] [SCSI] lpfc_scsi.c: make lpfc_get_scsi_buf() static Signed-off-by: Adrian Bunk Acked-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_scsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 9ee8218404c..dafabeefc5b 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -150,7 +150,7 @@ lpfc_new_scsi_buf(struct lpfc_hba * phba) return psb; } -struct lpfc_scsi_buf* +static struct lpfc_scsi_buf* lpfc_get_scsi_buf(struct lpfc_hba * phba) { struct lpfc_scsi_buf * lpfc_cmd = NULL; -- GitLab From 8e0df4a757db82a571f3a179108b62d09258eaf2 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Mon, 9 Jan 2006 10:17:40 -0800 Subject: [PATCH 012/465] [SCSI] qla2xxx: Kconfig: two fixes Original From: Adrian Bunk Here's a composite patch with Adrian's original additions and help-text with the new Kconfig variable SCSI_QLA_FC. Signed-off-by: James Bottomley --- drivers/scsi/Makefile | 2 +- drivers/scsi/qla2xxx/Kconfig | 20 ++++++++++++-------- drivers/scsi/qla2xxx/Makefile | 2 +- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index f062ea0f813..b9d2bb88787 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -80,7 +80,7 @@ obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas408.o qlogicfas.o obj-$(CONFIG_PCMCIA_QLOGIC) += qlogicfas408.o obj-$(CONFIG_SCSI_QLOGIC_FC) += qlogicfc.o obj-$(CONFIG_SCSI_QLOGIC_1280) += qla1280.o -obj-$(CONFIG_SCSI_QLA2XXX) += qla2xxx/ +obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx/ obj-$(CONFIG_SCSI_LPFC) += lpfc/ obj-$(CONFIG_SCSI_PAS16) += pas16.o obj-$(CONFIG_SCSI_SEAGATE) += seagate.o diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig index 5205c4e7d6f..02cc79474e8 100644 --- a/drivers/scsi/qla2xxx/Kconfig +++ b/drivers/scsi/qla2xxx/Kconfig @@ -1,4 +1,4 @@ -config SCSI_QLA2XXX +config SCSI_QLA_FC tristate "QLogic QLA2XXX Fibre Channel Support" depends on PCI && SCSI select SCSI_FC_ATTRS @@ -28,43 +28,47 @@ config SCSI_QLA2XXX config SCSI_QLA2XXX_EMBEDDED_FIRMWARE bool " Use firmware-loader modules (DEPRECATED)" - depends on SCSI_QLA2XXX + depends on SCSI_QLA_FC + help + This option offers you the deprecated firmware-loader + modules that have been obsoleted by the usage of the + Firmware Loader interface in the qla2xxx driver. config SCSI_QLA21XX tristate " Build QLogic ISP2100 firmware-module" - depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE + depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE ---help--- This driver supports the QLogic 21xx (ISP2100) host adapter family. config SCSI_QLA22XX tristate " Build QLogic ISP2200 firmware-module" - depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE + depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE ---help--- This driver supports the QLogic 22xx (ISP2200) host adapter family. config SCSI_QLA2300 tristate " Build QLogic ISP2300 firmware-module" - depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE + depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE ---help--- This driver supports the QLogic 2300 (ISP2300 and ISP2312) host adapter family. config SCSI_QLA2322 tristate " Build QLogic ISP2322 firmware-module" - depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE + depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE ---help--- This driver supports the QLogic 2322 (ISP2322) host adapter family. config SCSI_QLA6312 tristate " Build QLogic ISP63xx firmware-module" - depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE + depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE ---help--- This driver supports the QLogic 63xx (ISP6312 and ISP6322) host adapter family. config SCSI_QLA24XX tristate " Build QLogic ISP24xx firmware-module" - depends on SCSI_QLA2XXX_EMBEDDED_FIRMWARE + depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE ---help--- This driver supports the QLogic 24xx (ISP2422 and ISP2432) host adapter family. diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile index 40c0de12588..d028bc50ccf 100644 --- a/drivers/scsi/qla2xxx/Makefile +++ b/drivers/scsi/qla2xxx/Makefile @@ -3,7 +3,7 @@ EXTRA_CFLAGS += -DUNIQUE_FW_NAME qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \ qla_dbg.o qla_sup.o qla_rscn.o qla_attr.o -obj-$(CONFIG_SCSI_QLA2XXX) += qla2xxx.o +obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o qla2100-y := ql2100.o ql2100_fw.o qla2200-y := ql2200.o ql2200_fw.o -- GitLab From dacee84b070c4e705a5b6446f1f0a6a6e2f8d7a4 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 10 Jan 2006 12:11:42 -0600 Subject: [PATCH 013/465] [SCSI] aic7xxx: fix timer handling bug The driver is doing a rather stupid mod_timer allegedly to "give request sense more time to complete". This is illegal and pointless, so just eliminate it. Also eliminate all the other uses of struct timer_list in the driver, which are mostly bogus. Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/Kconfig.aic7xxx | 4 ++-- drivers/scsi/aic7xxx/aic7xxx_osm.c | 28 ++++++++++++++-------------- drivers/scsi/aic7xxx/aic7xxx_osm.h | 25 ------------------------- 3 files changed, 16 insertions(+), 41 deletions(-) diff --git a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx index ac8de03c9fa..6c2c395554f 100644 --- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx +++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx @@ -42,13 +42,13 @@ config AIC7XXX_CMDS_PER_DEVICE config AIC7XXX_RESET_DELAY_MS int "Initial bus reset delay in milli-seconds" depends on SCSI_AIC7XXX - default "15000" + default "5000" ---help--- The number of milliseconds to delay after an initial bus reset. The bus settle delay following all error recovery actions is dictated by the SCSI layer and is not affected by this value. - Default: 15000 (15 seconds) + Default: 5000 (5 seconds) config AIC7XXX_PROBE_EISA_VL bool "Probe for EISA and VL AIC7XXX Adapters" diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index fd389e9f946..051970efba6 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -375,7 +375,7 @@ static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, struct scsi_cmnd *cmd); static void ahc_linux_sem_timeout(u_long arg); static void ahc_linux_freeze_simq(struct ahc_softc *ahc); -static void ahc_linux_release_simq(u_long arg); +static void ahc_linux_release_simq(struct ahc_softc *ahc); static int ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag); static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc); static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc, @@ -1073,7 +1073,6 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa return (ENOMEM); *((struct ahc_softc **)host->hostdata) = ahc; - ahc_lock(ahc, &s); ahc->platform_data->host = host; host->can_queue = AHC_MAX_QUEUE; host->cmd_per_lun = 2; @@ -1084,7 +1083,9 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa host->max_lun = AHC_NUM_LUNS; host->max_channel = (ahc->features & AHC_TWIN) ? 1 : 0; host->sg_tablesize = AHC_NSEG; + ahc_lock(ahc, &s); ahc_set_unit(ahc, ahc_linux_unit++); + ahc_unlock(ahc, &s); sprintf(buf, "scsi%d", host->host_no); new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); if (new_name != NULL) { @@ -1094,7 +1095,6 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa host->unique_id = ahc->unit; ahc_linux_initialize_scsi_bus(ahc); ahc_intr_enable(ahc, TRUE); - ahc_unlock(ahc, &s); host->transportt = ahc_linux_transport_template; @@ -1120,10 +1120,13 @@ ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc) { int i; int numtarg; + unsigned long s; i = 0; numtarg = 0; + ahc_lock(ahc, &s); + if (aic7xxx_no_reset != 0) ahc->flags &= ~(AHC_RESET_BUS_A|AHC_RESET_BUS_B); @@ -1170,16 +1173,12 @@ ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc) ahc_update_neg_request(ahc, &devinfo, tstate, tinfo, AHC_NEG_ALWAYS); } + ahc_unlock(ahc, &s); /* Give the bus some time to recover */ if ((ahc->flags & (AHC_RESET_BUS_A|AHC_RESET_BUS_B)) != 0) { ahc_linux_freeze_simq(ahc); - init_timer(&ahc->platform_data->reset_timer); - ahc->platform_data->reset_timer.data = (u_long)ahc; - ahc->platform_data->reset_timer.expires = - jiffies + (AIC7XXX_RESET_DELAY * HZ)/1000; - ahc->platform_data->reset_timer.function = - ahc_linux_release_simq; - add_timer(&ahc->platform_data->reset_timer); + msleep(AIC7XXX_RESET_DELAY); + ahc_linux_release_simq(ahc); } } @@ -2059,6 +2058,9 @@ ahc_linux_sem_timeout(u_long arg) static void ahc_linux_freeze_simq(struct ahc_softc *ahc) { + unsigned long s; + + ahc_lock(ahc, &s); ahc->platform_data->qfrozen++; if (ahc->platform_data->qfrozen == 1) { scsi_block_requests(ahc->platform_data->host); @@ -2068,17 +2070,15 @@ ahc_linux_freeze_simq(struct ahc_softc *ahc) CAM_LUN_WILDCARD, SCB_LIST_NULL, ROLE_INITIATOR, CAM_REQUEUE_REQ); } + ahc_unlock(ahc, &s); } static void -ahc_linux_release_simq(u_long arg) +ahc_linux_release_simq(struct ahc_softc *ahc) { - struct ahc_softc *ahc; u_long s; int unblock_reqs; - ahc = (struct ahc_softc *)arg; - unblock_reqs = 0; ahc_lock(ahc, &s); if (ahc->platform_data->qfrozen > 0) diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h index f2a95447142..e0edacae895 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h @@ -223,9 +223,6 @@ int ahc_dmamap_unload(struct ahc_softc *, bus_dma_tag_t, bus_dmamap_t); */ #define ahc_dmamap_sync(ahc, dma_tag, dmamap, offset, len, op) -/************************** Timer DataStructures ******************************/ -typedef struct timer_list ahc_timer_t; - /********************************** Includes **********************************/ #ifdef CONFIG_AIC7XXX_REG_PRETTY_PRINT #define AIC_DEBUG_REGISTERS 1 @@ -235,30 +232,9 @@ typedef struct timer_list ahc_timer_t; #include "aic7xxx.h" /***************************** Timer Facilities *******************************/ -#define ahc_timer_init init_timer -#define ahc_timer_stop del_timer_sync -typedef void ahc_linux_callback_t (u_long); -static __inline void ahc_timer_reset(ahc_timer_t *timer, int usec, - ahc_callback_t *func, void *arg); -static __inline void ahc_scb_timer_reset(struct scb *scb, u_int usec); - -static __inline void -ahc_timer_reset(ahc_timer_t *timer, int usec, ahc_callback_t *func, void *arg) -{ - struct ahc_softc *ahc; - - ahc = (struct ahc_softc *)arg; - del_timer(timer); - timer->data = (u_long)arg; - timer->expires = jiffies + (usec * HZ)/1000000; - timer->function = (ahc_linux_callback_t*)func; - add_timer(timer); -} - static __inline void ahc_scb_timer_reset(struct scb *scb, u_int usec) { - mod_timer(&scb->io_ctx->eh_timeout, jiffies + (usec * HZ)/1000000); } /***************************** SMP support ************************************/ @@ -393,7 +369,6 @@ struct ahc_platform_data { spinlock_t spin_lock; u_int qfrozen; - struct timer_list reset_timer; struct semaphore eh_sem; struct Scsi_Host *host; /* pointer to scsi host */ #define AHC_LINUX_NOIRQ ((uint32_t)~0) -- GitLab From 0b9506723826c68b50fa33e345700ddcac1bed36 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Wed, 11 Jan 2006 13:16:10 +0100 Subject: [PATCH 014/465] [SCSI] turn most scsi semaphores into mutexes the scsi layer is using semaphores in a mutex way, this patch converts these into using mutexes instead Signed-off-by: Arjan van de Ven Signed-off-by: James Bottomley --- drivers/scsi/ch.c | 33 +++++++++++++------------ drivers/scsi/dpt_i2o.c | 35 +++++++++++++------------- drivers/scsi/hosts.c | 8 +++--- drivers/scsi/iscsi_tcp.c | 37 ++++++++++++++-------------- drivers/scsi/iscsi_tcp.h | 2 +- drivers/scsi/megaraid.c | 6 ++--- drivers/scsi/megaraid.h | 4 +-- drivers/scsi/megaraid/megaraid_sas.c | 7 +++--- drivers/scsi/scsi.c | 13 +++++----- drivers/scsi/scsi_proc.c | 11 +++++---- drivers/scsi/scsi_scan.c | 16 ++++++------ drivers/scsi/scsi_sysfs.c | 4 +-- drivers/scsi/scsi_transport_iscsi.c | 17 +++++++------ drivers/scsi/sd.c | 21 ++++++++-------- drivers/scsi/sr.c | 17 +++++++------ drivers/scsi/st.c | 17 +++++++------ include/scsi/scsi_host.h | 3 ++- 17 files changed, 131 insertions(+), 120 deletions(-) diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c index 4299fabca55..c3f27285db1 100644 --- a/drivers/scsi/ch.c +++ b/drivers/scsi/ch.c @@ -22,6 +22,7 @@ #include #include #include /* here are all the ioctls */ +#include #include #include @@ -111,7 +112,7 @@ typedef struct { u_int counts[CH_TYPES]; u_int unit_attention; u_int voltags; - struct semaphore lock; + struct mutex lock; } scsi_changer; static LIST_HEAD(ch_devlist); @@ -565,7 +566,7 @@ static int ch_gstatus(scsi_changer *ch, int type, unsigned char __user *dest) u_char data[16]; unsigned int i; - down(&ch->lock); + mutex_lock(&ch->lock); for (i = 0; i < ch->counts[type]; i++) { if (0 != ch_read_element_status (ch, ch->firsts[type]+i,data)) { @@ -582,7 +583,7 @@ static int ch_gstatus(scsi_changer *ch, int type, unsigned char __user *dest) if (0 != retval) break; } - up(&ch->lock); + mutex_unlock(&ch->lock); return retval; } @@ -687,11 +688,11 @@ static int ch_ioctl(struct inode * inode, struct file * file, dprintk("CHIOPOSITION: invalid parameter\n"); return -EBADSLT; } - down(&ch->lock); + mutex_lock(&ch->lock); retval = ch_position(ch,0, ch->firsts[pos.cp_type] + pos.cp_unit, pos.cp_flags & CP_INVERT); - up(&ch->lock); + mutex_unlock(&ch->lock); return retval; } @@ -708,12 +709,12 @@ static int ch_ioctl(struct inode * inode, struct file * file, return -EBADSLT; } - down(&ch->lock); + mutex_lock(&ch->lock); retval = ch_move(ch,0, ch->firsts[mv.cm_fromtype] + mv.cm_fromunit, ch->firsts[mv.cm_totype] + mv.cm_tounit, mv.cm_flags & CM_INVERT); - up(&ch->lock); + mutex_unlock(&ch->lock); return retval; } @@ -731,14 +732,14 @@ static int ch_ioctl(struct inode * inode, struct file * file, return -EBADSLT; } - down(&ch->lock); + mutex_lock(&ch->lock); retval = ch_exchange (ch,0, ch->firsts[mv.ce_srctype] + mv.ce_srcunit, ch->firsts[mv.ce_fdsttype] + mv.ce_fdstunit, ch->firsts[mv.ce_sdsttype] + mv.ce_sdstunit, mv.ce_flags & CE_INVERT1, mv.ce_flags & CE_INVERT2); - up(&ch->lock); + mutex_unlock(&ch->lock); return retval; } @@ -772,7 +773,7 @@ static int ch_ioctl(struct inode * inode, struct file * file, buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); if (!buffer) return -ENOMEM; - down(&ch->lock); + mutex_lock(&ch->lock); voltag_retry: memset(cmd,0,sizeof(cmd)); @@ -823,7 +824,7 @@ static int ch_ioctl(struct inode * inode, struct file * file, goto voltag_retry; } kfree(buffer); - up(&ch->lock); + mutex_unlock(&ch->lock); if (copy_to_user(argp, &cge, sizeof (cge))) return -EFAULT; @@ -832,9 +833,9 @@ static int ch_ioctl(struct inode * inode, struct file * file, case CHIOINITELEM: { - down(&ch->lock); + mutex_lock(&ch->lock); retval = ch_init_elem(ch); - up(&ch->lock); + mutex_unlock(&ch->lock); return retval; } @@ -851,12 +852,12 @@ static int ch_ioctl(struct inode * inode, struct file * file, return -EBADSLT; } elem = ch->firsts[csv.csv_type] + csv.csv_unit; - down(&ch->lock); + mutex_lock(&ch->lock); retval = ch_set_voltag(ch, elem, csv.csv_flags & CSV_AVOLTAG, csv.csv_flags & CSV_CLEARTAG, csv.csv_voltag); - up(&ch->lock); + mutex_unlock(&ch->lock); return retval; } @@ -929,7 +930,7 @@ static int ch_probe(struct device *dev) memset(ch,0,sizeof(*ch)); ch->minor = ch_devcount; sprintf(ch->name,"ch%d",ch->minor); - init_MUTEX(&ch->lock); + mutex_init(&ch->lock); ch->device = sd; ch_readconfig(ch); if (init) diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index 6252b9ddc01..cdeb30b0462 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -61,6 +61,7 @@ MODULE_DESCRIPTION("Adaptec I2O RAID Driver"); #include #include #include +#include #include /* for boot_cpu_data */ #include @@ -106,7 +107,7 @@ static dpt_sig_S DPTI_sig = { *============================================================================ */ -static DECLARE_MUTEX(adpt_configuration_lock); +static DEFINE_MUTEX(adpt_configuration_lock); static struct i2o_sys_tbl *sys_tbl = NULL; static int sys_tbl_ind = 0; @@ -537,13 +538,13 @@ static int adpt_proc_info(struct Scsi_Host *host, char *buffer, char **start, of */ // Find HBA (host bus adapter) we are looking for - down(&adpt_configuration_lock); + mutex_lock(&adpt_configuration_lock); for (pHba = hba_chain; pHba; pHba = pHba->next) { if (pHba->host == host) { break; /* found adapter */ } } - up(&adpt_configuration_lock); + mutex_unlock(&adpt_configuration_lock); if (pHba == NULL) { return 0; } @@ -958,7 +959,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev } memset(pHba, 0, sizeof(adpt_hba)); - down(&adpt_configuration_lock); + mutex_lock(&adpt_configuration_lock); if(hba_chain != NULL){ for(p = hba_chain; p->next; p = p->next); @@ -971,7 +972,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev sprintf(pHba->name, "dpti%d", hba_count); hba_count++; - up(&adpt_configuration_lock); + mutex_unlock(&adpt_configuration_lock); pHba->pDev = pDev; pHba->base_addr_phys = base_addr0_phys; @@ -1027,7 +1028,7 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba) struct adpt_device* pNext; - down(&adpt_configuration_lock); + mutex_lock(&adpt_configuration_lock); // scsi_unregister calls our adpt_release which // does a quiese if(pHba->host){ @@ -1046,7 +1047,7 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba) } hba_count--; - up(&adpt_configuration_lock); + mutex_unlock(&adpt_configuration_lock); iounmap(pHba->base_addr_virt); pci_release_regions(pHba->pDev); @@ -1549,7 +1550,7 @@ static int adpt_i2o_parse_lct(adpt_hba* pHba) static int adpt_i2o_install_device(adpt_hba* pHba, struct i2o_device *d) { - down(&adpt_configuration_lock); + mutex_lock(&adpt_configuration_lock); d->controller=pHba; d->owner=NULL; d->next=pHba->devices; @@ -1560,7 +1561,7 @@ static int adpt_i2o_install_device(adpt_hba* pHba, struct i2o_device *d) pHba->devices=d; *d->dev_name = 0; - up(&adpt_configuration_lock); + mutex_unlock(&adpt_configuration_lock); return 0; } @@ -1575,24 +1576,24 @@ static int adpt_open(struct inode *inode, struct file *file) if (minor >= hba_count) { return -ENXIO; } - down(&adpt_configuration_lock); + mutex_lock(&adpt_configuration_lock); for (pHba = hba_chain; pHba; pHba = pHba->next) { if (pHba->unit == minor) { break; /* found adapter */ } } if (pHba == NULL) { - up(&adpt_configuration_lock); + mutex_unlock(&adpt_configuration_lock); return -ENXIO; } // if(pHba->in_use){ - // up(&adpt_configuration_lock); + // mutex_unlock(&adpt_configuration_lock); // return -EBUSY; // } pHba->in_use = 1; - up(&adpt_configuration_lock); + mutex_unlock(&adpt_configuration_lock); return 0; } @@ -1606,13 +1607,13 @@ static int adpt_close(struct inode *inode, struct file *file) if (minor >= hba_count) { return -ENXIO; } - down(&adpt_configuration_lock); + mutex_lock(&adpt_configuration_lock); for (pHba = hba_chain; pHba; pHba = pHba->next) { if (pHba->unit == minor) { break; /* found adapter */ } } - up(&adpt_configuration_lock); + mutex_unlock(&adpt_configuration_lock); if (pHba == NULL) { return -ENXIO; } @@ -1910,13 +1911,13 @@ static int adpt_ioctl(struct inode *inode, struct file *file, uint cmd, if (minor >= DPTI_MAX_HBA){ return -ENXIO; } - down(&adpt_configuration_lock); + mutex_lock(&adpt_configuration_lock); for (pHba = hba_chain; pHba; pHba = pHba->next) { if (pHba->unit == minor) { break; /* found adapter */ } } - up(&adpt_configuration_lock); + mutex_unlock(&adpt_configuration_lock); if(pHba == NULL){ return -ENXIO; } diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 66783c860a1..58810792349 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -156,16 +156,16 @@ EXPORT_SYMBOL(scsi_host_set_state); void scsi_remove_host(struct Scsi_Host *shost) { unsigned long flags; - down(&shost->scan_mutex); + mutex_lock(&shost->scan_mutex); spin_lock_irqsave(shost->host_lock, flags); if (scsi_host_set_state(shost, SHOST_CANCEL)) if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)) { spin_unlock_irqrestore(shost->host_lock, flags); - up(&shost->scan_mutex); + mutex_unlock(&shost->scan_mutex); return; } spin_unlock_irqrestore(shost->host_lock, flags); - up(&shost->scan_mutex); + mutex_unlock(&shost->scan_mutex); scsi_forget_host(shost); scsi_proc_host_rm(shost); @@ -320,7 +320,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) INIT_LIST_HEAD(&shost->starved_list); init_waitqueue_head(&shost->host_wait); - init_MUTEX(&shost->scan_mutex); + mutex_init(&shost->scan_mutex); shost->host_no = scsi_host_next_hn++; /* XXX(hch): still racy */ shost->dma_channel = 0xff; diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 10bcf42cb65..1067d77da10 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -2300,10 +2301,10 @@ iscsi_xmitworker(void *data) /* * serialize Xmit worker on a per-connection basis. */ - down(&conn->xmitsema); + mutex_lock(&conn->xmitmutex); if (iscsi_data_xmit(conn)) schedule_work(&conn->xmitwork); - up(&conn->xmitsema); + mutex_unlock(&conn->xmitmutex); } #define FAILURE_BAD_HOST 1 @@ -2367,11 +2368,11 @@ iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1); spin_unlock(&session->lock); - if (!in_interrupt() && !down_trylock(&conn->xmitsema)) { + if (!in_interrupt() && mutex_trylock(&conn->xmitmutex)) { spin_unlock_irq(host->host_lock); if (iscsi_data_xmit(conn)) schedule_work(&conn->xmitwork); - up(&conn->xmitsema); + mutex_unlock(&conn->xmitmutex); spin_lock_irq(host->host_lock); } else schedule_work(&conn->xmitwork); @@ -2531,7 +2532,7 @@ iscsi_conn_create(iscsi_sessionh_t sessionh, uint32_t conn_idx) goto max_recv_dlenght_alloc_fail; init_timer(&conn->tmabort_timer); - init_MUTEX(&conn->xmitsema); + mutex_init(&conn->xmitmutex); init_waitqueue_head(&conn->ehwait); return iscsi_handle(conn); @@ -2561,7 +2562,7 @@ iscsi_conn_destroy(iscsi_connh_t connh) struct iscsi_conn *conn = iscsi_ptr(connh); struct iscsi_session *session = conn->session; - down(&conn->xmitsema); + mutex_lock(&conn->xmitmutex); set_bit(SUSPEND_BIT, &conn->suspend_tx); if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE && conn->sock) { struct sock *sk = conn->sock->sk; @@ -2592,7 +2593,7 @@ iscsi_conn_destroy(iscsi_connh_t connh) } spin_unlock_bh(&session->lock); - up(&conn->xmitsema); + mutex_unlock(&conn->xmitmutex); /* * Block until all in-progress commands for this connection @@ -2796,7 +2797,7 @@ iscsi_conn_stop(iscsi_connh_t connh, int flag) set_bit(SUSPEND_BIT, &conn->suspend_rx); write_unlock_bh(&sk->sk_callback_lock); - down(&conn->xmitsema); + mutex_lock(&conn->xmitmutex); spin_lock_irqsave(session->host->host_lock, flags); spin_lock(&session->lock); @@ -2878,7 +2879,7 @@ iscsi_conn_stop(iscsi_connh_t connh, int flag) conn->datadgst_en = 0; } } - up(&conn->xmitsema); + mutex_unlock(&conn->xmitmutex); } static int @@ -3029,12 +3030,12 @@ iscsi_eh_abort(struct scsi_cmnd *sc) * 1) connection-level failure; * 2) recovery due protocol error; */ - down(&conn->xmitsema); + mutex_lock(&conn->xmitmutex); spin_lock_bh(&session->lock); if (session->state != ISCSI_STATE_LOGGED_IN) { if (session->state == ISCSI_STATE_TERMINATE) { spin_unlock_bh(&session->lock); - up(&conn->xmitsema); + mutex_unlock(&conn->xmitmutex); goto failed; } spin_unlock_bh(&session->lock); @@ -3052,7 +3053,7 @@ iscsi_eh_abort(struct scsi_cmnd *sc) * 2) session was re-open during time out of ctask. */ spin_unlock_bh(&session->lock); - up(&conn->xmitsema); + mutex_unlock(&conn->xmitmutex); goto success; } conn->tmabort_state = TMABORT_INITIAL; @@ -3107,7 +3108,7 @@ iscsi_eh_abort(struct scsi_cmnd *sc) conn->tmabort_state == TMABORT_SUCCESS) { conn->tmabort_state = TMABORT_INITIAL; spin_unlock_bh(&session->lock); - up(&conn->xmitsema); + mutex_unlock(&conn->xmitmutex); goto success; } conn->tmabort_state = TMABORT_INITIAL; @@ -3116,7 +3117,7 @@ iscsi_eh_abort(struct scsi_cmnd *sc) spin_unlock_bh(&session->lock); } } - up(&conn->xmitsema); + mutex_unlock(&conn->xmitmutex); /* @@ -3182,7 +3183,7 @@ failed: exit: del_timer_sync(&conn->tmabort_timer); - down(&conn->xmitsema); + mutex_lock(&conn->xmitmutex); if (conn->sock) { struct sock *sk = conn->sock->sk; @@ -3190,7 +3191,7 @@ exit: iscsi_ctask_cleanup(conn, ctask); write_unlock_bh(&sk->sk_callback_lock); } - up(&conn->xmitsema); + mutex_unlock(&conn->xmitmutex); return rc; } @@ -3601,9 +3602,9 @@ iscsi_conn_send_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr, char *data, struct iscsi_conn *conn = iscsi_ptr(connh); int rc; - down(&conn->xmitsema); + mutex_lock(&conn->xmitmutex); rc = iscsi_conn_send_generic(conn, hdr, data, data_size); - up(&conn->xmitsema); + mutex_unlock(&conn->xmitmutex); return rc; } diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h index 855f2dfd18a..9badafe8820 100644 --- a/drivers/scsi/iscsi_tcp.h +++ b/drivers/scsi/iscsi_tcp.h @@ -158,7 +158,7 @@ struct iscsi_conn { struct kfifo *mgmtqueue; /* mgmt (control) xmit queue */ struct kfifo *xmitqueue; /* data-path cmd queue */ struct work_struct xmitwork; /* per-conn. xmit workqueue */ - struct semaphore xmitsema; /* serializes connection xmit, + struct mutex xmitmutex; /* serializes connection xmit, * access to kfifos: * * xmitqueue, writequeue, * * immqueue, mgmtqueue */ diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 4a6feb1e5e3..d101a8a6f4e 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -4479,7 +4479,7 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru) * serialized. This is so because we want to reserve maximum number of * available command ids for the I/O commands. */ - down(&adapter->int_mtx); + mutex_lock(&adapter->int_mtx); scb = &adapter->int_scb; memset(scb, 0, sizeof(scb_t)); @@ -4527,7 +4527,7 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru) mc->cmd, mc->opcode, mc->subopcode, scmd->result); } - up(&adapter->int_mtx); + mutex_unlock(&adapter->int_mtx); return rval; } @@ -4866,7 +4866,7 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) adapter->has_64bit_addr = 0; } - init_MUTEX(&adapter->int_mtx); + mutex_init(&adapter->int_mtx); init_completion(&adapter->int_waitq); adapter->this_id = DEFAULT_INITIATOR_ID; diff --git a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h index 6f907802574..4b3e0d6e5af 100644 --- a/drivers/scsi/megaraid.h +++ b/drivers/scsi/megaraid.h @@ -2,7 +2,7 @@ #define __MEGARAID_H__ #include - +#include #define MEGARAID_VERSION \ "v2.00.3 (Release Date: Wed Feb 19 08:51:30 EST 2003)\n" @@ -889,7 +889,7 @@ typedef struct { scb_t int_scb; Scsi_Cmnd int_scmd; - struct semaphore int_mtx; /* To synchronize the internal + struct mutex int_mtx; /* To synchronize the internal commands */ struct completion int_waitq; /* wait queue for internal cmds */ diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 3c32e69afcd..c0bb8061401 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -72,7 +73,7 @@ MODULE_DEVICE_TABLE(pci, megasas_pci_table); static int megasas_mgmt_majorno; static struct megasas_mgmt_info megasas_mgmt_info; static struct fasync_struct *megasas_async_queue; -static DECLARE_MUTEX(megasas_async_queue_mutex); +static DEFINE_MUTEX(megasas_async_queue_mutex); /** * megasas_get_cmd - Get a command from the free pool @@ -2362,11 +2363,11 @@ static int megasas_mgmt_fasync(int fd, struct file *filep, int mode) { int rc; - down(&megasas_async_queue_mutex); + mutex_lock(&megasas_async_queue_mutex); rc = fasync_helper(fd, filep, mode, &megasas_async_queue); - up(&megasas_async_queue_mutex); + mutex_unlock(&megasas_async_queue_mutex); if (rc >= 0) { /* For sanity check when we get ioctl */ diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index ee5f4dfdab1..245ca99a641 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -55,6 +55,7 @@ #include #include #include +#include #include #include @@ -209,7 +210,7 @@ static struct scsi_host_cmd_pool scsi_cmd_dma_pool = { .gfp_mask = __GFP_DMA, }; -static DECLARE_MUTEX(host_cmd_pool_mutex); +static DEFINE_MUTEX(host_cmd_pool_mutex); static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask) @@ -330,7 +331,7 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost) * Select a command slab for this host and create it if not * yet existant. */ - down(&host_cmd_pool_mutex); + mutex_lock(&host_cmd_pool_mutex); pool = (shost->unchecked_isa_dma ? &scsi_cmd_dma_pool : &scsi_cmd_pool); if (!pool->users) { pool->slab = kmem_cache_create(pool->name, @@ -342,7 +343,7 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost) pool->users++; shost->cmd_pool = pool; - up(&host_cmd_pool_mutex); + mutex_unlock(&host_cmd_pool_mutex); /* * Get one backup command for this host. @@ -359,7 +360,7 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost) kmem_cache_destroy(pool->slab); return -ENOMEM; fail: - up(&host_cmd_pool_mutex); + mutex_unlock(&host_cmd_pool_mutex); return -ENOMEM; } @@ -381,10 +382,10 @@ void scsi_destroy_command_freelist(struct Scsi_Host *shost) kmem_cache_free(shost->cmd_pool->slab, cmd); } - down(&host_cmd_pool_mutex); + mutex_lock(&host_cmd_pool_mutex); if (!--shost->cmd_pool->users) kmem_cache_destroy(shost->cmd_pool->slab); - up(&host_cmd_pool_mutex); + mutex_unlock(&host_cmd_pool_mutex); } #ifdef CONFIG_SCSI_LOGGING diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c index a50958b1b6e..1b5711e714a 100644 --- a/drivers/scsi/scsi_proc.c +++ b/drivers/scsi/scsi_proc.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -41,7 +42,7 @@ static struct proc_dir_entry *proc_scsi; /* Protect sht->present and sht->proc_dir */ -static DECLARE_MUTEX(global_host_template_sem); +static DEFINE_MUTEX(global_host_template_mutex); static int proc_scsi_read(char *buffer, char **start, off_t offset, int length, int *eof, void *data) @@ -83,7 +84,7 @@ void scsi_proc_hostdir_add(struct scsi_host_template *sht) if (!sht->proc_info) return; - down(&global_host_template_sem); + mutex_lock(&global_host_template_mutex); if (!sht->present++) { sht->proc_dir = proc_mkdir(sht->proc_name, proc_scsi); if (!sht->proc_dir) @@ -92,7 +93,7 @@ void scsi_proc_hostdir_add(struct scsi_host_template *sht) else sht->proc_dir->owner = sht->module; } - up(&global_host_template_sem); + mutex_unlock(&global_host_template_mutex); } void scsi_proc_hostdir_rm(struct scsi_host_template *sht) @@ -100,12 +101,12 @@ void scsi_proc_hostdir_rm(struct scsi_host_template *sht) if (!sht->proc_info) return; - down(&global_host_template_sem); + mutex_lock(&global_host_template_mutex); if (!--sht->present && sht->proc_dir) { remove_proc_entry(sht->proc_name, proc_scsi); sht->proc_dir = NULL; } - up(&global_host_template_sem); + mutex_unlock(&global_host_template_mutex); } void scsi_proc_host_add(struct Scsi_Host *shost) diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 05ebb9cef96..edcd80b749c 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1289,14 +1289,14 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, return ERR_PTR(-ENOMEM); get_device(&starget->dev); - down(&shost->scan_mutex); + mutex_lock(&shost->scan_mutex); if (scsi_host_scan_allowed(shost)) { res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata); if (res != SCSI_SCAN_LUN_PRESENT) sdev = ERR_PTR(-ENODEV); } - up(&shost->scan_mutex); + mutex_unlock(&shost->scan_mutex); scsi_target_reap(starget); put_device(&starget->dev); @@ -1404,10 +1404,10 @@ void scsi_scan_target(struct device *parent, unsigned int channel, { struct Scsi_Host *shost = dev_to_shost(parent); - down(&shost->scan_mutex); + mutex_lock(&shost->scan_mutex); if (scsi_host_scan_allowed(shost)) __scsi_scan_target(parent, channel, id, lun, rescan); - up(&shost->scan_mutex); + mutex_unlock(&shost->scan_mutex); } EXPORT_SYMBOL(scsi_scan_target); @@ -1454,7 +1454,7 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun))) return -EINVAL; - down(&shost->scan_mutex); + mutex_lock(&shost->scan_mutex); if (scsi_host_scan_allowed(shost)) { if (channel == SCAN_WILD_CARD) for (channel = 0; channel <= shost->max_channel; @@ -1464,7 +1464,7 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, else scsi_scan_channel(shost, channel, id, lun, rescan); } - up(&shost->scan_mutex); + mutex_unlock(&shost->scan_mutex); return 0; } @@ -1522,7 +1522,7 @@ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) struct scsi_device *sdev = NULL; struct scsi_target *starget; - down(&shost->scan_mutex); + mutex_lock(&shost->scan_mutex); if (!scsi_host_scan_allowed(shost)) goto out; starget = scsi_alloc_target(&shost->shost_gendev, 0, shost->this_id); @@ -1536,7 +1536,7 @@ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) } put_device(&starget->dev); out: - up(&shost->scan_mutex); + mutex_unlock(&shost->scan_mutex); return sdev; } EXPORT_SYMBOL(scsi_get_host_dev); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index ea7f3a43357..2cb962751a7 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -745,9 +745,9 @@ void scsi_remove_device(struct scsi_device *sdev) { struct Scsi_Host *shost = sdev->host; - down(&shost->scan_mutex); + mutex_lock(&shost->scan_mutex); __scsi_remove_device(sdev); - up(&shost->scan_mutex); + mutex_unlock(&shost->scan_mutex); } EXPORT_SYMBOL(scsi_remove_device); diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index e08462d50c9..50ed88f98f4 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -46,7 +47,7 @@ struct iscsi_internal { struct list_head sessions; /* * lock to serialize access to the sessions list which must - * be taken after the rx_queue_sema + * be taken after the rx_queue_mutex */ spinlock_t session_lock; /* @@ -70,7 +71,7 @@ struct iscsi_internal { /* * list of registered transports and lock that must * be held while accessing list. The iscsi_transport_lock must - * be acquired after the rx_queue_sema. + * be acquired after the rx_queue_mutex. */ static LIST_HEAD(iscsi_transports); static DEFINE_SPINLOCK(iscsi_transport_lock); @@ -145,7 +146,7 @@ static DECLARE_TRANSPORT_CLASS(iscsi_connection_class, static struct sock *nls; static int daemon_pid; -static DECLARE_MUTEX(rx_queue_sema); +static DEFINE_MUTEX(rx_queue_mutex); struct mempool_zone { mempool_t *pool; @@ -881,7 +882,7 @@ iscsi_if_rx(struct sock *sk, int len) { struct sk_buff *skb; - down(&rx_queue_sema); + mutex_lock(&rx_queue_mutex); while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { while (skb->len >= NLMSG_SPACE(0)) { int err; @@ -923,7 +924,7 @@ iscsi_if_rx(struct sock *sk, int len) } kfree_skb(skb); } - up(&rx_queue_sema); + mutex_unlock(&rx_queue_mutex); } /* @@ -1159,7 +1160,7 @@ int iscsi_unregister_transport(struct iscsi_transport *tt) BUG_ON(!tt); - down(&rx_queue_sema); + mutex_lock(&rx_queue_mutex); priv = iscsi_if_transport_lookup(tt); BUG_ON (!priv); @@ -1167,7 +1168,7 @@ int iscsi_unregister_transport(struct iscsi_transport *tt) spin_lock_irqsave(&priv->session_lock, flags); if (!list_empty(&priv->sessions)) { spin_unlock_irqrestore(&priv->session_lock, flags); - up(&rx_queue_sema); + mutex_unlock(&rx_queue_mutex); return -EPERM; } spin_unlock_irqrestore(&priv->session_lock, flags); @@ -1181,7 +1182,7 @@ int iscsi_unregister_transport(struct iscsi_transport *tt) sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group); class_device_unregister(&priv->cdev); - up(&rx_queue_sema); + mutex_unlock(&rx_queue_mutex); return 0; } diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 4c5127ed379..fbd8e1bbad3 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include @@ -111,7 +112,7 @@ static DEFINE_SPINLOCK(sd_index_lock); /* This semaphore is used to mediate the 0->1 reference get in the * face of object destruction (i.e. we can't allow a get on an * object after last put) */ -static DECLARE_MUTEX(sd_ref_sem); +static DEFINE_MUTEX(sd_ref_mutex); static int sd_revalidate_disk(struct gendisk *disk); static void sd_rw_intr(struct scsi_cmnd * SCpnt); @@ -193,9 +194,9 @@ static struct scsi_disk *scsi_disk_get(struct gendisk *disk) { struct scsi_disk *sdkp; - down(&sd_ref_sem); + mutex_lock(&sd_ref_mutex); sdkp = __scsi_disk_get(disk); - up(&sd_ref_sem); + mutex_unlock(&sd_ref_mutex); return sdkp; } @@ -203,11 +204,11 @@ static struct scsi_disk *scsi_disk_get_from_dev(struct device *dev) { struct scsi_disk *sdkp; - down(&sd_ref_sem); + mutex_lock(&sd_ref_mutex); sdkp = dev_get_drvdata(dev); if (sdkp) sdkp = __scsi_disk_get(sdkp->disk); - up(&sd_ref_sem); + mutex_unlock(&sd_ref_mutex); return sdkp; } @@ -215,10 +216,10 @@ static void scsi_disk_put(struct scsi_disk *sdkp) { struct scsi_device *sdev = sdkp->device; - down(&sd_ref_sem); + mutex_lock(&sd_ref_mutex); kref_put(&sdkp->kref, scsi_disk_release); scsi_device_put(sdev); - up(&sd_ref_sem); + mutex_unlock(&sd_ref_mutex); } /** @@ -1635,10 +1636,10 @@ static int sd_remove(struct device *dev) del_gendisk(sdkp->disk); sd_shutdown(dev); - down(&sd_ref_sem); + mutex_lock(&sd_ref_mutex); dev_set_drvdata(dev, NULL); kref_put(&sdkp->kref, scsi_disk_release); - up(&sd_ref_sem); + mutex_unlock(&sd_ref_mutex); return 0; } @@ -1647,7 +1648,7 @@ static int sd_remove(struct device *dev) * scsi_disk_release - Called to free the scsi_disk structure * @kref: pointer to embedded kref * - * sd_ref_sem must be held entering this routine. Because it is + * sd_ref_mutex must be held entering this routine. Because it is * called on last put, you should always use the scsi_disk_get() * scsi_disk_put() helpers which manipulate the semaphore directly * and never do a direct kref_put(). diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index a4d9be7c687..ec73223ad2e 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -90,7 +91,7 @@ static DEFINE_SPINLOCK(sr_index_lock); /* This semaphore is used to mediate the 0->1 reference get in the * face of object destruction (i.e. we can't allow a get on an * object after last put) */ -static DECLARE_MUTEX(sr_ref_sem); +static DEFINE_MUTEX(sr_ref_mutex); static int sr_open(struct cdrom_device_info *, int); static void sr_release(struct cdrom_device_info *); @@ -133,7 +134,7 @@ static inline struct scsi_cd *scsi_cd_get(struct gendisk *disk) { struct scsi_cd *cd = NULL; - down(&sr_ref_sem); + mutex_lock(&sr_ref_mutex); if (disk->private_data == NULL) goto out; cd = scsi_cd(disk); @@ -146,7 +147,7 @@ static inline struct scsi_cd *scsi_cd_get(struct gendisk *disk) kref_put(&cd->kref, sr_kref_release); cd = NULL; out: - up(&sr_ref_sem); + mutex_unlock(&sr_ref_mutex); return cd; } @@ -154,10 +155,10 @@ static inline void scsi_cd_put(struct scsi_cd *cd) { struct scsi_device *sdev = cd->device; - down(&sr_ref_sem); + mutex_lock(&sr_ref_mutex); kref_put(&cd->kref, sr_kref_release); scsi_device_put(sdev); - up(&sr_ref_sem); + mutex_unlock(&sr_ref_mutex); } /* @@ -845,7 +846,7 @@ static int sr_packet(struct cdrom_device_info *cdi, * sr_kref_release - Called to free the scsi_cd structure * @kref: pointer to embedded kref * - * sr_ref_sem must be held entering this routine. Because it is + * sr_ref_mutex must be held entering this routine. Because it is * called on last put, you should always use the scsi_cd_get() * scsi_cd_put() helpers which manipulate the semaphore directly * and never do a direct kref_put(). @@ -874,9 +875,9 @@ static int sr_remove(struct device *dev) del_gendisk(cd->disk); - down(&sr_ref_sem); + mutex_lock(&sr_ref_mutex); kref_put(&cd->kref, sr_kref_release); - up(&sr_ref_sem); + mutex_unlock(&sr_ref_mutex); return 0; } diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index c4aade8f534..6e4a36af58c 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -38,6 +38,7 @@ static const char *verstr = "20050830"; #include #include #include +#include #include #include @@ -220,7 +221,7 @@ static void scsi_tape_release(struct kref *); #define to_scsi_tape(obj) container_of(obj, struct scsi_tape, kref) -static DECLARE_MUTEX(st_ref_sem); +static DEFINE_MUTEX(st_ref_mutex); #include "osst_detect.h" @@ -237,7 +238,7 @@ static struct scsi_tape *scsi_tape_get(int dev) { struct scsi_tape *STp = NULL; - down(&st_ref_sem); + mutex_lock(&st_ref_mutex); write_lock(&st_dev_arr_lock); if (dev < st_dev_max && scsi_tapes != NULL) @@ -259,7 +260,7 @@ out_put: STp = NULL; out: write_unlock(&st_dev_arr_lock); - up(&st_ref_sem); + mutex_unlock(&st_ref_mutex); return STp; } @@ -267,10 +268,10 @@ static void scsi_tape_put(struct scsi_tape *STp) { struct scsi_device *sdev = STp->device; - down(&st_ref_sem); + mutex_lock(&st_ref_mutex); kref_put(&STp->kref, scsi_tape_release); scsi_device_put(sdev); - up(&st_ref_sem); + mutex_unlock(&st_ref_mutex); } struct st_reject_data { @@ -4141,9 +4142,9 @@ static int st_remove(struct device *dev) } } - down(&st_ref_sem); + mutex_lock(&st_ref_mutex); kref_put(&tpnt->kref, scsi_tape_release); - up(&st_ref_sem); + mutex_unlock(&st_ref_mutex); return 0; } } @@ -4156,7 +4157,7 @@ static int st_remove(struct device *dev) * scsi_tape_release - Called to free the Scsi_Tape structure * @kref: pointer to embedded kref * - * st_ref_sem must be held entering this routine. Because it is + * st_ref_mutex must be held entering this routine. Because it is * called on last put, you should always use the scsi_tape_get() * scsi_tape_put() helpers which manipulate the semaphore directly * and never do a direct kref_put(). diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 230bc55c0bf..467274a764d 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -5,6 +5,7 @@ #include #include #include +#include struct block_device; struct completion; @@ -469,7 +470,7 @@ struct Scsi_Host { spinlock_t default_lock; spinlock_t *host_lock; - struct semaphore scan_mutex;/* serialize scanning activity */ + struct mutex scan_mutex;/* serialize scanning activity */ struct list_head eh_cmd_q; struct task_struct * ehandler; /* Error recovery thread. */ -- GitLab From 33b114e935a2202206e224dd2c695cee5a5986bf Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 11 Jan 2006 14:20:43 +0100 Subject: [PATCH 015/465] [SCSI] sas: clear parent->rphy in sas_rphy_delete We need to clear the backpointer on rphy removal, else we'll run into problems with host removal after a device has been hot unplugged. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_sas.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index edabbd05d25..357b52f5f99 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -697,6 +697,8 @@ sas_rphy_delete(struct sas_rphy *rphy) list_del(&rphy->list); spin_unlock(&sas_host->lock); + parent->rphy = NULL; + put_device(&parent->dev); } EXPORT_SYMBOL(sas_rphy_delete); -- GitLab From 6e289a9023d589c24f86b29186d324215cdc9947 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Wed, 11 Jan 2006 09:28:07 -0800 Subject: [PATCH 016/465] [SCSI] aacraid: Fix default FIB size Received from Mark Salyzyn. If the adapter has not instructed us otherwise that it can handle a 'large' FIB, then it can handle at most a 2KB FIB. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/commctrl.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index ef623bd965f..4fe79cd7c95 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c @@ -85,6 +85,10 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg) if (size < le16_to_cpu(kfib->header.SenderSize)) size = le16_to_cpu(kfib->header.SenderSize); if (size > dev->max_fib_size) { + if (size > 2048) { + retval = -EINVAL; + goto cleanup; + } /* Highjack the hw_fib */ hw_fib = fibptr->hw_fib; hw_fib_pa = fibptr->hw_fib_pa; -- GitLab From 7686f132653fa3d52d45c3f021215f714094f1ca Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Wed, 11 Jan 2006 09:28:16 -0800 Subject: [PATCH 017/465] [SCSI] aacraid: better sysfs adapter information Received from Mark Salyzyn. Provide more accurate adapter information. Allows the Adapter Firmware to override the Adapter product information. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/linit.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 9b9062f0246..d183a072a9d 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -574,7 +574,15 @@ static ssize_t aac_show_model(struct class_device *class_dev, struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata; int len; - len = snprintf(buf, PAGE_SIZE, "%s\n", + if (dev->supplement_adapter_info.AdapterTypeText[0]) { + char * cp = dev->supplement_adapter_info.AdapterTypeText; + while (*cp && *cp != ' ') + ++cp; + while (*cp == ' ') + ++cp; + len = snprintf(buf, PAGE_SIZE, "%s\n", cp); + } else + len = snprintf(buf, PAGE_SIZE, "%s\n", aac_drivers[dev->cardtype].model); return len; } @@ -585,7 +593,15 @@ static ssize_t aac_show_vendor(struct class_device *class_dev, struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata; int len; - len = snprintf(buf, PAGE_SIZE, "%s\n", + if (dev->supplement_adapter_info.AdapterTypeText[0]) { + char * cp = dev->supplement_adapter_info.AdapterTypeText; + while (*cp && *cp != ' ') + ++cp; + len = snprintf(buf, PAGE_SIZE, "%.*s\n", + (int)(cp - (char *)dev->supplement_adapter_info.AdapterTypeText), + dev->supplement_adapter_info.AdapterTypeText); + } else + len = snprintf(buf, PAGE_SIZE, "%s\n", aac_drivers[dev->cardtype].vname); return len; } -- GitLab From db39363c029cd9e74661ef059a17785d1c62a851 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Wed, 11 Jan 2006 09:28:29 -0800 Subject: [PATCH 018/465] [SCSI] aacraid: 17 element sg performance update Received From Mark Salyzyn. The Jaguar and Corsair class of adapters (2410, 2810, 2610, 21610, CERC) perform better (about 10% better read performance, write performance neutral) with current Firmware if the OS limits the number of scatter gather elements to 17 per request. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aacraid.h | 7 +++++++ drivers/scsi/aacraid/linit.c | 15 +++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 30fd8d6e3f3..66dbb6d2c50 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -531,6 +531,13 @@ struct aac_driver_ident */ #define AAC_QUIRK_MASTER 0x0008 +/* + * Some adapter firmware perform poorly when it must split up scatter gathers + * in order to deal with the limits of the underlying CHIM. This limit in this + * class of adapters is 17 scatter gather elements. + */ +#define AAC_QUIRK_17SG 0x0010 + /* * The adapter interface specs all queues to be located in the same * physically contigous block. The host structure that defines the diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index d183a072a9d..0bf5f9a943e 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -200,10 +200,10 @@ static struct aac_driver_ident aac_drivers[] = { { aac_rkt_init, "aacraid", "ADAPTEC ", "Callisto ", 2, AAC_QUIRK_MASTER }, /* Jupiter Platform */ { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020SA ", 1 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */ { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2025SA ", 1 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */ - { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2410SA SATA ", 1 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */ - { aac_rx_init, "aacraid", "DELL ", "CERC SR2 ", 1 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */ - { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2810SA SATA ", 1 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */ - { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-21610SA SATA", 1 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2410SA SATA ", 1, AAC_QUIRK_17SG }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */ + { aac_rx_init, "aacraid", "DELL ", "CERC SR2 ", 1, AAC_QUIRK_17SG }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2810SA SATA ", 1, AAC_QUIRK_17SG }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-21610SA SATA", 1, AAC_QUIRK_17SG }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */ { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2026ZCR ", 1 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */ { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2610SA ", 1 }, /* SATA 6Ch (Bearcat) */ { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2240S ", 1 }, /* ASR-2240S (SabreExpress) */ @@ -853,6 +853,13 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, = (aac->scsi_host_ptr->sg_tablesize * 8) + 112; } + if ((aac_drivers[index].quirks & AAC_QUIRK_17SG) && + (aac->scsi_host_ptr->sg_tablesize > 17)) { + aac->scsi_host_ptr->sg_tablesize = 17; + aac->scsi_host_ptr->max_sectors + = (aac->scsi_host_ptr->sg_tablesize * 8) + 112; + } + /* * Firware printf works only with older firmware. */ -- GitLab From 6171b5eff2ef3f84333af652e8c7b0838bf72945 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Wed, 11 Jan 2006 09:28:57 -0800 Subject: [PATCH 019/465] [SCSI] aacraid: README update Received From Mark Salyzyn. Move the README from the driver directory to the Documentation directory. Updated the documentation, added descriptions for cards that were missing. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley --- Documentation/scsi/aacraid.txt | 108 +++++++++++++++++++++++++++++++++ drivers/scsi/aacraid/README | 74 ---------------------- 2 files changed, 108 insertions(+), 74 deletions(-) create mode 100644 Documentation/scsi/aacraid.txt delete mode 100644 drivers/scsi/aacraid/README diff --git a/Documentation/scsi/aacraid.txt b/Documentation/scsi/aacraid.txt new file mode 100644 index 00000000000..820fd079350 --- /dev/null +++ b/Documentation/scsi/aacraid.txt @@ -0,0 +1,108 @@ +AACRAID Driver for Linux (take two) + +Introduction +------------------------- +The aacraid driver adds support for Adaptec (http://www.adaptec.com) +RAID controllers. This is a major rewrite from the original +Adaptec supplied driver. It has signficantly cleaned up both the code +and the running binary size (the module is less than half the size of +the original). + +Supported Cards/Chipsets +------------------------- + PCI ID (pci.ids) OEM Product + 9005:0285:9005:028a Adaptec 2020ZCR (Skyhawk) + 9005:0285:9005:028e Adaptec 2020SA (Skyhawk) + 9005:0285:9005:028b Adaptec 2025ZCR (Terminator) + 9005:0285:9005:028f Adaptec 2025SA (Terminator) + 9005:0285:9005:0286 Adaptec 2120S (Crusader) + 9005:0286:9005:028d Adaptec 2130S (Lancer) + 9005:0285:9005:0285 Adaptec 2200S (Vulcan) + 9005:0285:9005:0287 Adaptec 2200S (Vulcan-2m) + 9005:0286:9005:028c Adaptec 2230S (Lancer) + 9005:0286:9005:028c Adaptec 2230SLP (Lancer) + 9005:0285:9005:0296 Adaptec 2240S (SabreExpress) + 9005:0285:9005:0290 Adaptec 2410SA (Jaguar) + 9005:0285:9005:0293 Adaptec 21610SA (Corsair-16) + 9005:0285:103c:3227 Adaptec 2610SA (Bearcat) + 9005:0285:9005:0292 Adaptec 2810SA (Corsair-8) + 9005:0285:9005:0294 Adaptec Prowler + 9005:0286:9005:029d Adaptec 2420SA (Intruder) + 9005:0286:9005:029c Adaptec 2620SA (Intruder) + 9005:0286:9005:029b Adaptec 2820SA (Intruder) + 9005:0286:9005:02a7 Adaptec 2830SA (Skyray) + 9005:0286:9005:02a8 Adaptec 2430SA (Skyray) + 9005:0285:9005:0288 Adaptec 3230S (Harrier) + 9005:0285:9005:0289 Adaptec 3240S (Tornado) + 9005:0285:9005:0298 Adaptec 4000SAS (BlackBird) + 9005:0285:9005:0297 Adaptec 4005SAS (AvonPark) + 9005:0285:9005:0299 Adaptec 4800SAS (Marauder-X) + 9005:0285:9005:029a Adaptec 4805SAS (Marauder-E) + 9005:0286:9005:02a2 Adaptec 4810SAS (Hurricane) + 1011:0046:9005:0364 Adaptec 5400S (Mustang) + 1011:0046:9005:0365 Adaptec 5400S (Mustang) + 9005:0283:9005:0283 Adaptec Catapult (3210S with arc firmware) + 9005:0284:9005:0284 Adaptec Tomcat (3410S with arc firmware) + 9005:0287:9005:0800 Adaptec Themisto (Jupiter) + 9005:0200:9005:0200 Adaptec Themisto (Jupiter) + 9005:0286:9005:0800 Adaptec Callisto (Jupiter) + 1011:0046:9005:1364 Dell PERC 2/QC (Quad Channel, Mustang) + 1028:0001:1028:0001 Dell PERC 2/Si (Iguana) + 1028:0003:1028:0003 Dell PERC 3/Si (SlimFast) + 1028:0002:1028:0002 Dell PERC 3/Di (Opal) + 1028:0004:1028:0004 Dell PERC 3/DiF (Iguana) + 1028:0002:1028:00d1 Dell PERC 3/DiV (Viper) + 1028:0002:1028:00d9 Dell PERC 3/DiL (Lexus) + 1028:000a:1028:0106 Dell PERC 3/DiJ (Jaguar) + 1028:000a:1028:011b Dell PERC 3/DiD (Dagger) + 1028:000a:1028:0121 Dell PERC 3/DiB (Boxster) + 9005:0285:1028:0287 Dell PERC 320/DC (Vulcan) + 9005:0285:1028:0291 Dell CERC 2 (DellCorsair) + 1011:0046:103c:10c2 HP NetRAID-4M (Mustang) + 9005:0285:17aa:0286 Legend S220 (Crusader) + 9005:0285:17aa:0287 Legend S230 (Vulcan) + 9005:0285:9005:0290 IBM ServeRAID 7t (Jaguar) + 9005:0285:1014:02F2 IBM ServeRAID 8i (AvonPark) + 9005:0285:1014:0312 IBM ServeRAID 8i (AvonParkLite) + 9005:0286:1014:9580 IBM ServeRAID 8k/8k-l8 (Aurora) + 9005:0286:1014:9540 IBM ServeRAID 8k/8k-l4 (AuroraLite) + 9005:0286:9005:029f ICP ICP9014R0 (Lancer) + 9005:0286:9005:029e ICP ICP9024R0 (Lancer) + 9005:0286:9005:02a0 ICP ICP9047MA (Lancer) + 9005:0286:9005:02a1 ICP ICP9087MA (Lancer) + 9005:0286:9005:02a4 ICP ICP9085LI (Marauder-X) + 9005:0286:9005:02a5 ICP ICP5085BR (Marauder-E) + 9005:0286:9005:02a3 ICP ICP5085AU (Hurricane) + 9005:0286:9005:02a6 ICP ICP9067MA (Intruder-6) + 9005:0286:9005:02a9 ICP ICP5087AU (Skyray) + 9005:0286:9005:02aa ICP ICP5047AU (Skyray) + +People +------------------------- +Alan Cox +Christoph Hellwig (updates for new-style PCI probing and SCSI host registration, + small cleanups/fixes) +Matt Domsch (revision ioctl, adapter messages) +Deanna Bonds (non-DASD support, PAE fibs and 64 bit, added new adaptec controllers + added new ioctls, changed scsi interface to use new error handler, + increased the number of fibs and outstanding commands to a container) + + (fixed 64bit and 64G memory model, changed confusing naming convention + where fibs that go to the hardware are consistently called hw_fibs and + not just fibs like the name of the driver tracking structure) +Mark Salyzyn Fixed panic issues and added some new product ids for upcoming hbas. Performance tuning, card failover and bug mitigations. + +Original Driver +------------------------- +Adaptec Unix OEM Product Group + +Mailing List +------------------------- +linux-scsi@vger.kernel.org (Interested parties troll here) +Also note this is very different to Brian's original driver +so don't expect him to support it. +Adaptec does support this driver. Contact Adaptec tech support or +aacraid@adaptec.com + +Original by Brian Boerner February 2001 +Rewritten by Alan Cox, November 2001 diff --git a/drivers/scsi/aacraid/README b/drivers/scsi/aacraid/README deleted file mode 100644 index 4193865d419..00000000000 --- a/drivers/scsi/aacraid/README +++ /dev/null @@ -1,74 +0,0 @@ -AACRAID Driver for Linux (take two) - -Introduction -------------------------- -The aacraid driver adds support for Adaptec (http://www.adaptec.com) -RAID controllers. This is a major rewrite from the original -Adaptec supplied driver. It has signficantly cleaned up both the code -and the running binary size (the module is less than half the size of -the original). - -Supported Cards/Chipsets -------------------------- - Adaptec 2020S - Adaptec 2025S - Adaptec 2120S - Adaptec 2130S - Adaptec 2200S - Adaptec 2230S - Adaptec 2240S - Adaptec 2410SA - Adaptec 2610SA - Adaptec 2810SA - Adaptec 21610SA - Adaptec 3230S - Adaptec 3240S - Adaptec 4000SAS - Adaptec 4005SAS - Adaptec 4800SAS - Adaptec 4805SAS - Adaptec 5400S - Dell PERC 2 Quad Channel - Dell PERC 2/Si - Dell PERC 3/Si - Dell PERC 3/Di - Dell CERC 2 - HP NetRAID-4M - Legend S220 - Legend S230 - IBM ServeRAID 8i - ICP 9014R0 - ICP 9024R0 - ICP 9047MA - ICP 9087MA - ICP 9085LI - ICP 5085AU - -People -------------------------- -Alan Cox -Christoph Hellwig (updates for new-style PCI probing and SCSI host registration, - small cleanups/fixes) -Matt Domsch (revision ioctl, adapter messages) -Deanna Bonds (non-DASD support, PAE fibs and 64 bit, added new adaptec controllers - added new ioctls, changed scsi interface to use new error handler, - increased the number of fibs and outstanding commands to a container) - - (fixed 64bit and 64G memory model, changed confusing naming convention - where fibs that go to the hardware are consistently called hw_fibs and - not just fibs like the name of the driver tracking structure) -Mark Salyzyn Fixed panic issues and added some new product ids for upcoming hbas. Performance tuning, card failover and bug mitigations. - -Original Driver -------------------------- -Adaptec Unix OEM Product Group - -Mailing List -------------------------- -linux-scsi@vger.kernel.org (Interested parties troll here) -Also note this is very different to Brian's original driver -so don't expect him to support it. -Adaptec does support this driver. Contact either tech support or Mark Salyzyn. - -Original by Brian Boerner February 2001 -Rewritten by Alan Cox, November 2001 -- GitLab From bcc1e382bce8de4f26182c6447916f9c82b0fbe5 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert <76306.1226@compuserve.com> Date: Wed, 11 Jan 2006 23:58:40 -0500 Subject: [PATCH 020/465] [SCSI] Mask capabilities for SCSI-1 CD drive SCSI-1 CD drives can't do MRW or be opened for writing, so mask off those capabilities. Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Acked-by: Jens Axboe Signed-off-by: James Bottomley --- drivers/scsi/sr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index ec73223ad2e..18a3b756c63 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -763,8 +763,9 @@ static void get_capabilities(struct scsi_cd *cd) /* failed, drive doesn't have capabilities mode page */ cd->cdi.speed = 1; cd->cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R | - CDC_DVD | CDC_DVD_RAM | - CDC_SELECT_DISC | CDC_SELECT_SPEED); + CDC_DVD | CDC_DVD_RAM | + CDC_SELECT_DISC | CDC_SELECT_SPEED | + CDC_MRW | CDC_MRW_W | CDC_RAM); kfree(buffer); printk("%s: scsi-1 drive\n", cd->cdi.name); return; -- GitLab From 5e46631b04382ef14255467288052f29cb77daeb Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 12 Jan 2006 12:04:28 +0100 Subject: [PATCH 021/465] [SCSI] aic7xxx/aic79xx: New device ids Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic79xx_pci.c | 24 +++++++++++++++--------- drivers/scsi/aic7xxx/aic79xx_pci.h | 5 +++-- drivers/scsi/aic7xxx/aic7xxx_pci.c | 24 +++++++++++++++++++++--- drivers/scsi/aic7xxx/aic7xxx_pci.h | 1 + 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c index 2131db60018..196a6344b03 100644 --- a/drivers/scsi/aic7xxx/aic79xx_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_pci.c @@ -38,9 +38,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#77 $ - * - * $FreeBSD$ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#89 $ */ #ifdef __linux__ @@ -114,6 +112,13 @@ struct ahd_pci_identity ahd_pci_ident_table [] = "Adaptec 29320ALP Ultra320 SCSI adapter", ahd_aic7901_setup }, + /* aic7901A based controllers */ + { + ID_AHA_29320LP, + ID_ALL_MASK, + "Adaptec 29320LP Ultra320 SCSI adapter", + ahd_aic7901A_setup + }, /* aic7902 based controllers */ { ID_AHA_29320, @@ -127,12 +132,6 @@ struct ahd_pci_identity ahd_pci_ident_table [] = "Adaptec 29320B Ultra320 SCSI adapter", ahd_aic7902_setup }, - { - ID_AHA_29320LP, - ID_ALL_MASK, - "Adaptec 29320LP Ultra320 SCSI adapter", - ahd_aic7901A_setup - }, { ID_AHA_39320, ID_ALL_MASK, @@ -145,6 +144,12 @@ struct ahd_pci_identity ahd_pci_ident_table [] = "Adaptec 39320 Ultra320 SCSI adapter", ahd_aic7902_setup }, + { + ID_AHA_39320_B_DELL, + ID_ALL_MASK, + "Adaptec (Dell OEM) 39320 Ultra320 SCSI adapter", + ahd_aic7902_setup + }, { ID_AHA_39320A, ID_ALL_MASK, @@ -668,6 +673,7 @@ ahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control) * Now set the termination based on what we found. */ sxfrctl1 = ahd_inb(ahd, SXFRCTL1) & ~STPWEN; + ahd->flags &= ~AHD_TERM_ENB_A; if ((termctl & FLX_TERMCTL_ENPRILOW) != 0) { ahd->flags |= AHD_TERM_ENB_A; sxfrctl1 |= STPWEN; diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.h b/drivers/scsi/aic7xxx/aic79xx_pci.h index b5cfeabdfec..da45153668c 100644 --- a/drivers/scsi/aic7xxx/aic79xx_pci.h +++ b/drivers/scsi/aic7xxx/aic79xx_pci.h @@ -53,14 +53,15 @@ #define ID_AHA_29320ALP 0x8017900500449005ull #define ID_AIC7901A 0x801E9005FFFF9005ull -#define ID_AHA_29320 0x8012900500429005ull -#define ID_AHA_29320B 0x8013900500439005ull #define ID_AHA_29320LP 0x8014900500449005ull #define ID_AIC7902 0x801F9005FFFF9005ull #define ID_AIC7902_B 0x801D9005FFFF9005ull #define ID_AHA_39320 0x8010900500409005ull +#define ID_AHA_29320 0x8012900500429005ull +#define ID_AHA_29320B 0x8013900500439005ull #define ID_AHA_39320_B 0x8015900500409005ull +#define ID_AHA_39320_B_DELL 0x8015900501681028ull #define ID_AHA_39320A 0x8016900500409005ull #define ID_AHA_39320D 0x8011900500419005ull #define ID_AHA_39320D_B 0x801C900500419005ull diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c index b3b2e2237eb..5f586140e05 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c @@ -39,9 +39,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#69 $ - * - * $FreeBSD$ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#79 $ */ #ifdef __linux__ @@ -393,6 +391,12 @@ struct ahc_pci_identity ahc_pci_ident_table [] = "Adaptec aic7892 Ultra160 SCSI adapter (ARO)", ahc_aic7892_setup }, + { + ID_AHA_2915_30LP, + ID_ALL_MASK, + "Adaptec 2915/30LP Ultra160 SCSI adapter", + ahc_aic7892_setup + }, /* aic7895 based controllers */ { ID_AHA_2940U_DUAL, @@ -1193,9 +1197,19 @@ ahc_pci_test_register_access(struct ahc_softc *ahc) * use for this test. */ hcntrl = ahc_inb(ahc, HCNTRL); + if (hcntrl == 0xFF) goto fail; + if ((hcntrl & CHIPRST) != 0) { + /* + * The chip has not been initialized since + * PCI/EISA/VLB bus reset. Don't trust + * "left over BIOS data". + */ + ahc->flags |= AHC_NO_BIOS_INIT; + } + /* * Next create a situation where write combining * or read prefetching could be initiated by the @@ -1307,6 +1321,10 @@ check_extport(struct ahc_softc *ahc, u_int *sxfrctl1) sd.sd_chip = C56_66; } ahc_release_seeprom(&sd); + + /* Remember the SEEPROM type for later */ + if (sd.sd_chip == C56_66) + ahc->flags |= AHC_LARGE_SEEPROM; } if (!have_seeprom) { diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.h b/drivers/scsi/aic7xxx/aic7xxx_pci.h index be27fcb2034..263f85da405 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_pci.h +++ b/drivers/scsi/aic7xxx/aic7xxx_pci.h @@ -105,6 +105,7 @@ #define ID_AHA_29160C 0x0080900562209005ull #define ID_AHA_29160B 0x00809005E2209005ull #define ID_AHA_19160B 0x0081900562A19005ull +#define ID_AHA_2915_30LP 0x0082900502109005ull #define ID_AIC7896 0x005F9005FFFF9005ull #define ID_AIC7896_ARO 0x00539005FFFF9005ull -- GitLab From 66a0683e4620f087e41e79d4d2be6c5a06bb206b Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 12 Jan 2006 12:05:46 +0100 Subject: [PATCH 022/465] [SCSI] aic79xx: Use struct map_node Use struct map_node instead of separate variables. Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic79xx.h | 27 +++++++++++++-------- drivers/scsi/aic7xxx/aic79xx_core.c | 30 +++++++++++++---------- drivers/scsi/aic7xxx/aic79xx_inline.h | 34 +++++++++++++++++++-------- 3 files changed, 58 insertions(+), 33 deletions(-) diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h index 653fb0b42ae..ac3d07a2a28 100644 --- a/drivers/scsi/aic7xxx/aic79xx.h +++ b/drivers/scsi/aic7xxx/aic79xx.h @@ -37,7 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#95 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#108 $ * * $FreeBSD$ */ @@ -1062,6 +1062,7 @@ struct ahd_softc { struct scb_data scb_data; struct hardware_scb *next_queued_hscb; + struct map_node *next_queued_hscb_map; /* * SCBs that have been sent to the controller @@ -1140,10 +1141,6 @@ struct ahd_softc { ahd_flag flags; struct seeprom_config *seep_config; - /* Values to store in the SEQCTL register for pause and unpause */ - uint8_t unpause; - uint8_t pause; - /* Command Queues */ uint16_t qoutfifonext; uint16_t qoutfifonext_valid_tag; @@ -1151,6 +1148,17 @@ struct ahd_softc { uint16_t qinfifo[AHD_SCB_MAX]; uint16_t *qoutfifo; + /* + * Our qfreeze count. The sequencer compares + * this value with its own counter to determine + * whether to allow selections to occur. + */ + uint16_t qfreeze_cnt; + + /* Values to store in the SEQCTL register for pause and unpause */ + uint8_t unpause; + uint8_t pause; + /* Critical Section Data */ struct cs *critical_sections; u_int num_critical_sections; @@ -1197,8 +1205,7 @@ struct ahd_softc { */ bus_dma_tag_t parent_dmat; bus_dma_tag_t shared_data_dmat; - bus_dmamap_t shared_data_dmamap; - dma_addr_t shared_data_busaddr; + struct map_node shared_data_map; /* Information saved through suspend/resume cycles */ struct ahd_suspend_state suspend_state; @@ -1296,9 +1303,9 @@ struct ahd_devinfo { }; /****************************** PCI Structures ********************************/ -#define AHD_PCI_IOADDR0 PCIR_MAPS /* I/O BAR*/ -#define AHD_PCI_MEMADDR (PCIR_MAPS + 4) /* Memory BAR */ -#define AHD_PCI_IOADDR1 (PCIR_MAPS + 12)/* Second I/O BAR */ +#define AHD_PCI_IOADDR0 PCIR_BAR(0) /* I/O BAR*/ +#define AHD_PCI_MEMADDR PCIR_BAR(1) /* Memory BAR */ +#define AHD_PCI_IOADDR1 PCIR_BAR(3) /* Second I/O BAR */ typedef int (ahd_device_setup_t)(struct ahd_softc *); diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 4e8f00df978..55c44bf5405 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -5203,13 +5203,13 @@ ahd_free(struct ahd_softc *ahd) /* FALLTHROUGH */ case 4: ahd_dmamap_unload(ahd, ahd->shared_data_dmat, - ahd->shared_data_dmamap); + ahd->shared_data_map.dmamap); /* FALLTHROUGH */ case 3: ahd_dmamem_free(ahd, ahd->shared_data_dmat, ahd->qoutfifo, - ahd->shared_data_dmamap); + ahd->shared_data_map.dmamap); ahd_dmamap_destroy(ahd, ahd->shared_data_dmat, - ahd->shared_data_dmamap); + ahd->shared_data_map.dmamap); /* FALLTHROUGH */ case 2: ahd_dma_tag_destroy(ahd, ahd->shared_data_dmat); @@ -6088,7 +6088,6 @@ static const char *termstat_strings[] = { int ahd_init(struct ahd_softc *ahd) { - uint8_t *base_vaddr; uint8_t *next_vaddr; dma_addr_t next_baddr; size_t driver_data_size; @@ -6178,20 +6177,23 @@ ahd_init(struct ahd_softc *ahd) /* Allocation of driver data */ if (ahd_dmamem_alloc(ahd, ahd->shared_data_dmat, - (void **)&base_vaddr, - BUS_DMA_NOWAIT, &ahd->shared_data_dmamap) != 0) { + (void **)&ahd->shared_data_map.vaddr, + BUS_DMA_NOWAIT, + &ahd->shared_data_map.dmamap) != 0) { return (ENOMEM); } ahd->init_level++; /* And permanently map it in */ - ahd_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap, - base_vaddr, driver_data_size, ahd_dmamap_cb, - &ahd->shared_data_busaddr, /*flags*/0); - ahd->qoutfifo = (uint16_t *)base_vaddr; + ahd_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap, + ahd->shared_data_map.vaddr, driver_data_size, + ahd_dmamap_cb, &ahd->shared_data_map.physaddr, + /*flags*/0); + ahd->qoutfifo = (uint16_t *)ahd->shared_data_map.vaddr; next_vaddr = (uint8_t *)&ahd->qoutfifo[AHD_QOUT_SIZE]; - next_baddr = ahd->shared_data_busaddr + AHD_QOUT_SIZE*sizeof(uint16_t); + next_baddr = ahd->shared_data_map.physaddr + + AHD_QOUT_SIZE*sizeof(uint16_t); if ((ahd->features & AHD_TARGETMODE) != 0) { ahd->targetcmds = (struct target_cmd *)next_vaddr; next_vaddr += AHD_TMODE_CMDS * sizeof(struct target_cmd); @@ -6212,6 +6214,7 @@ ahd_init(struct ahd_softc *ahd) * specially from the DMA safe memory chunk used for the QOUTFIFO. */ ahd->next_queued_hscb = (struct hardware_scb *)next_vaddr; + ahd->next_queued_hscb_map = &ahd->shared_data_map; ahd->next_queued_hscb->hscb_busaddr = ahd_htole32(next_baddr); ahd->init_level++; @@ -6557,12 +6560,13 @@ ahd_chip_init(struct ahd_softc *ahd) /* * The Freeze Count is 0. */ + ahd->qfreeze_cnt = 0; ahd_outw(ahd, QFREEZE_COUNT, 0); /* * Tell the sequencer where it can find our arrays in memory. */ - busaddr = ahd->shared_data_busaddr; + busaddr = ahd->shared_data_map.physaddr; ahd_outb(ahd, SHARED_DATA_ADDR, busaddr & 0xFF); ahd_outb(ahd, SHARED_DATA_ADDR + 1, (busaddr >> 8) & 0xFF); ahd_outb(ahd, SHARED_DATA_ADDR + 2, (busaddr >> 16) & 0xFF); @@ -9651,7 +9655,7 @@ ahd_run_tqinfifo(struct ahd_softc *ahd, int paused) cmd->cmd_valid = 0; ahd_dmamap_sync(ahd, ahd->shared_data_dmat, - ahd->shared_data_dmamap, + ahd->shared_data_map.dmamap, ahd_targetcmd_offset(ahd, ahd->tqinfifonext), sizeof(struct target_cmd), BUS_DMASYNC_PREREAD); diff --git a/drivers/scsi/aic7xxx/aic79xx_inline.h b/drivers/scsi/aic7xxx/aic79xx_inline.h index d80bc5161fb..2b7ff989f3d 100644 --- a/drivers/scsi/aic7xxx/aic79xx_inline.h +++ b/drivers/scsi/aic7xxx/aic79xx_inline.h @@ -37,7 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#51 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#58 $ * * $FreeBSD$ */ @@ -522,12 +522,21 @@ do { \ static __inline uint16_t ahd_inw(struct ahd_softc *ahd, u_int port) { + /* + * Read high byte first as some registers increment + * or have other side effects when the low byte is + * read. + */ return ((ahd_inb(ahd, port+1) << 8) | ahd_inb(ahd, port)); } static __inline void ahd_outw(struct ahd_softc *ahd, u_int port, u_int value) { + /* + * Write low byte first to accomodate registers + * such as PRGMCNT where the order maters. + */ ahd_outb(ahd, port, value & 0xFF); ahd_outb(ahd, port+1, (value >> 8) & 0xFF); } @@ -684,7 +693,7 @@ ahd_inb_scbram(struct ahd_softc *ahd, u_int offset) * Razor #528 */ value = ahd_inb(ahd, offset); - if ((ahd->flags & AHD_PCIX_SCBRAM_RD_BUG) != 0) + if ((ahd->bugs & AHD_PCIX_SCBRAM_RD_BUG) != 0) ahd_inb(ahd, MODE_PTR); return (value); } @@ -727,7 +736,8 @@ ahd_lookup_scb(struct ahd_softc *ahd, u_int tag) static __inline void ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb) { - struct hardware_scb *q_hscb; + struct hardware_scb *q_hscb; + struct map_node *q_hscb_map; uint32_t saved_hscb_busaddr; /* @@ -743,6 +753,7 @@ ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb) * locate the correct SCB by SCB_TAG. */ q_hscb = ahd->next_queued_hscb; + q_hscb_map = ahd->next_queued_hscb_map; saved_hscb_busaddr = q_hscb->hscb_busaddr; memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb)); q_hscb->hscb_busaddr = saved_hscb_busaddr; @@ -750,7 +761,9 @@ ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb) /* Now swap HSCB pointers. */ ahd->next_queued_hscb = scb->hscb; + ahd->next_queued_hscb_map = scb->hscb_map; scb->hscb = q_hscb; + scb->hscb_map = q_hscb_map; /* Now define the mapping from tag to SCB in the scbindex */ ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb; @@ -824,8 +837,9 @@ static __inline int ahd_intr(struct ahd_softc *ahd); static __inline void ahd_sync_qoutfifo(struct ahd_softc *ahd, int op) { - ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap, - /*offset*/0, /*len*/AHC_SCB_MAX * sizeof(uint16_t), op); + ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap, + /*offset*/0, + /*len*/AHD_SCB_MAX * sizeof(uint16_t), op); } static __inline void @@ -834,7 +848,7 @@ ahd_sync_tqinfifo(struct ahd_softc *ahd, int op) #ifdef AHD_TARGET_MODE if ((ahd->flags & AHD_TARGETROLE) != 0) { ahd_dmamap_sync(ahd, ahd->shared_data_dmat, - ahd->shared_data_dmamap, + ahd->shared_data_map.dmamap, ahd_targetcmd_offset(ahd, 0), sizeof(struct target_cmd) * AHD_TMODE_CMDS, op); @@ -854,9 +868,9 @@ ahd_check_cmdcmpltqueues(struct ahd_softc *ahd) u_int retval; retval = 0; - ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap, - /*offset*/ahd->qoutfifonext, /*len*/2, - BUS_DMASYNC_POSTREAD); + ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap, + /*offset*/ahd->qoutfifonext * sizeof(*ahd->qoutfifo), + /*len*/sizeof(*ahd->qoutfifo), BUS_DMASYNC_POSTREAD); if ((ahd->qoutfifo[ahd->qoutfifonext] & QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag) retval |= AHD_RUN_QOUTFIFO; @@ -864,7 +878,7 @@ ahd_check_cmdcmpltqueues(struct ahd_softc *ahd) if ((ahd->flags & AHD_TARGETROLE) != 0 && (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) { ahd_dmamap_sync(ahd, ahd->shared_data_dmat, - ahd->shared_data_dmamap, + ahd->shared_data_map.dmamap, ahd_targetcmd_offset(ahd, ahd->tqinfifofnext), /*len*/sizeof(struct target_cmd), BUS_DMASYNC_POSTREAD); -- GitLab From ba62cd2d01e401faa5d5a25fa8e990d0b1a1996a Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 12 Jan 2006 12:07:02 +0100 Subject: [PATCH 023/465] [SCSI] aic79xx: Sanitize inb/outb handling This patch coalesces inb/outb calls to the approriate word or long form. Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic79xx_core.c | 80 ++++++++--------------------- 1 file changed, 21 insertions(+), 59 deletions(-) diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 55c44bf5405..35b51e1979f 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -387,8 +387,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) u_int fifo_mode; u_int i; - scbid = (ahd_inb(ahd, GSFIFO+1) << 8) - | ahd_inb(ahd, GSFIFO); + scbid = ahd_inw(ahd, GSFIFO); scb = ahd_lookup_scb(ahd, scbid); if (scb == NULL) { printf("%s: Warning - GSFIFO SCB %d invalid\n", @@ -748,7 +747,7 @@ ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb) * Advertise the segment to the hardware. */ dfcntrl = ahd_inb(ahd, DFCNTRL)|PRELOADEN|HDMAEN; - if ((ahd->features & AHD_NEW_DFCNTRL_OPTS)!=0) { + if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0) { /* * Use SCSIENWRDIS so that SCSIEN * is never modified by this @@ -1060,7 +1059,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) ahd_outb(ahd, SAVED_LUN, 0); ahd_outb(ahd, SEQ_FLAGS, 0); ahd_assert_atn(ahd); - scb->flags &= ~(SCB_PACKETIZED); + scb->flags &= ~SCB_PACKETIZED; scb->flags |= SCB_ABORT|SCB_CMDPHASE_ABORT; ahd_freeze_devq(ahd, scb); ahd_set_transaction_status(scb, CAM_REQUEUE_REQ); @@ -2310,8 +2309,7 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) "PRGMCNT == 0x%x\n", ahd_lookup_phase_entry(lastphase)->phasemsg, aborted, - ahd_inb(ahd, PRGMCNT) - | (ahd_inb(ahd, PRGMCNT+1) << 8)); + ahd_inw(ahd, PRGMCNT)); ahd_dump_card_state(ahd); } /* Always restart the sequencer. */ @@ -2474,8 +2472,7 @@ ahd_clear_critical_section(struct ahd_softc *ahd) u_int i; ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - seqaddr = ahd_inb(ahd, CURADDR) - | (ahd_inb(ahd, CURADDR+1) << 8); + seqaddr = ahd_inw(ahd, CURADDR); cs = ahd->critical_sections; for (i = 0; i < ahd->num_critical_sections; i++, cs++) { @@ -4909,10 +4906,7 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd) * Determine initial values for data_addr and data_cnt * for resuming the data phase. */ - sgptr = (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 3) << 24) - | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 2) << 16) - | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 1) << 8) - | ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR); + sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR); sgptr &= SG_PTR_MASK; resid = (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT + 2) << 16) @@ -4930,10 +4924,7 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd) dataptr = ahd_le64toh(sg->addr) + (ahd_le32toh(sg->len) & AHD_SG_LEN_MASK) - resid; - ahd_outb(ahd, HADDR + 7, dataptr >> 56); - ahd_outb(ahd, HADDR + 6, dataptr >> 48); - ahd_outb(ahd, HADDR + 5, dataptr >> 40); - ahd_outb(ahd, HADDR + 4, dataptr >> 32); + ahd_outl(ahd, HADDR + 4, dataptr >> 32); } else { struct ahd_dma_seg *sg; @@ -4948,10 +4939,7 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd) ahd_outb(ahd, HADDR + 4, (ahd_le32toh(sg->len) & ~AHD_SG_LEN_MASK) >> 24); } - ahd_outb(ahd, HADDR + 3, dataptr >> 24); - ahd_outb(ahd, HADDR + 2, dataptr >> 16); - ahd_outb(ahd, HADDR + 1, dataptr >> 8); - ahd_outb(ahd, HADDR, dataptr); + ahd_outl(ahd, HADDR, dataptr); ahd_outb(ahd, HCNT + 2, resid >> 16); ahd_outb(ahd, HCNT + 1, resid >> 8); ahd_outb(ahd, HCNT, resid); @@ -6567,14 +6555,8 @@ ahd_chip_init(struct ahd_softc *ahd) * Tell the sequencer where it can find our arrays in memory. */ busaddr = ahd->shared_data_map.physaddr; - ahd_outb(ahd, SHARED_DATA_ADDR, busaddr & 0xFF); - ahd_outb(ahd, SHARED_DATA_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, SHARED_DATA_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, SHARED_DATA_ADDR + 3, (busaddr >> 24) & 0xFF); - ahd_outb(ahd, QOUTFIFO_NEXT_ADDR, busaddr & 0xFF); - ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 3, (busaddr >> 24) & 0xFF); + ahd_outl(ahd, SHARED_DATA_ADDR, busaddr); + ahd_outl(ahd, QOUTFIFO_NEXT_ADDR, busaddr); /* * Setup the allowed SCSI Sequences based on operational mode. @@ -6623,10 +6605,7 @@ ahd_chip_init(struct ahd_softc *ahd) * Tell the sequencer which SCB will be the next one it receives. */ busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF); + ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr); /* * Default to coalescing disabled. @@ -7159,10 +7138,7 @@ ahd_qinfifo_requeue(struct ahd_softc *ahd, struct scb *prev_scb, uint32_t busaddr; busaddr = ahd_le32toh(scb->hscb->hscb_busaddr); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF); + ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr); } else { prev_scb->hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr; ahd_sync_scb(ahd, prev_scb, @@ -7269,10 +7245,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, */ ahd->qinfifonext = qinstart; busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF); + ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr); while (qinpos != qintail) { scb = ahd_lookup_scb(ahd, ahd->qinfifo[qinpos]); @@ -7743,7 +7716,7 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset) */ ahd_clear_msg_state(ahd); ahd_outb(ahd, SIMODE1, - ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST|ENBUSFREE)); + ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST)); if (initiate_reset) ahd_reset_current_bus(ahd); @@ -8321,8 +8294,7 @@ ahd_dumpseq(struct ahd_softc* ahd) max_prog = 2048; ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM); - ahd_outb(ahd, PRGMCNT, 0); - ahd_outb(ahd, PRGMCNT+1, 0); + ahd_outw(ahd, PRGMCNT, 0); for (i = 0; i < max_prog; i++) { uint8_t ins_bytes[4]; @@ -8437,8 +8409,7 @@ ahd_loadseq(struct ahd_softc *ahd) downloaded = 0; skip_addr = 0; ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM); - ahd_outb(ahd, PRGMCNT, 0); - ahd_outb(ahd, PRGMCNT+1, 0); + ahd_outw(ahd, PRGMCNT, 0); for (i = 0; i < sizeof(seqprog)/4; i++) { if (ahd_check_patch(ahd, &cur_patch, i, &skip_addr) == 0) { @@ -8731,7 +8702,7 @@ ahd_dump_card_state(struct ahd_softc *ahd) printf(">>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<\n" "%s: Dumping Card State at program address 0x%x Mode 0x%x\n", ahd_name(ahd), - ahd_inb(ahd, CURADDR) | (ahd_inb(ahd, CURADDR+1) << 8), + ahd_inw(ahd, CURADDR), ahd_build_mode_state(ahd, ahd->saved_src_mode, ahd->saved_dst_mode)); if (paused) @@ -9427,13 +9398,9 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) if ((ahd->features & AHD_MULTI_TID) != 0) { u_int targid_mask; - targid_mask = ahd_inb(ahd, TARGID) - | (ahd_inb(ahd, TARGID + 1) << 8); - + targid_mask = ahd_inw(ahd, TARGID); targid_mask |= target_mask; - ahd_outb(ahd, TARGID, targid_mask); - ahd_outb(ahd, TARGID+1, (targid_mask >> 8)); - + ahd_outw(ahd, TARGID, targid_mask); ahd_update_scsiid(ahd, targid_mask); } else { u_int our_id; @@ -9547,14 +9514,9 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) if (ahd->features & AHD_MULTI_TID) { u_int targid_mask; - targid_mask = ahd_inb(ahd, TARGID) - | (ahd_inb(ahd, TARGID + 1) - << 8); - + targid_mask = ahd_inw(ahd, TARGID); targid_mask &= ~target_mask; - ahd_outb(ahd, TARGID, targid_mask); - ahd_outb(ahd, TARGID+1, - (targid_mask >> 8)); + ahd_outw(ahd, TARGID, targid_mask); ahd_update_scsiid(ahd, targid_mask); } } -- GitLab From 11668bb673c41ec169a85d0b52c538a1c11d29e1 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 12 Jan 2006 12:08:06 +0100 Subject: [PATCH 024/465] [SCSI] aic79xx: Sequencer update Update sequencer code to Adaptec version 2.0.12-6.3.9. Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic79xx.h | 12 +- drivers/scsi/aic7xxx/aic79xx.reg | 60 +- drivers/scsi/aic7xxx/aic79xx.seq | 241 +++- drivers/scsi/aic7xxx/aic79xx_core.c | 665 +++++---- drivers/scsi/aic7xxx/aic79xx_inline.h | 6 +- drivers/scsi/aic7xxx/aic79xx_osm.c | 62 +- drivers/scsi/aic7xxx/aic79xx_reg.h_shipped | 646 +++++---- .../scsi/aic7xxx/aic79xx_reg_print.c_shipped | 507 +++---- drivers/scsi/aic7xxx/aic79xx_seq.h_shipped | 1250 +++++++++-------- 9 files changed, 1911 insertions(+), 1538 deletions(-) diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h index ac3d07a2a28..2cfdbef447d 100644 --- a/drivers/scsi/aic7xxx/aic79xx.h +++ b/drivers/scsi/aic7xxx/aic79xx.h @@ -75,8 +75,7 @@ struct scb_platform_data; #define INITIATOR_WILDCARD (~0) #define SCB_LIST_NULL 0xFF00 #define SCB_LIST_NULL_LE (ahd_htole16(SCB_LIST_NULL)) -#define QOUTFIFO_ENTRY_VALID 0x8000 -#define QOUTFIFO_ENTRY_VALID_LE (ahd_htole16(0x8000)) +#define QOUTFIFO_ENTRY_VALID 0x80 #define SCBID_IS_NULL(scbid) (((scbid) & 0xFF00 ) == SCB_LIST_NULL) #define SCSIID_TARGET(ahd, scsiid) \ @@ -1053,6 +1052,13 @@ typedef uint8_t ahd_mode_state; typedef void ahd_callback_t (void *); +struct ahd_completion +{ + uint16_t tag; + uint8_t sg_status; + uint8_t valid_tag; +}; + struct ahd_softc { bus_space_tag_t tags[2]; bus_space_handle_t bshs[2]; @@ -1142,11 +1148,11 @@ struct ahd_softc { struct seeprom_config *seep_config; /* Command Queues */ + struct ahd_completion *qoutfifo; uint16_t qoutfifonext; uint16_t qoutfifonext_valid_tag; uint16_t qinfifonext; uint16_t qinfifo[AHD_SCB_MAX]; - uint16_t *qoutfifo; /* * Our qfreeze count. The sequencer compares diff --git a/drivers/scsi/aic7xxx/aic79xx.reg b/drivers/scsi/aic7xxx/aic79xx.reg index cca58edc864..3a3204703b1 100644 --- a/drivers/scsi/aic7xxx/aic79xx.reg +++ b/drivers/scsi/aic7xxx/aic79xx.reg @@ -39,7 +39,7 @@ * * $FreeBSD$ */ -VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $" +VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $" /* * This file is processed by the aic7xxx_asm utility for use in assembling @@ -65,13 +65,6 @@ VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $" mvi MODE_PTR, MK_MODE(src, dst); \ } -#define TOGGLE_DFF_MODE \ - if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { \ - call toggle_dff_mode_work_around; \ - } else { \ - xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); \ - } - #define RESTORE_MODE(mode) \ if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { \ mov mode call set_mode_work_around; \ @@ -1199,7 +1192,7 @@ register TARGPCISTAT { /* * LQ Packet In - * The last LQ Packet received + * The last LQ Packet recieved */ register LQIN { address 0x020 @@ -3542,10 +3535,34 @@ scratch_ram { COMPLETE_DMA_SCB_HEAD { size 2 } - /* Counting semaphore to prevent new select-outs */ + /* + * tail of list of SCBs that have + * completed but need to be uploaded + * to the host prior to being completed. + */ + COMPLETE_DMA_SCB_TAIL { + size 2 + } + /* + * head of list of SCBs that have + * been uploaded to the host, but cannot + * be completed until the QFREEZE is in + * full effect (i.e. no selections pending). + */ + COMPLETE_ON_QFREEZE_HEAD { + size 2 + } + /* + * Counting semaphore to prevent new select-outs + * The queue is frozen so long as the sequencer + * and kernel freeze counts differ. + */ QFREEZE_COUNT { size 2 } + KERNEL_QFREEZE_COUNT { + size 2 + } /* * Mode to restore on legacy idle loop exit. */ @@ -3624,6 +3641,17 @@ scratch_ram { QOUTFIFO_ENTRY_VALID_TAG { size 1 } + /* + * Kernel and sequencer offsets into the queue of + * incoming target mode command descriptors. The + * queue is full when the KERNEL_TQINPOS == TQINPOS. + */ + KERNEL_TQINPOS { + size 1 + } + TQINPOS { + size 1 + } /* * Base address of our shared data with the kernel driver in host * memory. This includes the qoutfifo and target mode @@ -3639,17 +3667,6 @@ scratch_ram { QOUTFIFO_NEXT_ADDR { size 4 } - /* - * Kernel and sequencer offsets into the queue of - * incoming target mode command descriptors. The - * queue is full when the KERNEL_TQINPOS == TQINPOS. - */ - KERNEL_TQINPOS { - size 1 - } - TQINPOS { - size 1 - } ARG_1 { size 1 mask SEND_MSG 0x80 @@ -3951,6 +3968,7 @@ const SG_PREFETCH_ADDR_MASK download const SG_SIZEOF download const PKT_OVERRUN_BUFOFFSET download const SCB_TRANSFER_SIZE download +const CACHELINE_MASK download /* * BIOS SCB offsets diff --git a/drivers/scsi/aic7xxx/aic79xx.seq b/drivers/scsi/aic7xxx/aic79xx.seq index 65339bc1ca9..bef1f9d369b 100644 --- a/drivers/scsi/aic7xxx/aic79xx.seq +++ b/drivers/scsi/aic7xxx/aic79xx.seq @@ -40,7 +40,7 @@ * $FreeBSD$ */ -VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#99 $" +VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $" PATCH_ARG_LIST = "struct ahd_softc *ahd" PREFIX = "ahd_" @@ -68,13 +68,47 @@ no_error_set: } SET_MODE(M_SCSI, M_SCSI) test SCSISEQ0, ENSELO|ENARBO jnz idle_loop_checkbus; - test SEQ_FLAGS2, SELECTOUT_QFROZEN jnz idle_loop_checkbus; + test SEQ_FLAGS2, SELECTOUT_QFROZEN jz check_waiting_list; + /* + * If the kernel has caught up with us, thaw the queue. + */ + mov A, KERNEL_QFREEZE_COUNT; + cmp QFREEZE_COUNT, A jne check_frozen_completions; + mov A, KERNEL_QFREEZE_COUNT[1]; + cmp QFREEZE_COUNT[1], A jne check_frozen_completions; + and SEQ_FLAGS2, ~SELECTOUT_QFROZEN; + jmp check_waiting_list; +check_frozen_completions: + test SSTAT0, SELDO|SELINGO jnz idle_loop_checkbus; +BEGIN_CRITICAL; + /* + * If we have completions stalled waiting for the qfreeze + * to take effect, move them over to the complete_scb list + * now that no selections are pending. + */ + cmp COMPLETE_ON_QFREEZE_HEAD[1],SCB_LIST_NULL je idle_loop_checkbus; + /* + * Find the end of the qfreeze list. The first element has + * to be treated specially. + */ + bmov SCBPTR, COMPLETE_ON_QFREEZE_HEAD, 2; + cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je join_lists; + /* + * Now the normal loop. + */ + bmov SCBPTR, SCB_NEXT_COMPLETE, 2; + cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL jne . - 1; +join_lists: + bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; + bmov COMPLETE_SCB_HEAD, COMPLETE_ON_QFREEZE_HEAD, 2; + mvi COMPLETE_ON_QFREEZE_HEAD[1], SCB_LIST_NULL; + jmp idle_loop_checkbus; +check_waiting_list: cmp WAITING_TID_HEAD[1], SCB_LIST_NULL je idle_loop_checkbus; /* * ENSELO is cleared by a SELDO, so we must test for SELDO * one last time. */ -BEGIN_CRITICAL; test SSTAT0, SELDO jnz select_out; END_CRITICAL; call start_selection; @@ -90,6 +124,13 @@ idle_loop_check_nonpackreq: test SSTAT2, NONPACKREQ jz . + 2; call unexpected_nonpkt_phase_find_ctxt; if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) { + /* + * On Rev A. hardware, the busy LED is only + * turned on automaically during selections + * and re-selections. Make the LED status + * more useful by forcing it to be on so + * long as one of our data FIFOs is active. + */ and A, FIFO0FREE|FIFO1FREE, DFFSTAT; cmp A, FIFO0FREE|FIFO1FREE jne . + 3; and SBLKCTL, ~DIAGLEDEN|DIAGLEDON; @@ -101,9 +142,9 @@ idle_loop_check_nonpackreq: call idle_loop_cchan; jmp idle_loop; -BEGIN_CRITICAL; idle_loop_gsfifo: SET_MODE(M_SCSI, M_SCSI) +BEGIN_CRITICAL; idle_loop_gsfifo_in_scsi_mode: test LQISTAT2, LQIGSAVAIL jz return; /* @@ -152,11 +193,15 @@ END_CRITICAL; idle_loop_service_fifos: SET_MODE(M_DFF0, M_DFF0) +BEGIN_CRITICAL; test LONGJMP_ADDR[1], INVALID_ADDR jnz idle_loop_next_fifo; call longjmp; +END_CRITICAL; idle_loop_next_fifo: SET_MODE(M_DFF1, M_DFF1) +BEGIN_CRITICAL; test LONGJMP_ADDR[1], INVALID_ADDR jz longjmp; +END_CRITICAL; return: ret; @@ -170,7 +215,6 @@ BEGIN_CRITICAL; test CCSCBCTL, CCARREN|CCSCBEN jz scbdma_idle; test CCSCBCTL, CCSCBDIR jnz fetch_new_scb_inprog; test CCSCBCTL, CCSCBDONE jz return; -END_CRITICAL; /* FALLTHROUGH */ scbdma_tohost_done: test CCSCBCTL, CCARREN jz fill_qoutfifo_dmadone; @@ -180,26 +224,18 @@ scbdma_tohost_done: * bad SCSI status (currently only for underruns), we * queue the SCB for normal completion. Otherwise, we * wait until any select-out activity has halted, and - * then notify the host so that the transaction can be - * dealt with. + * then queue the completion. */ - test SCB_SCSI_STATUS, 0xff jnz scbdma_notify_host; and CCSCBCTL, ~(CCARREN|CCSCBEN); bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2; + cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL jne . + 2; + mvi COMPLETE_DMA_SCB_TAIL[1], SCB_LIST_NULL; + test SCB_SCSI_STATUS, 0xff jz scbdma_queue_completion; + bmov SCB_NEXT_COMPLETE, COMPLETE_ON_QFREEZE_HEAD, 2; + bmov COMPLETE_ON_QFREEZE_HEAD, SCBPTR, 2 ret; +scbdma_queue_completion: bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret; -scbdma_notify_host: - SET_MODE(M_SCSI, M_SCSI) - test SCSISEQ0, ENSELO jnz return; - test SSTAT0, (SELDO|SELINGO) jnz return; - SET_MODE(M_CCHAN, M_CCHAN) - /* - * Remove SCB and notify host. - */ - and CCSCBCTL, ~(CCARREN|CCSCBEN); - bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2; - SET_SEQINTCODE(BAD_SCB_STATUS) - ret; fill_qoutfifo_dmadone: and CCSCBCTL, ~(CCARREN|CCSCBEN); call qoutfifo_updated; @@ -208,6 +244,7 @@ fill_qoutfifo_dmadone: test QOFF_CTLSTA, SDSCB_ROLLOVR jz return; bmov QOUTFIFO_NEXT_ADDR, SHARED_DATA_ADDR, 4; xor QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID_TOGGLE ret; +END_CRITICAL; qoutfifo_updated: /* @@ -324,14 +361,15 @@ fill_qoutfifo: * Keep track of the SCBs we are dmaing just * in case the DMA fails or is aborted. */ - mov A, QOUTFIFO_ENTRY_VALID_TAG; bmov COMPLETE_SCB_DMAINPROG_HEAD, COMPLETE_SCB_HEAD, 2; mvi CCSCBCTL, CCSCBRESET; bmov SCBHADDR, QOUTFIFO_NEXT_ADDR, 4; + mov A, QOUTFIFO_NEXT_ADDR; bmov SCBPTR, COMPLETE_SCB_HEAD, 2; fill_qoutfifo_loop: - mov CCSCBRAM, SCBPTR; - or CCSCBRAM, A, SCBPTR[1]; + bmov CCSCBRAM, SCBPTR, 2; + mov CCSCBRAM, SCB_SGPTR[0]; + mov CCSCBRAM, QOUTFIFO_ENTRY_VALID_TAG; mov NONE, SDSCB_QOFF; inc INT_COALESCING_CMDCOUNT; add CMDS_PENDING, -1; @@ -339,6 +377,18 @@ fill_qoutfifo_loop: cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je fill_qoutfifo_done; cmp CCSCBADDR, CCSCBADDR_MAX je fill_qoutfifo_done; test QOFF_CTLSTA, SDSCB_ROLLOVR jnz fill_qoutfifo_done; + /* + * Don't cross an ADB or Cachline boundary when DMA'ing + * completion entries. In PCI mode, at least in 32/33 + * configurations, the SCB DMA engine may lose its place + * in the data-stream should the target force a retry on + * something other than an 8byte aligned boundary. In + * PCI-X mode, we do this to avoid split transactions since + * many chipsets seem to be unable to format proper split + * completions to continue the data transfer. + */ + add SINDEX, A, CCSCBADDR; + test SINDEX, CACHELINE_MASK jz fill_qoutfifo_done; bmov SCBPTR, SCB_NEXT_COMPLETE, 2; jmp fill_qoutfifo_loop; fill_qoutfifo_done: @@ -354,7 +404,6 @@ dma_complete_scb: bmov SCBPTR, COMPLETE_DMA_SCB_HEAD, 2; bmov SCBHADDR, SCB_BUSADDR, 4; mvi CCARREN|CCSCBEN|CCSCBRESET jmp dma_scb; -END_CRITICAL; /* * Either post or fetch an SCB from host memory. The caller @@ -371,9 +420,19 @@ dma_scb: mvi SCBHCNT, SCB_TRANSFER_SIZE; mov CCSCBCTL, SINDEX ret; -BEGIN_CRITICAL; setjmp: - bmov LONGJMP_ADDR, STACK, 2 ret; + /* + * At least on the A, a return in the same + * instruction as the bmov results in a return + * to the caller, not to the new address at the + * top of the stack. Since we want the latter + * (we use setjmp to register a handler from an + * interrupt context but not invoke that handler + * until we return to our idle loop), use a + * separate ret instruction. + */ + bmov LONGJMP_ADDR, STACK, 2; + ret; setjmp_inline: bmov LONGJMP_ADDR, STACK, 2; longjmp: @@ -392,11 +451,6 @@ set_mode_work_around: mvi SEQINTCTL, INTVEC1DSL; mov MODE_PTR, SINDEX; clr SEQINTCTL ret; - -toggle_dff_mode_work_around: - mvi SEQINTCTL, INTVEC1DSL; - xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); - clr SEQINTCTL ret; } @@ -490,6 +544,21 @@ allocate_fifo1: SET_SRC_MODE M_SCSI; SET_DST_MODE M_SCSI; select_in: + if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) { + /* + * On Rev A. hardware, the busy LED is only + * turned on automaically during selections + * and re-selections. Make the LED status + * more useful by forcing it to be on from + * the point of selection until our idle + * loop determines that neither of our FIFOs + * are busy. This handles the non-packetized + * case nicely as we will not return to the + * idle loop until the busfree at the end of + * each transaction. + */ + or SBLKCTL, DIAGLEDEN|DIAGLEDON; + } if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) { /* * Test to ensure that the bus has not @@ -528,6 +597,21 @@ SET_SRC_MODE M_SCSI; SET_DST_MODE M_SCSI; select_out: BEGIN_CRITICAL; + if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) { + /* + * On Rev A. hardware, the busy LED is only + * turned on automaically during selections + * and re-selections. Make the LED status + * more useful by forcing it to be on from + * the point of re-selection until our idle + * loop determines that neither of our FIFOs + * are busy. This handles the non-packetized + * case nicely as we will not return to the + * idle loop until the busfree at the end of + * each transaction. + */ + or SBLKCTL, DIAGLEDEN|DIAGLEDON; + } /* Clear out all SCBs that have been successfully sent. */ if ((ahd->bugs & AHD_SENT_SCB_UPDATE_BUG) != 0) { /* @@ -1000,15 +1084,9 @@ not_found_ITloop: /* * We received a "command complete" message. Put the SCB on the complete * queue and trigger a completion interrupt via the idle loop. Before doing - * so, check to see if there - * is a residual or the status byte is something other than STATUS_GOOD (0). - * In either of these conditions, we upload the SCB back to the host so it can - * process this information. In the case of a non zero status byte, we - * additionally interrupt the kernel driver synchronously, allowing it to - * decide if sense should be retrieved. If the kernel driver wishes to request - * sense, it will fill the kernel SCB with a request sense command, requeue - * it to the QINFIFO and tell us not to post to the QOUTFIFO by setting - * RETURN_1 to SEND_SENSE. + * so, check to see if there is a residual or the status byte is something + * other than STATUS_GOOD (0). In either of these conditions, we upload the + * SCB back to the host so it can process this information. */ mesgin_complete: @@ -1053,6 +1131,7 @@ complete_nomsg: call queue_scb_completion; jmp await_busfree; +BEGIN_CRITICAL; freeze_queue: /* Cancel any pending select-out. */ test SSTAT0, SELDO|SELINGO jnz . + 2; @@ -1063,6 +1142,7 @@ freeze_queue: adc QFREEZE_COUNT[1], A; or SEQ_FLAGS2, SELECTOUT_QFROZEN; mov A, ACCUM_SAVE ret; +END_CRITICAL; /* * Complete the current FIFO's SCB if data for this same @@ -1085,8 +1165,10 @@ queue_scb_completion: test SCB_SGPTR, SG_FULL_RESID jnz upload_scb;/* Never xfered */ test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jz upload_scb; complete: +BEGIN_CRITICAL; bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret; +END_CRITICAL; bad_status: cmp SCB_SCSI_STATUS, STATUS_PKT_SENSE je upload_scb; call freeze_queue; @@ -1097,9 +1179,18 @@ upload_scb: * it on the host. */ bmov SCB_TAG, SCBPTR, 2; - bmov SCB_NEXT_COMPLETE, COMPLETE_DMA_SCB_HEAD, 2; +BEGIN_CRITICAL; + or SCB_SGPTR, SG_STATUS_VALID; + mvi SCB_NEXT_COMPLETE[1], SCB_LIST_NULL; + cmp COMPLETE_DMA_SCB_HEAD[1], SCB_LIST_NULL jne add_dma_scb_tail; bmov COMPLETE_DMA_SCB_HEAD, SCBPTR, 2; - or SCB_SGPTR, SG_STATUS_VALID ret; + bmov COMPLETE_DMA_SCB_TAIL, SCBPTR, 2 ret; +add_dma_scb_tail: + bmov REG0, SCBPTR, 2; + bmov SCBPTR, COMPLETE_DMA_SCB_TAIL, 2; + bmov SCB_NEXT_COMPLETE, REG0, 2; + bmov COMPLETE_DMA_SCB_TAIL, REG0, 2 ret; +END_CRITICAL; /* * Is it a disconnect message? Set a flag in the SCB to remind us @@ -1146,8 +1237,18 @@ SET_DST_MODE M_DFF1; await_busfree_clrchn: mvi DFFSXFRCTL, CLRCHN; await_busfree_not_m_dff: - call clear_target_state; + /* clear target specific flags */ + mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT; test SSTAT1,REQINIT|BUSFREE jz .; + /* + * We only set BUSFREE status once either a new + * phase has been detected or we are really + * BUSFREE. This allows the driver to know + * that we are active on the bus even though + * no identified transaction exists should a + * timeout occur while awaiting busfree. + */ + mvi LASTPHASE, P_BUSFREE; test SSTAT1, BUSFREE jnz idle_loop; SET_SEQINTCODE(MISSED_BUSFREE) @@ -1202,11 +1303,6 @@ msgin_rdptrs_get_fifo: call allocate_fifo; jmp mesgin_done; -clear_target_state: - mvi LASTPHASE, P_BUSFREE; - /* clear target specific flags */ - mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT ret; - phase_lock: if ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0) { /* @@ -1297,6 +1393,47 @@ service_fifo: /* Are we actively fetching segments? */ test CCSGCTL, CCSGENACK jnz return; + /* + * Should the other FIFO get the S/G cache first? If + * both FIFOs have been allocated since we last checked + * any FIFO, it is important that we service a FIFO + * that is not actively on the bus first. This guarantees + * that a FIFO will be freed to handle snapshot requests for + * any FIFO that is still on the bus. Chips with RTI do not + * perform snapshots, so don't bother with this test there. + */ + if ((ahd->features & AHD_RTI) == 0) { + /* + * If we're not still receiving SCSI data, + * it is safe to allocate the S/G cache to + * this FIFO. + */ + test DFCNTRL, SCSIEN jz idle_sgfetch_start; + + /* + * Switch to the other FIFO. Non-RTI chips + * also have the "set mode" bug, so we must + * disable interrupts during the switch. + */ + mvi SEQINTCTL, INTVEC1DSL; + xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); + + /* + * If the other FIFO needs loading, then it + * must not have claimed the S/G cache yet + * (SG_CACHE_AVAIL would have been cleared in + * the orginal FIFO mode and we test this above). + * Return to the idle loop so we can process the + * FIFO not currently on the bus first. + */ + test SG_STATE, LOADING_NEEDED jz idle_sgfetch_okay; + clr SEQINTCTL ret; +idle_sgfetch_okay: + xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); + clr SEQINTCTL; + } + +idle_sgfetch_start: /* * We fetch a "cacheline aligned" and sized amount of data * so we don't end up referencing a non-existant page. @@ -1308,7 +1445,7 @@ service_fifo: mvi SGHCNT, SG_PREFETCH_CNT; if ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0) { /* - * Need two instruction between "touches" of SGHADDR. + * Need two instructions between "touches" of SGHADDR. */ nop; } @@ -1658,7 +1795,7 @@ export seq_isr: * savepointer in the current FIFO. We do this so that * a pending CTXTDONE or SAVEPTR is visible in the active * FIFO. This status is the only way we can detect if we - * have lost the race (e.g. host paused us) and our attepts + * have lost the race (e.g. host paused us) and our attempts * to disable the channel occurred after all REQs were * already seen and acked (REQINIT never comes true). */ @@ -1667,7 +1804,7 @@ export seq_isr: test DFCNTRL, DIRECTION jz interrupt_return; and DFCNTRL, ~SCSIEN; snapshot_wait_data_valid: - test SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz snapshot_data_valid; + test SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz interrupt_return; test SSTAT1, REQINIT jz snapshot_wait_data_valid; snapshot_data_valid: or DFCNTRL, SCSIEN; @@ -1834,7 +1971,6 @@ pkt_saveptrs_check_status: dec SCB_FIFO_USE_COUNT; test SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle; mvi DFFSXFRCTL, CLRCHN ret; -END_CRITICAL; /* * LAST_SEG_DONE status has been seen in the current FIFO. @@ -1843,7 +1979,6 @@ END_CRITICAL; * Check for overrun and see if we can complete this command. */ pkt_last_seg_done: -BEGIN_CRITICAL; /* * Mark transfer as completed. */ diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 35b51e1979f..db8f5ce99ee 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -37,9 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#202 $ - * - * $FreeBSD$ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#247 $ */ #ifdef __linux__ @@ -332,6 +330,14 @@ ahd_restart(struct ahd_softc *ahd) ahd_outb(ahd, SCSISEQ1, ahd_inb(ahd, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP)); ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN); + + /* + * Clear any pending sequencer interrupt. It is no + * longer relevant since we're resetting the Program + * Counter. + */ + ahd_outb(ahd, CLRINT, CLRSEQINT); + ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET); ahd_unpause(ahd); } @@ -373,13 +379,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) saved_modes = ahd_save_modes(ahd); /* - * Complete any SCBs that just finished being - * DMA'ed into the qoutfifo. - */ - ahd_run_qoutfifo(ahd); - - /* - * Flush the good status FIFO for compelted packetized commands. + * Flush the good status FIFO for completed packetized commands. */ ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); saved_scbptr = ahd_get_scbptr(ahd); @@ -400,22 +400,33 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) * the host before completing the command. */ fifo_mode = 0; +rescan_fifos: for (i = 0; i < 2; i++) { /* Toggle to the other mode. */ fifo_mode ^= 1; ahd_set_modes(ahd, fifo_mode, fifo_mode); + if (ahd_scb_active_in_fifo(ahd, scb) == 0) continue; ahd_run_data_fifo(ahd, scb); /* - * Clearing this transaction in this FIFO may - * cause a CFG4DATA for this same transaction - * to assert in the other FIFO. Make sure we - * loop one more time and check the other FIFO. + * Running this FIFO may cause a CFG4DATA for + * this same transaction to assert in the other + * FIFO or a new snapshot SAVEPTRS interrupt + * in this FIFO. Even running a FIFO may not + * clear the transaction if we are still waiting + * for data to drain to the host. We must loop + * until the transaction is not active in either + * FIFO just to be sure. Reset our loop counter + * so we will visit both FIFOs again before + * declaring this transaction finished. We + * also delay a bit so that status has a chance + * to change before we look at this FIFO again. */ - i = 0; + ahd_delay(200); + goto rescan_fifos; } ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); ahd_set_scbptr(ahd, scbid); @@ -428,19 +439,28 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) /* * The transfer completed with a residual. * Place this SCB on the complete DMA list - * so that we Update our in-core copy of the + * so that we update our in-core copy of the * SCB before completing the command. */ ahd_outb(ahd, SCB_SCSI_STATUS, 0); ahd_outb(ahd, SCB_SGPTR, ahd_inb_scbram(ahd, SCB_SGPTR) | SG_STATUS_VALID); - ahd_outw(ahd, SCB_TAG, SCB_GET_TAG(scb)); + ahd_outw(ahd, SCB_TAG, scbid); + ahd_outw(ahd, SCB_NEXT_COMPLETE, SCB_LIST_NULL); comp_head = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD); - ahd_outw(ahd, SCB_NEXT_COMPLETE, comp_head); - if (SCBID_IS_NULL(comp_head)) - ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, - SCB_GET_TAG(scb)); + if (SCBID_IS_NULL(comp_head)) { + ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, scbid); + ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid); + } else { + u_int tail; + + tail = ahd_inw(ahd, COMPLETE_DMA_SCB_TAIL); + ahd_set_scbptr(ahd, tail); + ahd_outw(ahd, SCB_NEXT_COMPLETE, scbid); + ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid); + ahd_set_scbptr(ahd, scbid); + } } else ahd_complete_scb(ahd, scb); } @@ -464,9 +484,22 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) break; ahd_delay(200); } - if ((ccscbctl & CCSCBDIR) != 0) + /* + * We leave the sequencer to cleanup in the case of DMA's to + * update the qoutfifo. In all other cases (DMA's to the + * chip or a push of an SCB from the COMPLETE_DMA_SCB list), + * we disable the DMA engine so that the sequencer will not + * attempt to handle the DMA completion. + */ + if ((ccscbctl & CCSCBDIR) != 0 || (ccscbctl & ARRDONE) != 0) ahd_outb(ahd, CCSCBCTL, ccscbctl & ~(CCARREN|CCSCBEN)); + /* + * Complete any SCBs that just finished + * being DMA'ed into the qoutfifo. + */ + ahd_run_qoutfifo(ahd); + saved_scbptr = ahd_get_scbptr(ahd); /* * Manually update/complete any completed SCBs that are waiting to be @@ -493,6 +526,24 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) scbid = next_scbid; } ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL); + ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL); + + scbid = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD); + while (!SCBID_IS_NULL(scbid)) { + + ahd_set_scbptr(ahd, scbid); + next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); + scb = ahd_lookup_scb(ahd, scbid); + if (scb == NULL) { + printf("%s: Warning - Complete Qfrz SCB %d invalid\n", + ahd_name(ahd), scbid); + continue; + } + + ahd_complete_scb(ahd, scb); + scbid = next_scbid; + } + ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL); scbid = ahd_inw(ahd, COMPLETE_SCB_HEAD); while (!SCBID_IS_NULL(scbid)) { @@ -557,150 +608,146 @@ ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb) { u_int seqintsrc; - while (1) { - seqintsrc = ahd_inb(ahd, SEQINTSRC); - if ((seqintsrc & CFG4DATA) != 0) { - uint32_t datacnt; - uint32_t sgptr; - - /* - * Clear full residual flag. - */ - sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID; - ahd_outb(ahd, SCB_SGPTR, sgptr); + seqintsrc = ahd_inb(ahd, SEQINTSRC); + if ((seqintsrc & CFG4DATA) != 0) { + uint32_t datacnt; + uint32_t sgptr; - /* - * Load datacnt and address. - */ - datacnt = ahd_inl_scbram(ahd, SCB_DATACNT); - if ((datacnt & AHD_DMA_LAST_SEG) != 0) { - sgptr |= LAST_SEG; - ahd_outb(ahd, SG_STATE, 0); - } else - ahd_outb(ahd, SG_STATE, LOADING_NEEDED); - ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR)); - ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK); - ahd_outb(ahd, SG_CACHE_PRE, sgptr); - ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN); + /* + * Clear full residual flag. + */ + sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID; + ahd_outb(ahd, SCB_SGPTR, sgptr); - /* - * Initialize Residual Fields. - */ - ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24); - ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK); + /* + * Load datacnt and address. + */ + datacnt = ahd_inl_scbram(ahd, SCB_DATACNT); + if ((datacnt & AHD_DMA_LAST_SEG) != 0) { + sgptr |= LAST_SEG; + ahd_outb(ahd, SG_STATE, 0); + } else + ahd_outb(ahd, SG_STATE, LOADING_NEEDED); + ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR)); + ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK); + ahd_outb(ahd, SG_CACHE_PRE, sgptr); + ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN); - /* - * Mark the SCB as having a FIFO in use. - */ - ahd_outb(ahd, SCB_FIFO_USE_COUNT, - ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1); + /* + * Initialize Residual Fields. + */ + ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24); + ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK); - /* - * Install a "fake" handler for this FIFO. - */ - ahd_outw(ahd, LONGJMP_ADDR, 0); + /* + * Mark the SCB as having a FIFO in use. + */ + ahd_outb(ahd, SCB_FIFO_USE_COUNT, + ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1); - /* - * Notify the hardware that we have satisfied - * this sequencer interrupt. - */ - ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA); - } else if ((seqintsrc & SAVEPTRS) != 0) { - uint32_t sgptr; - uint32_t resid; + /* + * Install a "fake" handler for this FIFO. + */ + ahd_outw(ahd, LONGJMP_ADDR, 0); - if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) { - /* - * Snapshot Save Pointers. Clear - * the snapshot and continue. - */ - ahd_outb(ahd, DFFSXFRCTL, CLRCHN); - continue; - } + /* + * Notify the hardware that we have satisfied + * this sequencer interrupt. + */ + ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA); + } else if ((seqintsrc & SAVEPTRS) != 0) { + uint32_t sgptr; + uint32_t resid; + if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) { /* - * Disable S/G fetch so the DMA engine - * is available to future users. + * Snapshot Save Pointers. All that + * is necessary to clear the snapshot + * is a CLRCHN. */ - if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) - ahd_outb(ahd, CCSGCTL, 0); - ahd_outb(ahd, SG_STATE, 0); + goto clrchn; + } - /* - * Flush the data FIFO. Strickly only - * necessary for Rev A parts. - */ - ahd_outb(ahd, DFCNTRL, - ahd_inb(ahd, DFCNTRL) | FIFOFLUSH); + /* + * Disable S/G fetch so the DMA engine + * is available to future users. + */ + if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) + ahd_outb(ahd, CCSGCTL, 0); + ahd_outb(ahd, SG_STATE, 0); - /* - * Calculate residual. - */ - sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR); - resid = ahd_inl(ahd, SHCNT); - resid |= - ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24; - ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid); - if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) { - /* - * Must back up to the correct S/G element. - * Typically this just means resetting our - * low byte to the offset in the SG_CACHE, - * but if we wrapped, we have to correct - * the other bytes of the sgptr too. - */ - if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0 - && (sgptr & 0x80) == 0) - sgptr -= 0x100; - sgptr &= ~0xFF; - sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW) - & SG_ADDR_MASK; - ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr); - ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0); - } else if ((resid & AHD_SG_LEN_MASK) == 0) { - ahd_outb(ahd, SCB_RESIDUAL_SGPTR, - sgptr | SG_LIST_NULL); - } - /* - * Save Pointers. - */ - ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR)); - ahd_outl(ahd, SCB_DATACNT, resid); - ahd_outl(ahd, SCB_SGPTR, sgptr); - ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS); - ahd_outb(ahd, SEQIMODE, - ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS); - /* - * If the data is to the SCSI bus, we are - * done, otherwise wait for FIFOEMP. - */ - if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0) - break; - } else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) { - uint32_t sgptr; - uint64_t data_addr; - uint32_t data_len; - u_int dfcntrl; + /* + * Flush the data FIFO. Strickly only + * necessary for Rev A parts. + */ + ahd_outb(ahd, DFCNTRL, ahd_inb(ahd, DFCNTRL) | FIFOFLUSH); + /* + * Calculate residual. + */ + sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR); + resid = ahd_inl(ahd, SHCNT); + resid |= ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24; + ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid); + if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) { /* - * Disable S/G fetch so the DMA engine - * is available to future users. + * Must back up to the correct S/G element. + * Typically this just means resetting our + * low byte to the offset in the SG_CACHE, + * but if we wrapped, we have to correct + * the other bytes of the sgptr too. */ - if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) { - ahd_outb(ahd, CCSGCTL, 0); - ahd_outb(ahd, SG_STATE, LOADING_NEEDED); - } + if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0 + && (sgptr & 0x80) == 0) + sgptr -= 0x100; + sgptr &= ~0xFF; + sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW) + & SG_ADDR_MASK; + ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr); + ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0); + } else if ((resid & AHD_SG_LEN_MASK) == 0) { + ahd_outb(ahd, SCB_RESIDUAL_SGPTR, + sgptr | SG_LIST_NULL); + } + /* + * Save Pointers. + */ + ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR)); + ahd_outl(ahd, SCB_DATACNT, resid); + ahd_outl(ahd, SCB_SGPTR, sgptr); + ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS); + ahd_outb(ahd, SEQIMODE, + ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS); + /* + * If the data is to the SCSI bus, we are + * done, otherwise wait for FIFOEMP. + */ + if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0) + goto clrchn; + } else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) { + uint32_t sgptr; + uint64_t data_addr; + uint32_t data_len; + u_int dfcntrl; - /* - * Wait for the DMA engine to notice that the - * host transfer is enabled and that there is - * space in the S/G FIFO for new segments before - * loading more segments. - */ - if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) == 0) - continue; - if ((ahd_inb(ahd, DFCNTRL) & HDMAENACK) == 0) - continue; + /* + * Disable S/G fetch so the DMA engine + * is available to future users. We won't + * be using the DMA engine to load segments. + */ + if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) { + ahd_outb(ahd, CCSGCTL, 0); + ahd_outb(ahd, SG_STATE, LOADING_NEEDED); + } + + /* + * Wait for the DMA engine to notice that the + * host transfer is enabled and that there is + * space in the S/G FIFO for new segments before + * loading more segments. + */ + if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) != 0 + && (ahd_inb(ahd, DFCNTRL) & HDMAENACK) != 0) { /* * Determine the offset of the next S/G @@ -756,35 +803,44 @@ ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb) dfcntrl |= SCSIENWRDIS; } ahd_outb(ahd, DFCNTRL, dfcntrl); - } else if ((ahd_inb(ahd, SG_CACHE_SHADOW) - & LAST_SEG_DONE) != 0) { - - /* - * Transfer completed to the end of SG list - * and has flushed to the host. - */ - ahd_outb(ahd, SCB_SGPTR, - ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL); - break; - } else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) { - break; } - ahd_delay(200); + } else if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG_DONE) != 0) { + + /* + * Transfer completed to the end of SG list + * and has flushed to the host. + */ + ahd_outb(ahd, SCB_SGPTR, + ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL); + goto clrchn; + } else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) { +clrchn: + /* + * Clear any handler for this FIFO, decrement + * the FIFO use count for the SCB, and release + * the FIFO. + */ + ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR); + ahd_outb(ahd, SCB_FIFO_USE_COUNT, + ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1); + ahd_outb(ahd, DFFSXFRCTL, CLRCHN); } - /* - * Clear any handler for this FIFO, decrement - * the FIFO use count for the SCB, and release - * the FIFO. - */ - ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR); - ahd_outb(ahd, SCB_FIFO_USE_COUNT, - ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1); - ahd_outb(ahd, DFFSXFRCTL, CLRCHN); } +/* + * Look for entries in the QoutFIFO that have completed. + * The valid_tag completion field indicates the validity + * of the entry - the valid value toggles each time through + * the queue. We use the sg_status field in the completion + * entry to avoid referencing the hscb if the completion + * occurred with no errors and no residual. sg_status is + * a copy of the first byte (little endian) of the sgptr + * hscb field. + */ void ahd_run_qoutfifo(struct ahd_softc *ahd) { + struct ahd_completion *completion; struct scb *scb; u_int scb_index; @@ -792,11 +848,13 @@ ahd_run_qoutfifo(struct ahd_softc *ahd) panic("ahd_run_qoutfifo recursion"); ahd->flags |= AHD_RUNNING_QOUTFIFO; ahd_sync_qoutfifo(ahd, BUS_DMASYNC_POSTREAD); - while ((ahd->qoutfifo[ahd->qoutfifonext] - & QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag) { + for (;;) { + completion = &ahd->qoutfifo[ahd->qoutfifonext]; + + if (completion->valid_tag != ahd->qoutfifonext_valid_tag) + break; - scb_index = ahd_le16toh(ahd->qoutfifo[ahd->qoutfifonext] - & ~QOUTFIFO_ENTRY_VALID_LE); + scb_index = ahd_le16toh(completion->tag); scb = ahd_lookup_scb(ahd, scb_index); if (scb == NULL) { printf("%s: WARNING no command for scb %d " @@ -804,12 +862,15 @@ ahd_run_qoutfifo(struct ahd_softc *ahd) ahd_name(ahd), scb_index, ahd->qoutfifonext); ahd_dump_card_state(ahd); - } else - ahd_complete_scb(ahd, scb); + } else if ((completion->sg_status & SG_STATUS_VALID) != 0) { + ahd_handle_scb_status(ahd, scb); + } else { + ahd_done(ahd, scb); + } ahd->qoutfifonext = (ahd->qoutfifonext+1) & (AHD_QOUT_SIZE-1); if (ahd->qoutfifonext == 0) - ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID_LE; + ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID; } ahd->flags &= ~AHD_RUNNING_QOUTFIFO; } @@ -875,26 +936,6 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) ahd_name(ahd), seqintcode); #endif switch (seqintcode) { - case BAD_SCB_STATUS: - { - struct scb *scb; - u_int scbid; - int cmds_pending; - - scbid = ahd_get_scbptr(ahd); - scb = ahd_lookup_scb(ahd, scbid); - if (scb != NULL) { - ahd_complete_scb(ahd, scb); - } else { - printf("%s: WARNING no command for scb %d " - "(bad status)\n", ahd_name(ahd), scbid); - ahd_dump_card_state(ahd); - } - cmds_pending = ahd_inw(ahd, CMDS_PENDING); - if (cmds_pending > 0) - ahd_outw(ahd, CMDS_PENDING, cmds_pending - 1); - break; - } case ENTERING_NONPACK: { struct scb *scb; @@ -1502,9 +1543,6 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) != 0) scb = NULL; - /* Make sure the sequencer is in a safe location. */ - ahd_clear_critical_section(ahd); - if ((status0 & IOERR) != 0) { u_int now_lvd; @@ -1520,26 +1558,35 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) ahd_setup_iocell_workaround(ahd); ahd_unpause(ahd); } else if ((status0 & OVERRUN) != 0) { + printf("%s: SCSI offset overrun detected. Resetting bus.\n", ahd_name(ahd)); ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); } else if ((status & SCSIRSTI) != 0) { + printf("%s: Someone reset channel A\n", ahd_name(ahd)); ahd_reset_channel(ahd, 'A', /*Initiate Reset*/FALSE); } else if ((status & SCSIPERR) != 0) { + + /* Make sure the sequencer is in a safe location. */ + ahd_clear_critical_section(ahd); + ahd_handle_transmission_error(ahd); } else if (lqostat0 != 0) { + printf("%s: lqostat0 == 0x%x!\n", ahd_name(ahd), lqostat0); ahd_outb(ahd, CLRLQOINT0, lqostat0); - if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) { + if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) ahd_outb(ahd, CLRLQOINT1, 0); - } } else if ((status & SELTO) != 0) { u_int scbid; /* Stop the selection */ ahd_outb(ahd, SCSISEQ0, 0); + /* Make sure the sequencer is in a safe location. */ + ahd_clear_critical_section(ahd); + /* No more pending messages */ ahd_clear_msg_state(ahd); @@ -1572,24 +1619,27 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) scbid); } #endif - /* - * Force a renegotiation with this target just in - * case the cable was pulled and will later be - * re-attached. The target may forget its negotiation - * settings with us should it attempt to reselect - * during the interruption. The target will not issue - * a unit attention in this case, so we must always - * renegotiate. - */ ahd_scb_devinfo(ahd, &devinfo, scb); - ahd_force_renegotiation(ahd, &devinfo); ahd_set_transaction_status(scb, CAM_SEL_TIMEOUT); ahd_freeze_devq(ahd, scb); + + /* + * Cancel any pending transactions on the device + * now that it seems to be missing. This will + * also revert us to async/narrow transfers until + * we can renegotiate with the device. + */ + ahd_handle_devreset(ahd, &devinfo, + CAM_LUN_WILDCARD, + CAM_SEL_TIMEOUT, + "Selection Timeout", + /*verbose_level*/1); } ahd_outb(ahd, CLRINT, CLRSCSIINT); ahd_iocell_first_selection(ahd); ahd_unpause(ahd); } else if ((status0 & (SELDI|SELDO)) != 0) { + ahd_iocell_first_selection(ahd); ahd_unpause(ahd); } else if (status3 != 0) { @@ -1597,6 +1647,10 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) ahd_name(ahd), status3); ahd_outb(ahd, CLRSINT3, status3); } else if ((lqistat1 & (LQIPHASE_LQ|LQIPHASE_NLQ)) != 0) { + + /* Make sure the sequencer is in a safe location. */ + ahd_clear_critical_section(ahd); + ahd_handle_lqiphase_error(ahd, lqistat1); } else if ((lqistat1 & LQICRCI_NLQ) != 0) { /* @@ -1621,6 +1675,9 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) */ ahd_outb(ahd, SCSISEQ0, 0); + /* Make sure the sequencer is in a safe location. */ + ahd_clear_critical_section(ahd); + /* * Determine what we were up to at the time of * the busfree. @@ -1658,7 +1715,16 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) clear_fifo = 0; packetized = (lqostat1 & LQOBUSFREE) != 0; if (!packetized - && ahd_inb(ahd, LASTPHASE) == P_BUSFREE) + && ahd_inb(ahd, LASTPHASE) == P_BUSFREE + && (ahd_inb(ahd, SSTAT0) & SELDI) == 0 + && ((ahd_inb(ahd, SSTAT0) & SELDO) == 0 + || (ahd_inb(ahd, SCSISEQ0) & ENSELO) == 0)) + /* + * Assume packetized if we are not + * on the bus in a non-packetized + * capacity and any pending selection + * was a packetized selection. + */ packetized = 1; break; } @@ -3193,14 +3259,25 @@ ahd_update_neg_table(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, iocell_opts[AHD_PRECOMP_SLEW_INDEX] &= ~AHD_PRECOMP_MASK; if ((ahd->features & AHD_NEW_IOCELL_OPTS) != 0 - && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0) { + && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0 + && (ppr_opts & MSG_EXT_PPR_IU_REQ) == 0) { /* * Slow down our CRC interval to be - * compatible with devices that can't - * handle a CRC at full speed. + * compatible with non-packetized + * U160 devices that can't handle a + * CRC at full speed. */ con_opts |= ENSLOWCRC; } + + if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) { + /* + * On H2A4, revert to a slower slewrate + * on non-paced transfers. + */ + iocell_opts[AHD_PRECOMP_SLEW_INDEX] &= + ~AHD_SLEWRATE_MASK; + } } ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_PRECOMP_SLEW); @@ -3289,11 +3366,15 @@ ahd_update_pending_scbs(struct ahd_softc *ahd) * Force the sequencer to reinitialize the selection for * the command at the head of the execution queue if it * has already been setup. The negotiation changes may - * effect whether we select-out with ATN. + * effect whether we select-out with ATN. It is only + * safe to clear ENSELO when the bus is not free and no + * selection is in progres or completed. */ saved_modes = ahd_save_modes(ahd); ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO); + if ((ahd_inb(ahd, SCSISIGI) & BSYI) != 0 + && (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) == 0) + ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO); saved_scbptr = ahd_get_scbptr(ahd); /* Ensure that the hscbs down on the card match the new information */ for (scb_tag = 0; scb_tag < ahd->scb_data.maxhscbs; scb_tag++) { @@ -4999,13 +5080,14 @@ ahd_handle_devreset(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, ahd_set_width(ahd, devinfo, MSG_EXT_WDTR_BUS_8_BIT, AHD_TRANS_CUR, /*paused*/TRUE); ahd_set_syncrate(ahd, devinfo, /*period*/0, /*offset*/0, - /*ppr_options*/0, AHD_TRANS_CUR, /*paused*/TRUE); + /*ppr_options*/0, AHD_TRANS_CUR, + /*paused*/TRUE); - ahd_send_async(ahd, devinfo->channel, devinfo->target, - lun, AC_SENT_BDR, NULL); + if (status != CAM_SEL_TIMEOUT) + ahd_send_async(ahd, devinfo->channel, devinfo->target, + CAM_LUN_WILDCARD, AC_SENT_BDR, NULL); - if (message != NULL - && (verbose_level <= bootverbose)) + if (message != NULL && bootverbose) printf("%s: %s on %c:%d. %d SCBs aborted\n", ahd_name(ahd), message, devinfo->channel, devinfo->target, found); } @@ -5963,16 +6045,13 @@ ahd_alloc_scbs(struct ahd_softc *ahd) newcount = MIN(scb_data->sense_left, scb_data->scbs_left); newcount = MIN(newcount, scb_data->sgs_left); newcount = MIN(newcount, (AHD_SCB_MAX_ALLOC - scb_data->numscbs)); - scb_data->sense_left -= newcount; - scb_data->scbs_left -= newcount; - scb_data->sgs_left -= newcount; for (i = 0; i < newcount; i++) { - u_int col_tag; - struct scb_platform_data *pdata; + u_int col_tag; #ifndef __linux__ int error; #endif + next_scb = (struct scb *)malloc(sizeof(*next_scb), M_DEVBUF, M_NOWAIT); if (next_scb == NULL) @@ -6029,6 +6108,9 @@ ahd_alloc_scbs(struct ahd_softc *ahd) sense_data += AHD_SENSE_BUFSIZE; sense_busaddr += AHD_SENSE_BUFSIZE; scb_data->numscbs++; + scb_data->sense_left--; + scb_data->scbs_left--; + scb_data->sgs_left--; } } @@ -6143,7 +6225,7 @@ ahd_init(struct ahd_softc *ahd) * for the target mode role, we must additionally provide space for * the incoming target command fifo. */ - driver_data_size = AHD_SCB_MAX * sizeof(uint16_t) + driver_data_size = AHD_SCB_MAX * sizeof(*ahd->qoutfifo) + sizeof(struct hardware_scb); if ((ahd->features & AHD_TARGETMODE) != 0) driver_data_size += AHD_TMODE_CMDS * sizeof(struct target_cmd); @@ -6178,10 +6260,10 @@ ahd_init(struct ahd_softc *ahd) ahd->shared_data_map.vaddr, driver_data_size, ahd_dmamap_cb, &ahd->shared_data_map.physaddr, /*flags*/0); - ahd->qoutfifo = (uint16_t *)ahd->shared_data_map.vaddr; + ahd->qoutfifo = (struct ahd_completion *)ahd->shared_data_map.vaddr; next_vaddr = (uint8_t *)&ahd->qoutfifo[AHD_QOUT_SIZE]; next_baddr = ahd->shared_data_map.physaddr - + AHD_QOUT_SIZE*sizeof(uint16_t); + + AHD_QOUT_SIZE*sizeof(struct ahd_completion); if ((ahd->features & AHD_TARGETMODE) != 0) { ahd->targetcmds = (struct target_cmd *)next_vaddr; next_vaddr += AHD_TMODE_CMDS * sizeof(struct target_cmd); @@ -6508,10 +6590,10 @@ ahd_chip_init(struct ahd_softc *ahd) /* All of our queues are empty */ ahd->qoutfifonext = 0; - ahd->qoutfifonext_valid_tag = QOUTFIFO_ENTRY_VALID_LE; - ahd_outb(ahd, QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID >> 8); + ahd->qoutfifonext_valid_tag = QOUTFIFO_ENTRY_VALID; + ahd_outb(ahd, QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID); for (i = 0; i < AHD_QOUT_SIZE; i++) - ahd->qoutfifo[i] = 0; + ahd->qoutfifo[i].valid_tag = 0; ahd_sync_qoutfifo(ahd, BUS_DMASYNC_PREREAD); ahd->qinfifonext = 0; @@ -6544,12 +6626,15 @@ ahd_chip_init(struct ahd_softc *ahd) ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL); ahd_outw(ahd, COMPLETE_SCB_DMAINPROG_HEAD, SCB_LIST_NULL); ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL); + ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL); + ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL); /* * The Freeze Count is 0. */ ahd->qfreeze_cnt = 0; ahd_outw(ahd, QFREEZE_COUNT, 0); + ahd_outw(ahd, KERNEL_QFREEZE_COUNT, 0); /* * Tell the sequencer where it can find our arrays in memory. @@ -6909,43 +6994,34 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd) { u_int intstat; u_int maxloops; - u_int qfreeze_cnt; maxloops = 1000; ahd->flags |= AHD_ALL_INTERRUPTS; ahd_pause(ahd); /* - * Increment the QFreeze Count so that the sequencer - * will not start new selections. We do this only + * Freeze the outgoing selections. We do this only * until we are safely paused without further selections * pending. */ - ahd_outw(ahd, QFREEZE_COUNT, ahd_inw(ahd, QFREEZE_COUNT) + 1); + ahd->qfreeze_cnt--; + ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt); ahd_outb(ahd, SEQ_FLAGS2, ahd_inb(ahd, SEQ_FLAGS2) | SELECTOUT_QFROZEN); do { - struct scb *waiting_scb; ahd_unpause(ahd); + /* + * Give the sequencer some time to service + * any active selections. + */ + ahd_delay(500); + ahd_intr(ahd); ahd_pause(ahd); - ahd_clear_critical_section(ahd); intstat = ahd_inb(ahd, INTSTAT); - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - if ((ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) == 0) - ahd_outb(ahd, SCSISEQ0, - ahd_inb(ahd, SCSISEQ0) & ~ENSELO); - /* - * In the non-packetized case, the sequencer (for Rev A), - * relies on ENSELO remaining set after SELDO. The hardware - * auto-clears ENSELO in the packetized case. - */ - waiting_scb = ahd_lookup_scb(ahd, - ahd_inw(ahd, WAITING_TID_HEAD)); - if (waiting_scb != NULL - && (waiting_scb->flags & SCB_PACKETIZED) == 0 - && (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) != 0) - ahd_outb(ahd, SCSISEQ0, - ahd_inb(ahd, SCSISEQ0) | ENSELO); + if ((intstat & INT_PEND) == 0) { + ahd_clear_critical_section(ahd); + intstat = ahd_inb(ahd, INTSTAT); + } } while (--maxloops && (intstat != 0xFF || (ahd->features & AHD_REMOVABLE) == 0) && ((intstat & INT_PEND) != 0 @@ -6956,17 +7032,8 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd) printf("Infinite interrupt loop, INTSTAT = %x", ahd_inb(ahd, INTSTAT)); } - qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT); - if (qfreeze_cnt == 0) { - printf("%s: ahd_pause_and_flushwork with 0 qfreeze count!\n", - ahd_name(ahd)); - } else { - qfreeze_cnt--; - } - ahd_outw(ahd, QFREEZE_COUNT, qfreeze_cnt); - if (qfreeze_cnt == 0) - ahd_outb(ahd, SEQ_FLAGS2, - ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN); + ahd->qfreeze_cnt++; + ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt); ahd_flush_qoutfifo(ahd); @@ -7307,6 +7374,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, * appropriate, traverse the SCBs of each "their id" * looking for matches. */ + ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); savedscbptr = ahd_get_scbptr(ahd); tid_next = ahd_inw(ahd, WAITING_TID_HEAD); tid_prev = SCB_LIST_NULL; @@ -7376,7 +7444,7 @@ ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel, u_int prev; int found; - AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); + AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); found = 0; prev = SCB_LIST_NULL; next = *list_head; @@ -7443,7 +7511,7 @@ static void ahd_stitch_tid_list(struct ahd_softc *ahd, u_int tid_prev, u_int tid_cur, u_int tid_next) { - AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); + AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); if (SCBID_IS_NULL(tid_cur)) { @@ -7483,7 +7551,7 @@ ahd_rem_wscb(struct ahd_softc *ahd, u_int scbid, { u_int tail_offset; - AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); + AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); if (!SCBID_IS_NULL(prev)) { ahd_set_scbptr(ahd, prev); ahd_outw(ahd, SCB_NEXT, next); @@ -7887,30 +7955,35 @@ ahd_handle_scb_status(struct ahd_softc *ahd, struct scb *scb) void ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) { - struct hardware_scb *hscb; - u_int qfreeze_cnt; + struct hardware_scb *hscb; + int paused; /* * The sequencer freezes its select-out queue * anytime a SCSI status error occurs. We must - * handle the error and decrement the QFREEZE count - * to allow the sequencer to continue. + * handle the error and increment our qfreeze count + * to allow the sequencer to continue. We don't + * bother clearing critical sections here since all + * operations are on data structures that the sequencer + * is not touching once the queue is frozen. */ hscb = scb->hscb; + if (ahd_is_paused(ahd)) { + paused = 1; + } else { + paused = 0; + ahd_pause(ahd); + } + /* Freeze the queue until the client sees the error. */ ahd_freeze_devq(ahd, scb); ahd_freeze_scb(scb); - qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT); - if (qfreeze_cnt == 0) { - printf("%s: Bad status with 0 qfreeze count!\n", ahd_name(ahd)); - } else { - qfreeze_cnt--; - ahd_outw(ahd, QFREEZE_COUNT, qfreeze_cnt); - } - if (qfreeze_cnt == 0) - ahd_outb(ahd, SEQ_FLAGS2, - ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN); + ahd->qfreeze_cnt++; + ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt); + + if (paused == 0) + ahd_unpause(ahd); /* Don't want to clobber the original sense code */ if ((scb->flags & SCB_SENSE) != 0) { @@ -8323,13 +8396,14 @@ ahd_loadseq(struct ahd_softc *ahd) u_int sg_prefetch_cnt_limit; u_int sg_prefetch_align; u_int sg_size; + u_int cacheline_mask; uint8_t download_consts[DOWNLOAD_CONST_COUNT]; if (bootverbose) printf("%s: Downloading Sequencer Program...", ahd_name(ahd)); -#if DOWNLOAD_CONST_COUNT != 7 +#if DOWNLOAD_CONST_COUNT != 8 #error "Download Const Mismatch" #endif /* @@ -8365,6 +8439,9 @@ ahd_loadseq(struct ahd_softc *ahd) /* Round down to the nearest power of 2. */ while (powerof2(sg_prefetch_align) == 0) sg_prefetch_align--; + + cacheline_mask = sg_prefetch_align - 1; + /* * If the cacheline boundary is greater than half our prefetch RAM * we risk not being able to fetch even a single complete S/G @@ -8405,6 +8482,7 @@ ahd_loadseq(struct ahd_softc *ahd) download_consts[PKT_OVERRUN_BUFOFFSET] = (ahd->overrun_buf - (uint8_t *)ahd->qoutfifo) / 256; download_consts[SCB_TRANSFER_SIZE] = SCB_TRANSFER_SIZE_1BYTE_LUN; + download_consts[CACHELINE_MASK] = cacheline_mask; cur_patch = patches; downloaded = 0; skip_addr = 0; @@ -8818,6 +8896,15 @@ ahd_dump_card_state(struct ahd_softc *ahd) scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); } printf("\n"); + printf("Sequencer On QFreeze and Complete list: "); + scb_index = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD); + i = 0; + while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) { + ahd_set_scbptr(ahd, scb_index); + printf("%d ", scb_index); + scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); + } + printf("\n"); ahd_set_scbptr(ahd, saved_scb_index); dffstat = ahd_inb(ahd, DFFSTAT); for (i = 0; i < 2; i++) { @@ -9052,7 +9139,7 @@ ahd_wait_seeprom(struct ahd_softc *ahd) { int cnt; - cnt = 20; + cnt = 5000; while ((ahd_inb(ahd, SEESTAT) & (SEEARBACK|SEEBUSY)) != 0 && --cnt) ahd_delay(5); diff --git a/drivers/scsi/aic7xxx/aic79xx_inline.h b/drivers/scsi/aic7xxx/aic79xx_inline.h index 2b7ff989f3d..91c4f7f484b 100644 --- a/drivers/scsi/aic7xxx/aic79xx_inline.h +++ b/drivers/scsi/aic7xxx/aic79xx_inline.h @@ -839,7 +839,7 @@ ahd_sync_qoutfifo(struct ahd_softc *ahd, int op) { ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap, /*offset*/0, - /*len*/AHD_SCB_MAX * sizeof(uint16_t), op); + /*len*/AHD_SCB_MAX * sizeof(struct ahd_completion), op); } static __inline void @@ -871,8 +871,8 @@ ahd_check_cmdcmpltqueues(struct ahd_softc *ahd) ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap, /*offset*/ahd->qoutfifonext * sizeof(*ahd->qoutfifo), /*len*/sizeof(*ahd->qoutfifo), BUS_DMASYNC_POSTREAD); - if ((ahd->qoutfifo[ahd->qoutfifonext] - & QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag) + if (ahd->qoutfifo[ahd->qoutfifonext].valid_tag + == ahd->qoutfifonext_valid_tag) retval |= AHD_RUN_QOUTFIFO; #ifdef AHD_TARGET_MODE if ((ahd->flags & AHD_TARGETROLE) != 0 diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 1c8f872e2dd..2567e29960b 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -1468,6 +1468,30 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev, if ((tstate->auto_negotiate & mask) != 0) { scb->flags |= SCB_AUTO_NEGOTIATE; scb->hscb->control |= MK_MESSAGE; + } else if (cmd->cmnd[0] == INQUIRY + && (tinfo->curr.offset != 0 + || tinfo->curr.width != MSG_EXT_WDTR_BUS_8_BIT + || tinfo->curr.ppr_options != 0) + && (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ)==0) { + /* + * The SCSI spec requires inquiry + * commands to complete without + * reporting unit attention conditions. + * Because of this, an inquiry command + * that occurs just after a device is + * reset will result in a data phase + * with mismatched negotiated rates. + * The core already forces a renegotiation + * for reset events that are visible to + * our controller or that we initiate, + * but a third party device reset or a + * hot-plug insertion can still cause this + * issue. Therefore, we force a re-negotiation + * for every inquiry command unless we + * are async. + */ + scb->flags |= SCB_NEGOTIATE; + scb->hscb->control |= MK_MESSAGE; } if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) { @@ -2058,6 +2082,7 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) int paused; int wait; int disconnected; + int found; ahd_mode_state saved_modes; unsigned long flags; @@ -2176,7 +2201,8 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) last_phase = ahd_inb(ahd, LASTPHASE); saved_scbptr = ahd_get_scbptr(ahd); active_scbptr = saved_scbptr; - if (disconnected && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) { + if (disconnected && ((last_phase != P_BUSFREE) || + (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0)) { struct scb *bus_scb; bus_scb = ahd_lookup_scb(ahd, active_scbptr); @@ -2194,28 +2220,41 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) * bus or is in the disconnected state. */ saved_scsiid = ahd_inb(ahd, SAVED_SCSIID); - if (last_phase != P_BUSFREE - && (SCB_GET_TAG(pending_scb) == active_scbptr + if (SCB_GET_TAG(pending_scb) == active_scbptr || (flag == SCB_DEVICE_RESET - && SCSIID_TARGET(ahd, saved_scsiid) == scmd_id(cmd)))) { + && SCSIID_TARGET(ahd, saved_scsiid) == scmd_id(cmd))) { /* * We're active on the bus, so assert ATN * and hope that the target responds. */ pending_scb = ahd_lookup_scb(ahd, active_scbptr); - pending_scb->flags |= SCB_RECOVERY_SCB|flag; + pending_scb->flags |= SCB_RECOVERY_SCB|SCB_DEVICE_RESET; ahd_outb(ahd, MSG_OUT, HOST_MSG); ahd_outb(ahd, SCSISIGO, last_phase|ATNO); - scmd_printk(KERN_INFO, cmd, "Device is active, asserting ATN\n"); + scmd_printk(KERN_INFO, cmd, "BDR message in message buffer\n"); wait = TRUE; + } else if (last_phase != P_BUSFREE + && ahd_inb(ahd, SCSIPHASE) == 0) { + /* + * SCB is not identified, there + * is no pending REQ, and the sequencer + * has not seen a busfree. Looks like + * a stuck connection waiting to + * go busfree. Reset the bus. + */ + found = ahd_reset_channel(ahd, cmd->device->channel + 'A', + /*Initiate Reset*/TRUE); + printf("%s: Issued Channel %c Bus Reset. " + "%d SCBs aborted\n", ahd_name(ahd), + cmd->device->channel + 'A', found); } else if (disconnected) { /* * Actually re-queue this SCB in an attempt * to select the device before it reconnects. */ - pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT; + pending_scb->flags |= SCB_RECOVERY_SCB|flag; ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb)); pending_scb->hscb->cdb_len = 0; pending_scb->hscb->task_attribute = 0; @@ -2296,16 +2335,17 @@ done: timer.expires = jiffies + (5 * HZ); timer.function = ahd_linux_sem_timeout; add_timer(&timer); - printf("Recovery code sleeping\n"); + printf("%s: Recovery code sleeping\n", ahd_name(ahd)); down(&ahd->platform_data->eh_sem); - printf("Recovery code awake\n"); + printf("%s: Recovery code awake\n", ahd_name(ahd)); ret = del_timer_sync(&timer); if (ret == 0) { - printf("Timer Expired\n"); + printf("%s: Timer Expired (active %d)\n", + ahd_name(ahd), dev->active); retval = FAILED; } } - ahd_unlock(ahd, &flags); + ahd_unlock(ahd, &flags); return (retval); } diff --git a/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped b/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped index c01ac39090d..8763b158856 100644 --- a/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped +++ b/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped @@ -2,8 +2,8 @@ * DO NOT EDIT - This file is automatically generated * from the following source files: * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $ - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $ */ typedef int (ahd_reg_print_t)(u_int, u_int *, u_int); typedef struct ahd_reg_parse_entry { @@ -83,17 +83,17 @@ ahd_reg_print_t ahd_hs_mailbox_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_clrseqintstat_print; +ahd_reg_print_t ahd_seqintstat_print; #else -#define ahd_clrseqintstat_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CLRSEQINTSTAT", 0x0c, regvalue, cur_col, wrap) +#define ahd_seqintstat_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SEQINTSTAT", 0x0c, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_seqintstat_print; +ahd_reg_print_t ahd_clrseqintstat_print; #else -#define ahd_seqintstat_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SEQINTSTAT", 0x0c, regvalue, cur_col, wrap) +#define ahd_clrseqintstat_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "CLRSEQINTSTAT", 0x0c, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -412,17 +412,17 @@ ahd_reg_print_t ahd_sxfrctl0_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_businitid_print; +ahd_reg_print_t ahd_dlcount_print; #else -#define ahd_businitid_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "BUSINITID", 0x3c, regvalue, cur_col, wrap) +#define ahd_dlcount_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "DLCOUNT", 0x3c, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_dlcount_print; +ahd_reg_print_t ahd_businitid_print; #else -#define ahd_dlcount_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "DLCOUNT", 0x3c, regvalue, cur_col, wrap) +#define ahd_businitid_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "BUSINITID", 0x3c, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -516,13 +516,6 @@ ahd_reg_print_t ahd_selid_print; ahd_print_register(NULL, 0, "SELID", 0x49, regvalue, cur_col, wrap) #endif -#if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_sblkctl_print; -#else -#define ahd_sblkctl_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SBLKCTL", 0x4a, regvalue, cur_col, wrap) -#endif - #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_optionmode_print; #else @@ -531,10 +524,10 @@ ahd_reg_print_t ahd_optionmode_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_sstat0_print; +ahd_reg_print_t ahd_sblkctl_print; #else -#define ahd_sstat0_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SSTAT0", 0x4b, regvalue, cur_col, wrap) +#define ahd_sblkctl_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SBLKCTL", 0x4a, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -544,6 +537,13 @@ ahd_reg_print_t ahd_clrsint0_print; ahd_print_register(NULL, 0, "CLRSINT0", 0x4b, regvalue, cur_col, wrap) #endif +#if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_sstat0_print; +#else +#define ahd_sstat0_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SSTAT0", 0x4b, regvalue, cur_col, wrap) +#endif + #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_simode0_print; #else @@ -573,17 +573,17 @@ ahd_reg_print_t ahd_sstat2_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_clrsint2_print; +ahd_reg_print_t ahd_simode2_print; #else -#define ahd_clrsint2_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CLRSINT2", 0x4d, regvalue, cur_col, wrap) +#define ahd_simode2_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SIMODE2", 0x4d, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_simode2_print; +ahd_reg_print_t ahd_clrsint2_print; #else -#define ahd_simode2_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SIMODE2", 0x4d, regvalue, cur_col, wrap) +#define ahd_clrsint2_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "CLRSINT2", 0x4d, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -684,13 +684,6 @@ ahd_reg_print_t ahd_clrsint3_print; ahd_print_register(NULL, 0, "CLRSINT3", 0x53, regvalue, cur_col, wrap) #endif -#if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_lqomode0_print; -#else -#define ahd_lqomode0_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "LQOMODE0", 0x54, regvalue, cur_col, wrap) -#endif - #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_lqostat0_print; #else @@ -705,6 +698,20 @@ ahd_reg_print_t ahd_clrlqoint0_print; ahd_print_register(NULL, 0, "CLRLQOINT0", 0x54, regvalue, cur_col, wrap) #endif +#if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_lqomode0_print; +#else +#define ahd_lqomode0_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "LQOMODE0", 0x54, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_lqomode1_print; +#else +#define ahd_lqomode1_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "LQOMODE1", 0x55, regvalue, cur_col, wrap) +#endif + #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_lqostat1_print; #else @@ -719,13 +726,6 @@ ahd_reg_print_t ahd_clrlqoint1_print; ahd_print_register(NULL, 0, "CLRLQOINT1", 0x55, regvalue, cur_col, wrap) #endif -#if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_lqomode1_print; -#else -#define ahd_lqomode1_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "LQOMODE1", 0x55, regvalue, cur_col, wrap) -#endif - #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_lqostat2_print; #else @@ -909,17 +909,17 @@ ahd_reg_print_t ahd_annexcol_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_scschkn_print; +ahd_reg_print_t ahd_annexdat_print; #else -#define ahd_scschkn_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SCSCHKN", 0x66, regvalue, cur_col, wrap) +#define ahd_annexdat_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "ANNEXDAT", 0x66, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_annexdat_print; +ahd_reg_print_t ahd_scschkn_print; #else -#define ahd_annexdat_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "ANNEXDAT", 0x66, regvalue, cur_col, wrap) +#define ahd_scschkn_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SCSCHKN", 0x66, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1000,17 +1000,17 @@ ahd_reg_print_t ahd_pll400ctl1_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_pll400cnt0_print; +ahd_reg_print_t ahd_unfairness_print; #else -#define ahd_pll400cnt0_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "PLL400CNT0", 0x6e, regvalue, cur_col, wrap) +#define ahd_unfairness_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "UNFAIRNESS", 0x6e, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_unfairness_print; +ahd_reg_print_t ahd_pll400cnt0_print; #else -#define ahd_unfairness_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "UNFAIRNESS", 0x6e, regvalue, cur_col, wrap) +#define ahd_pll400cnt0_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "PLL400CNT0", 0x6e, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1055,13 +1055,6 @@ ahd_reg_print_t ahd_hodmaen_print; ahd_print_register(NULL, 0, "HODMAEN", 0x7a, regvalue, cur_col, wrap) #endif -#if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_sghaddr_print; -#else -#define ahd_sghaddr_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SGHADDR", 0x7c, regvalue, cur_col, wrap) -#endif - #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_scbhaddr_print; #else @@ -1070,10 +1063,10 @@ ahd_reg_print_t ahd_scbhaddr_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_sghcnt_print; +ahd_reg_print_t ahd_sghaddr_print; #else -#define ahd_sghcnt_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SGHCNT", 0x84, regvalue, cur_col, wrap) +#define ahd_sghaddr_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SGHADDR", 0x7c, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1083,6 +1076,13 @@ ahd_reg_print_t ahd_scbhcnt_print; ahd_print_register(NULL, 0, "SCBHCNT", 0x84, regvalue, cur_col, wrap) #endif +#if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_sghcnt_print; +#else +#define ahd_sghcnt_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SGHCNT", 0x84, regvalue, cur_col, wrap) +#endif + #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_dff_thrsh_print; #else @@ -1153,13 +1153,6 @@ ahd_reg_print_t ahd_nsenable_print; ahd_print_register(NULL, 0, "NSENABLE", 0x91, regvalue, cur_col, wrap) #endif -#if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_dchrxmsg1_print; -#else -#define ahd_dchrxmsg1_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "DCHRXMSG1", 0x91, regvalue, cur_col, wrap) -#endif - #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_cmcrxmsg1_print; #else @@ -1168,17 +1161,17 @@ ahd_reg_print_t ahd_cmcrxmsg1_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_dchrxmsg2_print; +ahd_reg_print_t ahd_dchrxmsg1_print; #else -#define ahd_dchrxmsg2_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "DCHRXMSG2", 0x92, regvalue, cur_col, wrap) +#define ahd_dchrxmsg1_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "DCHRXMSG1", 0x91, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_ovlyrxmsg2_print; +ahd_reg_print_t ahd_dchrxmsg2_print; #else -#define ahd_ovlyrxmsg2_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "OVLYRXMSG2", 0x92, regvalue, cur_col, wrap) +#define ahd_dchrxmsg2_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "DCHRXMSG2", 0x92, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1195,6 +1188,13 @@ ahd_reg_print_t ahd_ost_print; ahd_print_register(NULL, 0, "OST", 0x92, regvalue, cur_col, wrap) #endif +#if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_ovlyrxmsg2_print; +#else +#define ahd_ovlyrxmsg2_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "OVLYRXMSG2", 0x92, regvalue, cur_col, wrap) +#endif + #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_dchrxmsg3_print; #else @@ -1202,6 +1202,13 @@ ahd_reg_print_t ahd_dchrxmsg3_print; ahd_print_register(NULL, 0, "DCHRXMSG3", 0x93, regvalue, cur_col, wrap) #endif +#if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_ovlyrxmsg3_print; +#else +#define ahd_ovlyrxmsg3_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "OVLYRXMSG3", 0x93, regvalue, cur_col, wrap) +#endif + #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_cmcrxmsg3_print; #else @@ -1216,13 +1223,6 @@ ahd_reg_print_t ahd_pcixctl_print; ahd_print_register(NULL, 0, "PCIXCTL", 0x93, regvalue, cur_col, wrap) #endif -#if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_ovlyrxmsg3_print; -#else -#define ahd_ovlyrxmsg3_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "OVLYRXMSG3", 0x93, regvalue, cur_col, wrap) -#endif - #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_ovlyseqbcnt_print; #else @@ -1230,13 +1230,6 @@ ahd_reg_print_t ahd_ovlyseqbcnt_print; ahd_print_register(NULL, 0, "OVLYSEQBCNT", 0x94, regvalue, cur_col, wrap) #endif -#if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_cmcseqbcnt_print; -#else -#define ahd_cmcseqbcnt_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CMCSEQBCNT", 0x94, regvalue, cur_col, wrap) -#endif - #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_dchseqbcnt_print; #else @@ -1245,17 +1238,17 @@ ahd_reg_print_t ahd_dchseqbcnt_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_cmcspltstat0_print; +ahd_reg_print_t ahd_cmcseqbcnt_print; #else -#define ahd_cmcspltstat0_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CMCSPLTSTAT0", 0x96, regvalue, cur_col, wrap) +#define ahd_cmcseqbcnt_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "CMCSEQBCNT", 0x94, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_ovlyspltstat0_print; +ahd_reg_print_t ahd_cmcspltstat0_print; #else -#define ahd_ovlyspltstat0_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "OVLYSPLTSTAT0", 0x96, regvalue, cur_col, wrap) +#define ahd_cmcspltstat0_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "CMCSPLTSTAT0", 0x96, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1266,10 +1259,10 @@ ahd_reg_print_t ahd_dchspltstat0_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_dchspltstat1_print; +ahd_reg_print_t ahd_ovlyspltstat0_print; #else -#define ahd_dchspltstat1_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "DCHSPLTSTAT1", 0x97, regvalue, cur_col, wrap) +#define ahd_ovlyspltstat0_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "OVLYSPLTSTAT0", 0x96, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1286,6 +1279,13 @@ ahd_reg_print_t ahd_ovlyspltstat1_print; ahd_print_register(NULL, 0, "OVLYSPLTSTAT1", 0x97, regvalue, cur_col, wrap) #endif +#if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_dchspltstat1_print; +#else +#define ahd_dchspltstat1_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "DCHSPLTSTAT1", 0x97, regvalue, cur_col, wrap) +#endif + #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_sgrxmsg0_print; #else @@ -1378,17 +1378,17 @@ ahd_reg_print_t ahd_sgspltstat0_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_sfunct_print; +ahd_reg_print_t ahd_sgspltstat1_print; #else -#define ahd_sfunct_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SFUNCT", 0x9f, regvalue, cur_col, wrap) +#define ahd_sgspltstat1_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SGSPLTSTAT1", 0x9f, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_sgspltstat1_print; +ahd_reg_print_t ahd_sfunct_print; #else -#define ahd_sgspltstat1_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SGSPLTSTAT1", 0x9f, regvalue, cur_col, wrap) +#define ahd_sfunct_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SFUNCT", 0x9f, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1504,17 +1504,17 @@ ahd_reg_print_t ahd_ccsgaddr_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_ccscbaddr_print; +ahd_reg_print_t ahd_ccscbadr_bk_print; #else -#define ahd_ccscbaddr_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CCSCBADDR", 0xac, regvalue, cur_col, wrap) +#define ahd_ccscbadr_bk_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "CCSCBADR_BK", 0xac, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_ccscbadr_bk_print; +ahd_reg_print_t ahd_ccscbaddr_print; #else -#define ahd_ccscbadr_bk_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CCSCBADR_BK", 0xac, regvalue, cur_col, wrap) +#define ahd_ccscbaddr_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "CCSCBADDR", 0xac, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1525,17 +1525,17 @@ ahd_reg_print_t ahd_cmc_rambist_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_ccsgctl_print; +ahd_reg_print_t ahd_ccscbctl_print; #else -#define ahd_ccsgctl_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CCSGCTL", 0xad, regvalue, cur_col, wrap) +#define ahd_ccscbctl_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "CCSCBCTL", 0xad, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_ccscbctl_print; +ahd_reg_print_t ahd_ccsgctl_print; #else -#define ahd_ccscbctl_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CCSCBCTL", 0xad, regvalue, cur_col, wrap) +#define ahd_ccsgctl_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "CCSGCTL", 0xad, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1706,13 +1706,6 @@ ahd_reg_print_t ahd_wrtbiascalc_print; ahd_print_register(NULL, 0, "WRTBIASCALC", 0xc7, regvalue, cur_col, wrap) #endif -#if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_dfptrs_print; -#else -#define ahd_dfptrs_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "DFPTRS", 0xc8, regvalue, cur_col, wrap) -#endif - #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_rcvrbiascalc_print; #else @@ -1721,10 +1714,10 @@ ahd_reg_print_t ahd_rcvrbiascalc_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_dfbkptr_print; +ahd_reg_print_t ahd_dfptrs_print; #else -#define ahd_dfbkptr_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "DFBKPTR", 0xc9, regvalue, cur_col, wrap) +#define ahd_dfptrs_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "DFPTRS", 0xc8, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1734,6 +1727,13 @@ ahd_reg_print_t ahd_skewcalc_print; ahd_print_register(NULL, 0, "SKEWCALC", 0xc9, regvalue, cur_col, wrap) #endif +#if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_dfbkptr_print; +#else +#define ahd_dfbkptr_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "DFBKPTR", 0xc9, regvalue, cur_col, wrap) +#endif + #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_dfdbctl_print; #else @@ -1826,17 +1826,17 @@ ahd_reg_print_t ahd_dindex_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_brkaddr1_print; +ahd_reg_print_t ahd_brkaddr0_print; #else -#define ahd_brkaddr1_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "BRKADDR1", 0xe6, regvalue, cur_col, wrap) +#define ahd_brkaddr0_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "BRKADDR0", 0xe6, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_brkaddr0_print; +ahd_reg_print_t ahd_brkaddr1_print; #else -#define ahd_brkaddr0_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "BRKADDR0", 0xe6, regvalue, cur_col, wrap) +#define ahd_brkaddr1_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "BRKADDR1", 0xe6, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1888,13 +1888,6 @@ ahd_reg_print_t ahd_stack_print; ahd_print_register(NULL, 0, "STACK", 0xf2, regvalue, cur_col, wrap) #endif -#if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_curaddr_print; -#else -#define ahd_curaddr_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CURADDR", 0xf4, regvalue, cur_col, wrap) -#endif - #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_intvec1_addr_print; #else @@ -1903,10 +1896,10 @@ ahd_reg_print_t ahd_intvec1_addr_print; #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_intvec2_addr_print; +ahd_reg_print_t ahd_curaddr_print; #else -#define ahd_intvec2_addr_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "INTVEC2_ADDR", 0xf6, regvalue, cur_col, wrap) +#define ahd_curaddr_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "CURADDR", 0xf4, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -1916,6 +1909,13 @@ ahd_reg_print_t ahd_lastaddr_print; ahd_print_register(NULL, 0, "LASTADDR", 0xf6, regvalue, cur_col, wrap) #endif +#if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_intvec2_addr_print; +#else +#define ahd_intvec2_addr_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "INTVEC2_ADDR", 0xf6, regvalue, cur_col, wrap) +#endif + #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_longjmp_addr_print; #else @@ -1993,193 +1993,214 @@ ahd_reg_print_t ahd_complete_dma_scb_head_print; ahd_print_register(NULL, 0, "COMPLETE_DMA_SCB_HEAD", 0x12c, regvalue, cur_col, wrap) #endif +#if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_complete_dma_scb_tail_print; +#else +#define ahd_complete_dma_scb_tail_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "COMPLETE_DMA_SCB_TAIL", 0x12e, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_complete_on_qfreeze_head_print; +#else +#define ahd_complete_on_qfreeze_head_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "COMPLETE_ON_QFREEZE_HEAD", 0x130, regvalue, cur_col, wrap) +#endif + #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_qfreeze_count_print; #else #define ahd_qfreeze_count_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "QFREEZE_COUNT", 0x12e, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "QFREEZE_COUNT", 0x132, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_kernel_qfreeze_count_print; +#else +#define ahd_kernel_qfreeze_count_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "KERNEL_QFREEZE_COUNT", 0x134, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_saved_mode_print; #else #define ahd_saved_mode_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SAVED_MODE", 0x130, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "SAVED_MODE", 0x136, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_msg_out_print; #else #define ahd_msg_out_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "MSG_OUT", 0x131, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "MSG_OUT", 0x137, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_dmaparams_print; #else #define ahd_dmaparams_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "DMAPARAMS", 0x132, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "DMAPARAMS", 0x138, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_seq_flags_print; #else #define ahd_seq_flags_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SEQ_FLAGS", 0x133, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "SEQ_FLAGS", 0x139, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_saved_scsiid_print; #else #define ahd_saved_scsiid_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SAVED_SCSIID", 0x134, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "SAVED_SCSIID", 0x13a, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_saved_lun_print; #else #define ahd_saved_lun_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SAVED_LUN", 0x135, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "SAVED_LUN", 0x13b, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_lastphase_print; #else #define ahd_lastphase_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "LASTPHASE", 0x136, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "LASTPHASE", 0x13c, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_qoutfifo_entry_valid_tag_print; #else #define ahd_qoutfifo_entry_valid_tag_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "QOUTFIFO_ENTRY_VALID_TAG", 0x137, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "QOUTFIFO_ENTRY_VALID_TAG", 0x13d, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_shared_data_addr_print; +ahd_reg_print_t ahd_kernel_tqinpos_print; #else -#define ahd_shared_data_addr_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SHARED_DATA_ADDR", 0x138, regvalue, cur_col, wrap) +#define ahd_kernel_tqinpos_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "KERNEL_TQINPOS", 0x13e, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_qoutfifo_next_addr_print; +ahd_reg_print_t ahd_tqinpos_print; #else -#define ahd_qoutfifo_next_addr_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR", 0x13c, regvalue, cur_col, wrap) +#define ahd_tqinpos_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "TQINPOS", 0x13f, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_kernel_tqinpos_print; +ahd_reg_print_t ahd_shared_data_addr_print; #else -#define ahd_kernel_tqinpos_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "KERNEL_TQINPOS", 0x140, regvalue, cur_col, wrap) +#define ahd_shared_data_addr_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SHARED_DATA_ADDR", 0x140, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_tqinpos_print; +ahd_reg_print_t ahd_qoutfifo_next_addr_print; #else -#define ahd_tqinpos_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "TQINPOS", 0x141, regvalue, cur_col, wrap) +#define ahd_qoutfifo_next_addr_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR", 0x144, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_arg_1_print; #else #define ahd_arg_1_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "ARG_1", 0x142, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "ARG_1", 0x148, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_arg_2_print; #else #define ahd_arg_2_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "ARG_2", 0x143, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "ARG_2", 0x149, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_last_msg_print; #else #define ahd_last_msg_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "LAST_MSG", 0x144, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "LAST_MSG", 0x14a, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_scsiseq_template_print; #else #define ahd_scsiseq_template_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SCSISEQ_TEMPLATE", 0x145, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "SCSISEQ_TEMPLATE", 0x14b, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_initiator_tag_print; #else #define ahd_initiator_tag_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "INITIATOR_TAG", 0x146, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "INITIATOR_TAG", 0x14c, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_seq_flags2_print; #else #define ahd_seq_flags2_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SEQ_FLAGS2", 0x147, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "SEQ_FLAGS2", 0x14d, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_allocfifo_scbptr_print; #else #define ahd_allocfifo_scbptr_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "ALLOCFIFO_SCBPTR", 0x148, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "ALLOCFIFO_SCBPTR", 0x14e, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_int_coalescing_timer_print; #else #define ahd_int_coalescing_timer_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "INT_COALESCING_TIMER", 0x14a, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "INT_COALESCING_TIMER", 0x150, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_int_coalescing_maxcmds_print; #else #define ahd_int_coalescing_maxcmds_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "INT_COALESCING_MAXCMDS", 0x14c, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "INT_COALESCING_MAXCMDS", 0x152, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_int_coalescing_mincmds_print; #else #define ahd_int_coalescing_mincmds_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "INT_COALESCING_MINCMDS", 0x14d, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "INT_COALESCING_MINCMDS", 0x153, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_cmds_pending_print; #else #define ahd_cmds_pending_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CMDS_PENDING", 0x14e, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "CMDS_PENDING", 0x154, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_int_coalescing_cmdcount_print; #else #define ahd_int_coalescing_cmdcount_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "INT_COALESCING_CMDCOUNT", 0x150, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "INT_COALESCING_CMDCOUNT", 0x156, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_local_hs_mailbox_print; #else #define ahd_local_hs_mailbox_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "LOCAL_HS_MAILBOX", 0x151, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "LOCAL_HS_MAILBOX", 0x157, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_cmdsize_table_print; #else #define ahd_cmdsize_table_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "CMDSIZE_TABLE", 0x152, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "CMDSIZE_TABLE", 0x158, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -2434,13 +2455,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define HOST_TQINPOS 0x80 #define ENINT_COALESCE 0x40 -#define CLRSEQINTSTAT 0x0c -#define CLRSEQ_SWTMRTO 0x10 -#define CLRSEQ_SEQINT 0x08 -#define CLRSEQ_SCSIINT 0x04 -#define CLRSEQ_PCIINT 0x02 -#define CLRSEQ_SPLTINT 0x01 - #define SEQINTSTAT 0x0c #define SEQ_SWTMRTO 0x10 #define SEQ_SEQINT 0x08 @@ -2448,6 +2462,13 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define SEQ_PCIINT 0x02 #define SEQ_SPLTINT 0x01 +#define CLRSEQINTSTAT 0x0c +#define CLRSEQ_SWTMRTO 0x10 +#define CLRSEQ_SEQINT 0x08 +#define CLRSEQ_SCSIINT 0x04 +#define CLRSEQ_PCIINT 0x02 +#define CLRSEQ_SPLTINT 0x01 + #define SWTIMER 0x0e #define SNSCB_QOFF 0x10 @@ -2623,10 +2644,10 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define BIOSCANCELEN 0x10 #define SPIOEN 0x08 -#define BUSINITID 0x3c - #define DLCOUNT 0x3c +#define BUSINITID 0x3c + #define SXFRCTL1 0x3d #define BITBUCKET 0x80 #define ENSACHK 0x40 @@ -2693,13 +2714,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define SELID_MASK 0xf0 #define ONEBIT 0x08 -#define SBLKCTL 0x4a -#define DIAGLEDEN 0x80 -#define DIAGLEDON 0x40 -#define ENAB40 0x08 -#define ENAB20 0x04 -#define SELWIDE 0x02 - #define OPTIONMODE 0x4a #define OPTIONMODE_DEFAULTS 0x02 #define BIOSCANCTL 0x80 @@ -2709,15 +2723,12 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define ENDGFORMCHK 0x04 #define AUTO_MSGOUT_DE 0x02 -#define SSTAT0 0x4b -#define TARGET 0x80 -#define SELDO 0x40 -#define SELDI 0x20 -#define SELINGO 0x10 -#define IOERR 0x08 -#define OVERRUN 0x04 -#define SPIORDY 0x02 -#define ARBDO 0x01 +#define SBLKCTL 0x4a +#define DIAGLEDEN 0x80 +#define DIAGLEDON 0x40 +#define ENAB40 0x08 +#define ENAB20 0x04 +#define SELWIDE 0x02 #define CLRSINT0 0x4b #define CLRSELDO 0x40 @@ -2728,6 +2739,16 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define CLRSPIORDY 0x02 #define CLRARBDO 0x01 +#define SSTAT0 0x4b +#define TARGET 0x80 +#define SELDO 0x40 +#define SELDI 0x20 +#define SELINGO 0x10 +#define IOERR 0x08 +#define OVERRUN 0x04 +#define SPIORDY 0x02 +#define ARBDO 0x01 + #define SIMODE0 0x4b #define ENSELDO 0x40 #define ENSELDI 0x20 @@ -2768,17 +2789,17 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define BUSFREE_DFF0 0x80 #define BUSFREE_LQO 0x40 +#define SIMODE2 0x4d +#define ENWIDE_RES 0x04 +#define ENSDONE 0x02 +#define ENDMADONE 0x01 + #define CLRSINT2 0x4d #define CLRNONPACKREQ 0x20 #define CLRWIDE_RES 0x04 #define CLRSDONE 0x02 #define CLRDMADONE 0x01 -#define SIMODE2 0x4d -#define ENWIDE_RES 0x04 -#define ENSDONE 0x02 -#define ENDMADONE 0x01 - #define PERRDIAG 0x4e #define HIZERO 0x80 #define HIPERR 0x40 @@ -2871,13 +2892,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define CLRNTRAMPERR 0x02 #define CLROSRAMPERR 0x01 -#define LQOMODE0 0x54 -#define ENLQOTARGSCBPERR 0x10 -#define ENLQOSTOPT2 0x08 -#define ENLQOATNLQ 0x04 -#define ENLQOATNPKT 0x02 -#define ENLQOTCRC 0x01 - #define LQOSTAT0 0x54 #define LQOTARGSCBPERR 0x10 #define LQOSTOPT2 0x08 @@ -2892,6 +2906,20 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define CLRLQOATNPKT 0x02 #define CLRLQOTCRC 0x01 +#define LQOMODE0 0x54 +#define ENLQOTARGSCBPERR 0x10 +#define ENLQOSTOPT2 0x08 +#define ENLQOATNLQ 0x04 +#define ENLQOATNPKT 0x02 +#define ENLQOTCRC 0x01 + +#define LQOMODE1 0x55 +#define ENLQOINITSCBPERR 0x10 +#define ENLQOSTOPI2 0x08 +#define ENLQOBADQAS 0x04 +#define ENLQOBUSFREE 0x02 +#define ENLQOPHACHGINPKT 0x01 + #define LQOSTAT1 0x55 #define LQOINITSCBPERR 0x10 #define LQOSTOPI2 0x08 @@ -2906,13 +2934,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define CLRLQOBUSFREE 0x02 #define CLRLQOPHACHGINPKT 0x01 -#define LQOMODE1 0x55 -#define ENLQOINITSCBPERR 0x10 -#define ENLQOSTOPI2 0x08 -#define ENLQOBADQAS 0x04 -#define ENLQOBUSFREE 0x02 -#define ENLQOPHACHGINPKT 0x01 - #define LQOSTAT2 0x56 #define LQOPKT 0xe0 #define LQOWAITFIFO 0x10 @@ -3028,6 +3049,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define ANNEXCOL 0x65 +#define ANNEXDAT 0x66 + #define SCSCHKN 0x66 #define STSELSKIDDIS 0x40 #define CURRFIFODEF 0x20 @@ -3037,8 +3060,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define SHVALIDSTDIS 0x02 #define LSTSGCLRDIS 0x01 -#define ANNEXDAT 0x66 - #define IOWNID 0x67 #define PLL960CTL0 0x68 @@ -3071,10 +3092,10 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define PLL_CNTCLR 0x40 #define PLL_RST 0x01 -#define PLL400CNT0 0x6e - #define UNFAIRNESS 0x6e +#define PLL400CNT0 0x6e + #define HADDR 0x70 #define PLLDELAY 0x70 @@ -3088,14 +3109,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define HODMAEN 0x7a -#define SGHADDR 0x7c - #define SCBHADDR 0x7c -#define SGHCNT 0x84 +#define SGHADDR 0x7c #define SCBHCNT 0x84 +#define SGHCNT 0x84 + #define DFF_THRSH 0x88 #define WR_DFTHRSH 0x70 #define RD_DFTHRSH 0x07 @@ -3113,8 +3134,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define RD_DFTHRSH_63 0x03 #define RD_DFTHRSH_50 0x02 #define RD_DFTHRSH_25 0x01 -#define WR_DFTHRSH_MIN 0x00 #define RD_DFTHRSH_MIN 0x00 +#define WR_DFTHRSH_MIN 0x00 #define ROMADDR 0x8a @@ -3150,20 +3171,22 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define DCH1NSEN 0x02 #define DCH0NSEN 0x01 -#define DCHRXMSG1 0x91 - #define CMCRXMSG1 0x91 -#define DCHRXMSG2 0x92 +#define DCHRXMSG1 0x91 -#define OVLYRXMSG2 0x92 +#define DCHRXMSG2 0x92 #define CMCRXMSG2 0x92 #define OST 0x92 +#define OVLYRXMSG2 0x92 + #define DCHRXMSG3 0x93 +#define OVLYRXMSG3 0x93 + #define CMCRXMSG3 0x93 #define PCIXCTL 0x93 @@ -3175,26 +3198,24 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define TSCSERREN 0x02 #define CMPABCDIS 0x01 -#define OVLYRXMSG3 0x93 - #define OVLYSEQBCNT 0x94 -#define CMCSEQBCNT 0x94 - #define DCHSEQBCNT 0x94 -#define CMCSPLTSTAT0 0x96 +#define CMCSEQBCNT 0x94 -#define OVLYSPLTSTAT0 0x96 +#define CMCSPLTSTAT0 0x96 #define DCHSPLTSTAT0 0x96 -#define DCHSPLTSTAT1 0x97 +#define OVLYSPLTSTAT0 0x96 #define CMCSPLTSTAT1 0x97 #define OVLYSPLTSTAT1 0x97 +#define DCHSPLTSTAT1 0x97 + #define SGRXMSG0 0x98 #define CDNUM 0xf8 #define CFNUM 0x07 @@ -3244,13 +3265,13 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define RXSCEMSG 0x02 #define RXSPLTRSP 0x01 +#define SGSPLTSTAT1 0x9f +#define RXDATABUCKET 0x01 + #define SFUNCT 0x9f #define TEST_GROUP 0xf0 #define TEST_NUM 0x0f -#define SGSPLTSTAT1 0x9f -#define RXDATABUCKET 0x01 - #define DF0PCISTAT 0xa0 #define REG0 0xa0 @@ -3299,10 +3320,10 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define CCSGADDR 0xac -#define CCSCBADDR 0xac - #define CCSCBADR_BK 0xac +#define CCSCBADDR 0xac + #define CMC_RAMBIST 0xad #define SG_ELEMENT_SIZE 0x80 #define SCBRAMBIST_FAIL 0x40 @@ -3311,14 +3332,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define CMC_BUFFER_BIST_FAIL 0x02 #define CMC_BUFFER_BIST_EN 0x01 -#define CCSGCTL 0xad -#define CCSGEN 0x0c -#define CCSGDONE 0x80 -#define SG_CACHE_AVAIL 0x10 -#define CCSGENACK 0x08 -#define SG_FETCH_REQ 0x02 -#define CCSGRESET 0x01 - #define CCSCBCTL 0xad #define CCSCBDONE 0x80 #define ARRDONE 0x40 @@ -3327,6 +3340,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define CCSCBDIR 0x04 #define CCSCBRESET 0x01 +#define CCSGCTL 0xad +#define CCSGEN 0x0c +#define CCSGDONE 0x80 +#define SG_CACHE_AVAIL 0x10 +#define CCSGENACK 0x08 +#define SG_FETCH_REQ 0x02 +#define CCSGRESET 0x01 + #define CCSGRAM 0xb0 #define FLEXADR 0xb0 @@ -3356,8 +3377,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define SEEDAT 0xbc #define SEECTL 0xbe -#define SEEOP_EWEN 0x40 #define SEEOP_WALL 0x40 +#define SEEOP_EWEN 0x40 #define SEEOP_EWDS 0x40 #define SEEOPCODE 0x70 #define SEERST 0x02 @@ -3414,14 +3435,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define WRTBIASCALC 0xc7 -#define DFPTRS 0xc8 - #define RCVRBIASCALC 0xc8 -#define DFBKPTR 0xc9 +#define DFPTRS 0xc8 #define SKEWCALC 0xc9 +#define DFBKPTR 0xc9 + #define DFDBCTL 0xcb #define DFF_CIO_WR_RDY 0x20 #define DFF_CIO_RD_RDY 0x10 @@ -3475,11 +3496,11 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define DINDEX 0xe4 +#define BRKADDR0 0xe6 + #define BRKADDR1 0xe6 #define BRKDIS 0x80 -#define BRKADDR0 0xe6 - #define ALLONES 0xe8 #define ALLZEROS 0xea @@ -3494,14 +3515,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define STACK 0xf2 -#define CURADDR 0xf4 - #define INTVEC1_ADDR 0xf4 -#define INTVEC2_ADDR 0xf6 +#define CURADDR 0xf4 #define LASTADDR 0xf6 +#define INTVEC2_ADDR 0xf6 + #define LONGJMP_ADDR 0xf8 #define ACCUM_SAVE 0xfa @@ -3524,25 +3545,31 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define COMPLETE_DMA_SCB_HEAD 0x12c -#define QFREEZE_COUNT 0x12e +#define COMPLETE_DMA_SCB_TAIL 0x12e + +#define COMPLETE_ON_QFREEZE_HEAD 0x130 + +#define QFREEZE_COUNT 0x132 -#define SAVED_MODE 0x130 +#define KERNEL_QFREEZE_COUNT 0x134 -#define MSG_OUT 0x131 +#define SAVED_MODE 0x136 -#define DMAPARAMS 0x132 +#define MSG_OUT 0x137 + +#define DMAPARAMS 0x138 #define PRELOADEN 0x80 #define WIDEODD 0x40 #define SCSIEN 0x20 #define SDMAEN 0x10 #define SDMAENACK 0x10 -#define HDMAENACK 0x08 #define HDMAEN 0x08 +#define HDMAENACK 0x08 #define DIRECTION 0x04 #define FIFOFLUSH 0x02 #define FIFORESET 0x01 -#define SEQ_FLAGS 0x133 +#define SEQ_FLAGS 0x139 #define NOT_IDENTIFIED 0x80 #define NO_CDB_SENT 0x40 #define TARGET_CMD_IS_TAGGED 0x40 @@ -3553,11 +3580,11 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define SPHASE_PENDING 0x02 #define NO_DISCONNECT 0x01 -#define SAVED_SCSIID 0x134 +#define SAVED_SCSIID 0x13a -#define SAVED_LUN 0x135 +#define SAVED_LUN 0x13b -#define LASTPHASE 0x136 +#define LASTPHASE 0x13c #define PHASE_MASK 0xe0 #define CDI 0x80 #define IOI 0x40 @@ -3572,18 +3599,18 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define P_DATAOUT_DT 0x20 #define P_DATAOUT 0x00 -#define QOUTFIFO_ENTRY_VALID_TAG 0x137 +#define QOUTFIFO_ENTRY_VALID_TAG 0x13d -#define SHARED_DATA_ADDR 0x138 +#define KERNEL_TQINPOS 0x13e -#define QOUTFIFO_NEXT_ADDR 0x13c +#define TQINPOS 0x13f -#define KERNEL_TQINPOS 0x140 +#define SHARED_DATA_ADDR 0x140 -#define TQINPOS 0x141 +#define QOUTFIFO_NEXT_ADDR 0x144 -#define ARG_1 0x142 -#define RETURN_1 0x142 +#define ARG_1 0x148 +#define RETURN_1 0x148 #define SEND_MSG 0x80 #define SEND_SENSE 0x40 #define SEND_REJ 0x20 @@ -3593,12 +3620,12 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define CONT_MSG_LOOP_READ 0x03 #define CONT_MSG_LOOP_TARG 0x02 -#define ARG_2 0x143 -#define RETURN_2 0x143 +#define ARG_2 0x149 +#define RETURN_2 0x149 -#define LAST_MSG 0x144 +#define LAST_MSG 0x14a -#define SCSISEQ_TEMPLATE 0x145 +#define SCSISEQ_TEMPLATE 0x14b #define MANUALCTL 0x40 #define ENSELI 0x20 #define ENRSELI 0x10 @@ -3606,27 +3633,27 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define ENAUTOATNP 0x02 #define ALTSTIM 0x01 -#define INITIATOR_TAG 0x146 +#define INITIATOR_TAG 0x14c -#define SEQ_FLAGS2 0x147 +#define SEQ_FLAGS2 0x14d #define SELECTOUT_QFROZEN 0x04 #define TARGET_MSG_PENDING 0x02 -#define ALLOCFIFO_SCBPTR 0x148 +#define ALLOCFIFO_SCBPTR 0x14e -#define INT_COALESCING_TIMER 0x14a +#define INT_COALESCING_TIMER 0x150 -#define INT_COALESCING_MAXCMDS 0x14c +#define INT_COALESCING_MAXCMDS 0x152 -#define INT_COALESCING_MINCMDS 0x14d +#define INT_COALESCING_MINCMDS 0x153 -#define CMDS_PENDING 0x14e +#define CMDS_PENDING 0x154 -#define INT_COALESCING_CMDCOUNT 0x150 +#define INT_COALESCING_CMDCOUNT 0x156 -#define LOCAL_HS_MAILBOX 0x151 +#define LOCAL_HS_MAILBOX 0x157 -#define CMDSIZE_TABLE 0x152 +#define CMDSIZE_TABLE 0x158 #define SCB_BASE 0x180 @@ -3701,6 +3728,16 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define SCB_DISCONNECTED_LISTS 0x1b8 +#define AHD_TIMER_MAX_US 0x18ffe7 +#define AHD_TIMER_MAX_TICKS 0xffff +#define AHD_SENSE_BUFSIZE 0x100 +#define BUS_8_BIT 0x00 +#define TARGET_CMD_CMPLT 0xfe +#define SEEOP_WRAL_ADDR 0x40 +#define AHD_AMPLITUDE_DEF 0x07 +#define AHD_PRECOMP_CUTBACK_37 0x07 +#define AHD_PRECOMP_SHIFT 0x00 +#define AHD_ANNEXCOL_PRECOMP_SLEW 0x04 #define AHD_TIMER_US_PER_TICK 0x19 #define SCB_TRANSFER_SIZE_FULL_LUN 0x38 #define STATUS_QUEUE_FULL 0x28 @@ -3724,28 +3761,18 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define B_CURRFIFO_0 0x02 #define LUNLEN_SINGLE_LEVEL_LUN 0x0f #define NVRAM_SCB_OFFSET 0x2c -#define AHD_TIMER_MAX_US 0x18ffe7 -#define AHD_TIMER_MAX_TICKS 0xffff #define STATUS_PKT_SENSE 0xff #define CMD_GROUP_CODE_SHIFT 0x05 -#define AHD_SENSE_BUFSIZE 0x100 #define MAX_OFFSET_PACED_BUG 0x7f -#define BUS_8_BIT 0x00 #define STIMESEL_BUG_ADJ 0x08 #define STIMESEL_MIN 0x18 #define STIMESEL_SHIFT 0x03 #define CCSGRAM_MAXSEGS 0x10 #define INVALID_ADDR 0x80 -#define TARGET_CMD_CMPLT 0xfe -#define SEEOP_WRAL_ADDR 0x40 #define SEEOP_ERAL_ADDR 0x80 -#define AHD_AMPLITUDE_DEF 0x07 #define AHD_SLEWRATE_DEF_REVB 0x08 -#define AHD_PRECOMP_CUTBACK_37 0x07 #define AHD_PRECOMP_CUTBACK_17 0x04 -#define AHD_PRECOMP_SHIFT 0x00 #define AHD_PRECOMP_MASK 0x07 -#define AHD_ANNEXCOL_PRECOMP_SLEW 0x04 #define SRC_MODE_SHIFT 0x00 #define PKT_OVERRUN_BUFSIZE 0x200 #define SCB_TRANSFER_SIZE_1BYTE_LUN 0x30 @@ -3761,6 +3788,7 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; /* Downloaded Constant Definitions */ +#define CACHELINE_MASK 0x07 #define SCB_TRANSFER_SIZE 0x06 #define PKT_OVERRUN_BUFOFFSET 0x05 #define SG_SIZEOF 0x04 @@ -3768,9 +3796,9 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print; #define SG_PREFETCH_ALIGN_MASK 0x02 #define SG_PREFETCH_CNT_LIMIT 0x01 #define SG_PREFETCH_CNT 0x00 -#define DOWNLOAD_CONST_COUNT 0x07 +#define DOWNLOAD_CONST_COUNT 0x08 /* Exported Labels */ -#define LABEL_seq_isr 0x269 -#define LABEL_timer_isr 0x265 +#define LABEL_seq_isr 0x285 +#define LABEL_timer_isr 0x281 diff --git a/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped b/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped index 3098a757e3d..a4137c98537 100644 --- a/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped +++ b/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped @@ -2,8 +2,8 @@ * DO NOT EDIT - This file is automatically generated * from the following source files: * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $ - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#118 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#75 $ */ #include "aic79xx_osm.h" @@ -172,21 +172,6 @@ ahd_hs_mailbox_print(u_int regvalue, u_int *cur_col, u_int wrap) 0x0b, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t CLRSEQINTSTAT_parse_table[] = { - { "CLRSEQ_SPLTINT", 0x01, 0x01 }, - { "CLRSEQ_PCIINT", 0x02, 0x02 }, - { "CLRSEQ_SCSIINT", 0x04, 0x04 }, - { "CLRSEQ_SEQINT", 0x08, 0x08 }, - { "CLRSEQ_SWTMRTO", 0x10, 0x10 } -}; - -int -ahd_clrseqintstat_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(CLRSEQINTSTAT_parse_table, 5, "CLRSEQINTSTAT", - 0x0c, regvalue, cur_col, wrap)); -} - static ahd_reg_parse_entry_t SEQINTSTAT_parse_table[] = { { "SEQ_SPLTINT", 0x01, 0x01 }, { "SEQ_PCIINT", 0x02, 0x02 }, @@ -202,6 +187,21 @@ ahd_seqintstat_print(u_int regvalue, u_int *cur_col, u_int wrap) 0x0c, regvalue, cur_col, wrap)); } +static ahd_reg_parse_entry_t CLRSEQINTSTAT_parse_table[] = { + { "CLRSEQ_SPLTINT", 0x01, 0x01 }, + { "CLRSEQ_PCIINT", 0x02, 0x02 }, + { "CLRSEQ_SCSIINT", 0x04, 0x04 }, + { "CLRSEQ_SEQINT", 0x08, 0x08 }, + { "CLRSEQ_SWTMRTO", 0x10, 0x10 } +}; + +int +ahd_clrseqintstat_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(CLRSEQINTSTAT_parse_table, 5, "CLRSEQINTSTAT", + 0x0c, regvalue, cur_col, wrap)); +} + int ahd_swtimer_print(u_int regvalue, u_int *cur_col, u_int wrap) { @@ -670,16 +670,16 @@ ahd_sxfrctl0_print(u_int regvalue, u_int *cur_col, u_int wrap) } int -ahd_businitid_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_dlcount_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "BUSINITID", + return (ahd_print_register(NULL, 0, "DLCOUNT", 0x3c, regvalue, cur_col, wrap)); } int -ahd_dlcount_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_businitid_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "DLCOUNT", + return (ahd_print_register(NULL, 0, "BUSINITID", 0x3c, regvalue, cur_col, wrap)); } @@ -859,21 +859,6 @@ ahd_selid_print(u_int regvalue, u_int *cur_col, u_int wrap) 0x49, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t SBLKCTL_parse_table[] = { - { "SELWIDE", 0x02, 0x02 }, - { "ENAB20", 0x04, 0x04 }, - { "ENAB40", 0x08, 0x08 }, - { "DIAGLEDON", 0x40, 0x40 }, - { "DIAGLEDEN", 0x80, 0x80 } -}; - -int -ahd_sblkctl_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(SBLKCTL_parse_table, 5, "SBLKCTL", - 0x4a, regvalue, cur_col, wrap)); -} - static ahd_reg_parse_entry_t OPTIONMODE_parse_table[] = { { "AUTO_MSGOUT_DE", 0x02, 0x02 }, { "ENDGFORMCHK", 0x04, 0x04 }, @@ -891,22 +876,19 @@ ahd_optionmode_print(u_int regvalue, u_int *cur_col, u_int wrap) 0x4a, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t SSTAT0_parse_table[] = { - { "ARBDO", 0x01, 0x01 }, - { "SPIORDY", 0x02, 0x02 }, - { "OVERRUN", 0x04, 0x04 }, - { "IOERR", 0x08, 0x08 }, - { "SELINGO", 0x10, 0x10 }, - { "SELDI", 0x20, 0x20 }, - { "SELDO", 0x40, 0x40 }, - { "TARGET", 0x80, 0x80 } +static ahd_reg_parse_entry_t SBLKCTL_parse_table[] = { + { "SELWIDE", 0x02, 0x02 }, + { "ENAB20", 0x04, 0x04 }, + { "ENAB40", 0x08, 0x08 }, + { "DIAGLEDON", 0x40, 0x40 }, + { "DIAGLEDEN", 0x80, 0x80 } }; int -ahd_sstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_sblkctl_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(SSTAT0_parse_table, 8, "SSTAT0", - 0x4b, regvalue, cur_col, wrap)); + return (ahd_print_register(SBLKCTL_parse_table, 5, "SBLKCTL", + 0x4a, regvalue, cur_col, wrap)); } static ahd_reg_parse_entry_t CLRSINT0_parse_table[] = { @@ -926,6 +908,24 @@ ahd_clrsint0_print(u_int regvalue, u_int *cur_col, u_int wrap) 0x4b, regvalue, cur_col, wrap)); } +static ahd_reg_parse_entry_t SSTAT0_parse_table[] = { + { "ARBDO", 0x01, 0x01 }, + { "SPIORDY", 0x02, 0x02 }, + { "OVERRUN", 0x04, 0x04 }, + { "IOERR", 0x08, 0x08 }, + { "SELINGO", 0x10, 0x10 }, + { "SELDI", 0x20, 0x20 }, + { "SELDO", 0x40, 0x40 }, + { "TARGET", 0x80, 0x80 } +}; + +int +ahd_sstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(SSTAT0_parse_table, 8, "SSTAT0", + 0x4b, regvalue, cur_col, wrap)); +} + static ahd_reg_parse_entry_t SIMODE0_parse_table[] = { { "ENARBDO", 0x01, 0x01 }, { "ENSPIORDY", 0x02, 0x02 }, @@ -998,30 +998,30 @@ ahd_sstat2_print(u_int regvalue, u_int *cur_col, u_int wrap) 0x4d, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t CLRSINT2_parse_table[] = { - { "CLRDMADONE", 0x01, 0x01 }, - { "CLRSDONE", 0x02, 0x02 }, - { "CLRWIDE_RES", 0x04, 0x04 }, - { "CLRNONPACKREQ", 0x20, 0x20 } +static ahd_reg_parse_entry_t SIMODE2_parse_table[] = { + { "ENDMADONE", 0x01, 0x01 }, + { "ENSDONE", 0x02, 0x02 }, + { "ENWIDE_RES", 0x04, 0x04 } }; int -ahd_clrsint2_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_simode2_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(CLRSINT2_parse_table, 4, "CLRSINT2", + return (ahd_print_register(SIMODE2_parse_table, 3, "SIMODE2", 0x4d, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t SIMODE2_parse_table[] = { - { "ENDMADONE", 0x01, 0x01 }, - { "ENSDONE", 0x02, 0x02 }, - { "ENWIDE_RES", 0x04, 0x04 } +static ahd_reg_parse_entry_t CLRSINT2_parse_table[] = { + { "CLRDMADONE", 0x01, 0x01 }, + { "CLRSDONE", 0x02, 0x02 }, + { "CLRWIDE_RES", 0x04, 0x04 }, + { "CLRNONPACKREQ", 0x20, 0x20 } }; int -ahd_simode2_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_clrsint2_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(SIMODE2_parse_table, 3, "SIMODE2", + return (ahd_print_register(CLRSINT2_parse_table, 4, "CLRSINT2", 0x4d, regvalue, cur_col, wrap)); } @@ -1220,21 +1220,6 @@ ahd_clrsint3_print(u_int regvalue, u_int *cur_col, u_int wrap) 0x53, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t LQOMODE0_parse_table[] = { - { "ENLQOTCRC", 0x01, 0x01 }, - { "ENLQOATNPKT", 0x02, 0x02 }, - { "ENLQOATNLQ", 0x04, 0x04 }, - { "ENLQOSTOPT2", 0x08, 0x08 }, - { "ENLQOTARGSCBPERR", 0x10, 0x10 } -}; - -int -ahd_lqomode0_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(LQOMODE0_parse_table, 5, "LQOMODE0", - 0x54, regvalue, cur_col, wrap)); -} - static ahd_reg_parse_entry_t LQOSTAT0_parse_table[] = { { "LQOTCRC", 0x01, 0x01 }, { "LQOATNPKT", 0x02, 0x02 }, @@ -1265,6 +1250,36 @@ ahd_clrlqoint0_print(u_int regvalue, u_int *cur_col, u_int wrap) 0x54, regvalue, cur_col, wrap)); } +static ahd_reg_parse_entry_t LQOMODE0_parse_table[] = { + { "ENLQOTCRC", 0x01, 0x01 }, + { "ENLQOATNPKT", 0x02, 0x02 }, + { "ENLQOATNLQ", 0x04, 0x04 }, + { "ENLQOSTOPT2", 0x08, 0x08 }, + { "ENLQOTARGSCBPERR", 0x10, 0x10 } +}; + +int +ahd_lqomode0_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(LQOMODE0_parse_table, 5, "LQOMODE0", + 0x54, regvalue, cur_col, wrap)); +} + +static ahd_reg_parse_entry_t LQOMODE1_parse_table[] = { + { "ENLQOPHACHGINPKT", 0x01, 0x01 }, + { "ENLQOBUSFREE", 0x02, 0x02 }, + { "ENLQOBADQAS", 0x04, 0x04 }, + { "ENLQOSTOPI2", 0x08, 0x08 }, + { "ENLQOINITSCBPERR", 0x10, 0x10 } +}; + +int +ahd_lqomode1_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(LQOMODE1_parse_table, 5, "LQOMODE1", + 0x55, regvalue, cur_col, wrap)); +} + static ahd_reg_parse_entry_t LQOSTAT1_parse_table[] = { { "LQOPHACHGINPKT", 0x01, 0x01 }, { "LQOBUSFREE", 0x02, 0x02 }, @@ -1295,21 +1310,6 @@ ahd_clrlqoint1_print(u_int regvalue, u_int *cur_col, u_int wrap) 0x55, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t LQOMODE1_parse_table[] = { - { "ENLQOPHACHGINPKT", 0x01, 0x01 }, - { "ENLQOBUSFREE", 0x02, 0x02 }, - { "ENLQOBADQAS", 0x04, 0x04 }, - { "ENLQOSTOPI2", 0x08, 0x08 }, - { "ENLQOINITSCBPERR", 0x10, 0x10 } -}; - -int -ahd_lqomode1_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(LQOMODE1_parse_table, 5, "LQOMODE1", - 0x55, regvalue, cur_col, wrap)); -} - static ahd_reg_parse_entry_t LQOSTAT2_parse_table[] = { { "LQOSTOP0", 0x01, 0x01 }, { "LQOPHACHGOUTPKT", 0x02, 0x02 }, @@ -1594,6 +1594,13 @@ ahd_annexcol_print(u_int regvalue, u_int *cur_col, u_int wrap) 0x65, regvalue, cur_col, wrap)); } +int +ahd_annexdat_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(NULL, 0, "ANNEXDAT", + 0x66, regvalue, cur_col, wrap)); +} + static ahd_reg_parse_entry_t SCSCHKN_parse_table[] = { { "LSTSGCLRDIS", 0x01, 0x01 }, { "SHVALIDSTDIS", 0x02, 0x02 }, @@ -1611,13 +1618,6 @@ ahd_scschkn_print(u_int regvalue, u_int *cur_col, u_int wrap) 0x66, regvalue, cur_col, wrap)); } -int -ahd_annexdat_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(NULL, 0, "ANNEXDAT", - 0x66, regvalue, cur_col, wrap)); -} - int ahd_iownid_print(u_int regvalue, u_int *cur_col, u_int wrap) { @@ -1728,16 +1728,16 @@ ahd_pll400ctl1_print(u_int regvalue, u_int *cur_col, u_int wrap) } int -ahd_pll400cnt0_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_unfairness_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "PLL400CNT0", + return (ahd_print_register(NULL, 0, "UNFAIRNESS", 0x6e, regvalue, cur_col, wrap)); } int -ahd_unfairness_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_pll400cnt0_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "UNFAIRNESS", + return (ahd_print_register(NULL, 0, "PLL400CNT0", 0x6e, regvalue, cur_col, wrap)); } @@ -1788,30 +1788,30 @@ ahd_hodmaen_print(u_int regvalue, u_int *cur_col, u_int wrap) } int -ahd_sghaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_scbhaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "SGHADDR", + return (ahd_print_register(NULL, 0, "SCBHADDR", 0x7c, regvalue, cur_col, wrap)); } int -ahd_scbhaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_sghaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "SCBHADDR", + return (ahd_print_register(NULL, 0, "SGHADDR", 0x7c, regvalue, cur_col, wrap)); } int -ahd_sghcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_scbhcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "SGHCNT", + return (ahd_print_register(NULL, 0, "SCBHCNT", 0x84, regvalue, cur_col, wrap)); } int -ahd_scbhcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_sghcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "SCBHCNT", + return (ahd_print_register(NULL, 0, "SGHCNT", 0x84, regvalue, cur_col, wrap)); } @@ -1950,25 +1950,25 @@ ahd_nsenable_print(u_int regvalue, u_int *cur_col, u_int wrap) 0x91, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t DCHRXMSG1_parse_table[] = { +static ahd_reg_parse_entry_t CMCRXMSG1_parse_table[] = { { "CBNUM", 0xff, 0xff } }; int -ahd_dchrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_cmcrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(DCHRXMSG1_parse_table, 1, "DCHRXMSG1", + return (ahd_print_register(CMCRXMSG1_parse_table, 1, "CMCRXMSG1", 0x91, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t CMCRXMSG1_parse_table[] = { +static ahd_reg_parse_entry_t DCHRXMSG1_parse_table[] = { { "CBNUM", 0xff, 0xff } }; int -ahd_cmcrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_dchrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(CMCRXMSG1_parse_table, 1, "CMCRXMSG1", + return (ahd_print_register(DCHRXMSG1_parse_table, 1, "DCHRXMSG1", 0x91, regvalue, cur_col, wrap)); } @@ -1983,17 +1983,6 @@ ahd_dchrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap) 0x92, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t OVLYRXMSG2_parse_table[] = { - { "MINDEX", 0xff, 0xff } -}; - -int -ahd_ovlyrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(OVLYRXMSG2_parse_table, 1, "OVLYRXMSG2", - 0x92, regvalue, cur_col, wrap)); -} - static ahd_reg_parse_entry_t CMCRXMSG2_parse_table[] = { { "MINDEX", 0xff, 0xff } }; @@ -2012,6 +2001,17 @@ ahd_ost_print(u_int regvalue, u_int *cur_col, u_int wrap) 0x92, regvalue, cur_col, wrap)); } +static ahd_reg_parse_entry_t OVLYRXMSG2_parse_table[] = { + { "MINDEX", 0xff, 0xff } +}; + +int +ahd_ovlyrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(OVLYRXMSG2_parse_table, 1, "OVLYRXMSG2", + 0x92, regvalue, cur_col, wrap)); +} + static ahd_reg_parse_entry_t DCHRXMSG3_parse_table[] = { { "MCLASS", 0x0f, 0x0f } }; @@ -2023,6 +2023,17 @@ ahd_dchrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap) 0x93, regvalue, cur_col, wrap)); } +static ahd_reg_parse_entry_t OVLYRXMSG3_parse_table[] = { + { "MCLASS", 0x0f, 0x0f } +}; + +int +ahd_ovlyrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(OVLYRXMSG3_parse_table, 1, "OVLYRXMSG3", + 0x93, regvalue, cur_col, wrap)); +} + static ahd_reg_parse_entry_t CMCRXMSG3_parse_table[] = { { "MCLASS", 0x0f, 0x0f } }; @@ -2051,17 +2062,6 @@ ahd_pcixctl_print(u_int regvalue, u_int *cur_col, u_int wrap) 0x93, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t OVLYRXMSG3_parse_table[] = { - { "MCLASS", 0x0f, 0x0f } -}; - -int -ahd_ovlyrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(OVLYRXMSG3_parse_table, 1, "OVLYRXMSG3", - 0x93, regvalue, cur_col, wrap)); -} - int ahd_ovlyseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) { @@ -2070,16 +2070,16 @@ ahd_ovlyseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) } int -ahd_cmcseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_dchseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "CMCSEQBCNT", + return (ahd_print_register(NULL, 0, "DCHSEQBCNT", 0x94, regvalue, cur_col, wrap)); } int -ahd_dchseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_cmcseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "DCHSEQBCNT", + return (ahd_print_register(NULL, 0, "CMCSEQBCNT", 0x94, regvalue, cur_col, wrap)); } @@ -2101,7 +2101,7 @@ ahd_cmcspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) 0x96, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t OVLYSPLTSTAT0_parse_table[] = { +static ahd_reg_parse_entry_t DCHSPLTSTAT0_parse_table[] = { { "RXSPLTRSP", 0x01, 0x01 }, { "RXSCEMSG", 0x02, 0x02 }, { "RXOVRUN", 0x04, 0x04 }, @@ -2113,13 +2113,13 @@ static ahd_reg_parse_entry_t OVLYSPLTSTAT0_parse_table[] = { }; int -ahd_ovlyspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_dchspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(OVLYSPLTSTAT0_parse_table, 8, "OVLYSPLTSTAT0", + return (ahd_print_register(DCHSPLTSTAT0_parse_table, 8, "DCHSPLTSTAT0", 0x96, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t DCHSPLTSTAT0_parse_table[] = { +static ahd_reg_parse_entry_t OVLYSPLTSTAT0_parse_table[] = { { "RXSPLTRSP", 0x01, 0x01 }, { "RXSCEMSG", 0x02, 0x02 }, { "RXOVRUN", 0x04, 0x04 }, @@ -2131,42 +2131,42 @@ static ahd_reg_parse_entry_t DCHSPLTSTAT0_parse_table[] = { }; int -ahd_dchspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_ovlyspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(DCHSPLTSTAT0_parse_table, 8, "DCHSPLTSTAT0", + return (ahd_print_register(OVLYSPLTSTAT0_parse_table, 8, "OVLYSPLTSTAT0", 0x96, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t DCHSPLTSTAT1_parse_table[] = { +static ahd_reg_parse_entry_t CMCSPLTSTAT1_parse_table[] = { { "RXDATABUCKET", 0x01, 0x01 } }; int -ahd_dchspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_cmcspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(DCHSPLTSTAT1_parse_table, 1, "DCHSPLTSTAT1", + return (ahd_print_register(CMCSPLTSTAT1_parse_table, 1, "CMCSPLTSTAT1", 0x97, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t CMCSPLTSTAT1_parse_table[] = { +static ahd_reg_parse_entry_t OVLYSPLTSTAT1_parse_table[] = { { "RXDATABUCKET", 0x01, 0x01 } }; int -ahd_cmcspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_ovlyspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(CMCSPLTSTAT1_parse_table, 1, "CMCSPLTSTAT1", + return (ahd_print_register(OVLYSPLTSTAT1_parse_table, 1, "OVLYSPLTSTAT1", 0x97, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t OVLYSPLTSTAT1_parse_table[] = { +static ahd_reg_parse_entry_t DCHSPLTSTAT1_parse_table[] = { { "RXDATABUCKET", 0x01, 0x01 } }; int -ahd_ovlyspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_dchspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(OVLYSPLTSTAT1_parse_table, 1, "OVLYSPLTSTAT1", + return (ahd_print_register(DCHSPLTSTAT1_parse_table, 1, "DCHSPLTSTAT1", 0x97, regvalue, cur_col, wrap)); } @@ -2320,26 +2320,26 @@ ahd_sgspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap) 0x9e, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t SFUNCT_parse_table[] = { - { "TEST_NUM", 0x0f, 0x0f }, - { "TEST_GROUP", 0xf0, 0xf0 } +static ahd_reg_parse_entry_t SGSPLTSTAT1_parse_table[] = { + { "RXDATABUCKET", 0x01, 0x01 } }; int -ahd_sfunct_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_sgspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(SFUNCT_parse_table, 2, "SFUNCT", + return (ahd_print_register(SGSPLTSTAT1_parse_table, 1, "SGSPLTSTAT1", 0x9f, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t SGSPLTSTAT1_parse_table[] = { - { "RXDATABUCKET", 0x01, 0x01 } +static ahd_reg_parse_entry_t SFUNCT_parse_table[] = { + { "TEST_NUM", 0x0f, 0x0f }, + { "TEST_GROUP", 0xf0, 0xf0 } }; int -ahd_sgspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_sfunct_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(SGSPLTSTAT1_parse_table, 1, "SGSPLTSTAT1", + return (ahd_print_register(SFUNCT_parse_table, 2, "SFUNCT", 0x9f, regvalue, cur_col, wrap)); } @@ -2537,16 +2537,16 @@ ahd_ccsgaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) } int -ahd_ccscbaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_ccscbadr_bk_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "CCSCBADDR", + return (ahd_print_register(NULL, 0, "CCSCBADR_BK", 0xac, regvalue, cur_col, wrap)); } int -ahd_ccscbadr_bk_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_ccscbaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "CCSCBADR_BK", + return (ahd_print_register(NULL, 0, "CCSCBADDR", 0xac, regvalue, cur_col, wrap)); } @@ -2566,22 +2566,6 @@ ahd_cmc_rambist_print(u_int regvalue, u_int *cur_col, u_int wrap) 0xad, regvalue, cur_col, wrap)); } -static ahd_reg_parse_entry_t CCSGCTL_parse_table[] = { - { "CCSGRESET", 0x01, 0x01 }, - { "SG_FETCH_REQ", 0x02, 0x02 }, - { "CCSGENACK", 0x08, 0x08 }, - { "SG_CACHE_AVAIL", 0x10, 0x10 }, - { "CCSGDONE", 0x80, 0x80 }, - { "CCSGEN", 0x0c, 0x0c } -}; - -int -ahd_ccsgctl_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(CCSGCTL_parse_table, 6, "CCSGCTL", - 0xad, regvalue, cur_col, wrap)); -} - static ahd_reg_parse_entry_t CCSCBCTL_parse_table[] = { { "CCSCBRESET", 0x01, 0x01 }, { "CCSCBDIR", 0x04, 0x04 }, @@ -2598,6 +2582,22 @@ ahd_ccscbctl_print(u_int regvalue, u_int *cur_col, u_int wrap) 0xad, regvalue, cur_col, wrap)); } +static ahd_reg_parse_entry_t CCSGCTL_parse_table[] = { + { "CCSGRESET", 0x01, 0x01 }, + { "SG_FETCH_REQ", 0x02, 0x02 }, + { "CCSGENACK", 0x08, 0x08 }, + { "SG_CACHE_AVAIL", 0x10, 0x10 }, + { "CCSGDONE", 0x80, 0x80 }, + { "CCSGEN", 0x0c, 0x0c } +}; + +int +ahd_ccsgctl_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(CCSGCTL_parse_table, 6, "CCSGCTL", + 0xad, regvalue, cur_col, wrap)); +} + int ahd_ccsgram_print(u_int regvalue, u_int *cur_col, u_int wrap) { @@ -2841,30 +2841,30 @@ ahd_wrtbiascalc_print(u_int regvalue, u_int *cur_col, u_int wrap) } int -ahd_dfptrs_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_rcvrbiascalc_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "DFPTRS", + return (ahd_print_register(NULL, 0, "RCVRBIASCALC", 0xc8, regvalue, cur_col, wrap)); } int -ahd_rcvrbiascalc_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_dfptrs_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "RCVRBIASCALC", + return (ahd_print_register(NULL, 0, "DFPTRS", 0xc8, regvalue, cur_col, wrap)); } int -ahd_dfbkptr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_skewcalc_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "DFBKPTR", + return (ahd_print_register(NULL, 0, "SKEWCALC", 0xc9, regvalue, cur_col, wrap)); } int -ahd_skewcalc_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_dfbkptr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "SKEWCALC", + return (ahd_print_register(NULL, 0, "DFBKPTR", 0xc9, regvalue, cur_col, wrap)); } @@ -3001,6 +3001,13 @@ ahd_dindex_print(u_int regvalue, u_int *cur_col, u_int wrap) 0xe4, regvalue, cur_col, wrap)); } +int +ahd_brkaddr0_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(NULL, 0, "BRKADDR0", + 0xe6, regvalue, cur_col, wrap)); +} + static ahd_reg_parse_entry_t BRKADDR1_parse_table[] = { { "BRKDIS", 0x80, 0x80 } }; @@ -3012,13 +3019,6 @@ ahd_brkaddr1_print(u_int regvalue, u_int *cur_col, u_int wrap) 0xe6, regvalue, cur_col, wrap)); } -int -ahd_brkaddr0_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(NULL, 0, "BRKADDR0", - 0xe6, regvalue, cur_col, wrap)); -} - int ahd_allones_print(u_int regvalue, u_int *cur_col, u_int wrap) { @@ -3069,30 +3069,30 @@ ahd_stack_print(u_int regvalue, u_int *cur_col, u_int wrap) } int -ahd_curaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_intvec1_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "CURADDR", + return (ahd_print_register(NULL, 0, "INTVEC1_ADDR", 0xf4, regvalue, cur_col, wrap)); } int -ahd_intvec1_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_curaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "INTVEC1_ADDR", + return (ahd_print_register(NULL, 0, "CURADDR", 0xf4, regvalue, cur_col, wrap)); } int -ahd_intvec2_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_lastaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "INTVEC2_ADDR", + return (ahd_print_register(NULL, 0, "LASTADDR", 0xf6, regvalue, cur_col, wrap)); } int -ahd_lastaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_intvec2_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "LASTADDR", + return (ahd_print_register(NULL, 0, "INTVEC2_ADDR", 0xf6, regvalue, cur_col, wrap)); } @@ -3173,25 +3173,46 @@ ahd_complete_dma_scb_head_print(u_int regvalue, u_int *cur_col, u_int wrap) 0x12c, regvalue, cur_col, wrap)); } +int +ahd_complete_dma_scb_tail_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(NULL, 0, "COMPLETE_DMA_SCB_TAIL", + 0x12e, regvalue, cur_col, wrap)); +} + +int +ahd_complete_on_qfreeze_head_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(NULL, 0, "COMPLETE_ON_QFREEZE_HEAD", + 0x130, regvalue, cur_col, wrap)); +} + int ahd_qfreeze_count_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "QFREEZE_COUNT", - 0x12e, regvalue, cur_col, wrap)); + 0x132, regvalue, cur_col, wrap)); +} + +int +ahd_kernel_qfreeze_count_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(NULL, 0, "KERNEL_QFREEZE_COUNT", + 0x134, regvalue, cur_col, wrap)); } int ahd_saved_mode_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "SAVED_MODE", - 0x130, regvalue, cur_col, wrap)); + 0x136, regvalue, cur_col, wrap)); } int ahd_msg_out_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "MSG_OUT", - 0x131, regvalue, cur_col, wrap)); + 0x137, regvalue, cur_col, wrap)); } static ahd_reg_parse_entry_t DMAPARAMS_parse_table[] = { @@ -3211,7 +3232,7 @@ int ahd_dmaparams_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(DMAPARAMS_parse_table, 10, "DMAPARAMS", - 0x132, regvalue, cur_col, wrap)); + 0x138, regvalue, cur_col, wrap)); } static ahd_reg_parse_entry_t SEQ_FLAGS_parse_table[] = { @@ -3230,21 +3251,21 @@ int ahd_seq_flags_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(SEQ_FLAGS_parse_table, 9, "SEQ_FLAGS", - 0x133, regvalue, cur_col, wrap)); + 0x139, regvalue, cur_col, wrap)); } int ahd_saved_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "SAVED_SCSIID", - 0x134, regvalue, cur_col, wrap)); + 0x13a, regvalue, cur_col, wrap)); } int ahd_saved_lun_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "SAVED_LUN", - 0x135, regvalue, cur_col, wrap)); + 0x13b, regvalue, cur_col, wrap)); } static ahd_reg_parse_entry_t LASTPHASE_parse_table[] = { @@ -3267,42 +3288,42 @@ int ahd_lastphase_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(LASTPHASE_parse_table, 13, "LASTPHASE", - 0x136, regvalue, cur_col, wrap)); + 0x13c, regvalue, cur_col, wrap)); } int ahd_qoutfifo_entry_valid_tag_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "QOUTFIFO_ENTRY_VALID_TAG", - 0x137, regvalue, cur_col, wrap)); + 0x13d, regvalue, cur_col, wrap)); } int -ahd_shared_data_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_kernel_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "SHARED_DATA_ADDR", - 0x138, regvalue, cur_col, wrap)); + return (ahd_print_register(NULL, 0, "KERNEL_TQINPOS", + 0x13e, regvalue, cur_col, wrap)); } int -ahd_qoutfifo_next_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR", - 0x13c, regvalue, cur_col, wrap)); + return (ahd_print_register(NULL, 0, "TQINPOS", + 0x13f, regvalue, cur_col, wrap)); } int -ahd_kernel_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_shared_data_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "KERNEL_TQINPOS", + return (ahd_print_register(NULL, 0, "SHARED_DATA_ADDR", 0x140, regvalue, cur_col, wrap)); } int -ahd_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_qoutfifo_next_addr_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "TQINPOS", - 0x141, regvalue, cur_col, wrap)); + return (ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR", + 0x144, regvalue, cur_col, wrap)); } static ahd_reg_parse_entry_t ARG_1_parse_table[] = { @@ -3320,21 +3341,21 @@ int ahd_arg_1_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(ARG_1_parse_table, 8, "ARG_1", - 0x142, regvalue, cur_col, wrap)); + 0x148, regvalue, cur_col, wrap)); } int ahd_arg_2_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "ARG_2", - 0x143, regvalue, cur_col, wrap)); + 0x149, regvalue, cur_col, wrap)); } int ahd_last_msg_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "LAST_MSG", - 0x144, regvalue, cur_col, wrap)); + 0x14a, regvalue, cur_col, wrap)); } static ahd_reg_parse_entry_t SCSISEQ_TEMPLATE_parse_table[] = { @@ -3350,14 +3371,14 @@ int ahd_scsiseq_template_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(SCSISEQ_TEMPLATE_parse_table, 6, "SCSISEQ_TEMPLATE", - 0x145, regvalue, cur_col, wrap)); + 0x14b, regvalue, cur_col, wrap)); } int ahd_initiator_tag_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "INITIATOR_TAG", - 0x146, regvalue, cur_col, wrap)); + 0x14c, regvalue, cur_col, wrap)); } static ahd_reg_parse_entry_t SEQ_FLAGS2_parse_table[] = { @@ -3369,63 +3390,63 @@ int ahd_seq_flags2_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(SEQ_FLAGS2_parse_table, 2, "SEQ_FLAGS2", - 0x147, regvalue, cur_col, wrap)); + 0x14d, regvalue, cur_col, wrap)); } int ahd_allocfifo_scbptr_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "ALLOCFIFO_SCBPTR", - 0x148, regvalue, cur_col, wrap)); + 0x14e, regvalue, cur_col, wrap)); } int ahd_int_coalescing_timer_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "INT_COALESCING_TIMER", - 0x14a, regvalue, cur_col, wrap)); + 0x150, regvalue, cur_col, wrap)); } int ahd_int_coalescing_maxcmds_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "INT_COALESCING_MAXCMDS", - 0x14c, regvalue, cur_col, wrap)); + 0x152, regvalue, cur_col, wrap)); } int ahd_int_coalescing_mincmds_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "INT_COALESCING_MINCMDS", - 0x14d, regvalue, cur_col, wrap)); + 0x153, regvalue, cur_col, wrap)); } int ahd_cmds_pending_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "CMDS_PENDING", - 0x14e, regvalue, cur_col, wrap)); + 0x154, regvalue, cur_col, wrap)); } int ahd_int_coalescing_cmdcount_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "INT_COALESCING_CMDCOUNT", - 0x150, regvalue, cur_col, wrap)); + 0x156, regvalue, cur_col, wrap)); } int ahd_local_hs_mailbox_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "LOCAL_HS_MAILBOX", - 0x151, regvalue, cur_col, wrap)); + 0x157, regvalue, cur_col, wrap)); } int ahd_cmdsize_table_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "CMDSIZE_TABLE", - 0x152, regvalue, cur_col, wrap)); + 0x158, regvalue, cur_col, wrap)); } int diff --git a/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped b/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped index 77c471f934e..b1e5365be23 100644 --- a/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped +++ b/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped @@ -2,215 +2,228 @@ * DO NOT EDIT - This file is automatically generated * from the following source files: * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $ - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $ */ static uint8_t seqprog[] = { 0xff, 0x02, 0x06, 0x78, - 0x00, 0xea, 0x50, 0x59, + 0x00, 0xea, 0x64, 0x59, 0x01, 0xea, 0x04, 0x30, 0xff, 0x04, 0x0c, 0x78, - 0x19, 0xea, 0x50, 0x59, + 0x19, 0xea, 0x64, 0x59, 0x19, 0xea, 0x04, 0x00, - 0x33, 0xea, 0x44, 0x59, + 0x33, 0xea, 0x5e, 0x59, 0x33, 0xea, 0x00, 0x00, - 0x60, 0x3a, 0x1a, 0x68, - 0x04, 0x47, 0x1b, 0x68, - 0xff, 0x21, 0x1b, 0x70, - 0x40, 0x4b, 0x92, 0x69, - 0x00, 0xe2, 0x54, 0x59, - 0x40, 0x4b, 0x92, 0x69, - 0x20, 0x4b, 0x82, 0x69, - 0xfc, 0x42, 0x24, 0x78, - 0x10, 0x40, 0x24, 0x78, - 0x00, 0xe2, 0xc4, 0x5d, - 0x20, 0x4d, 0x28, 0x78, - 0x00, 0xe2, 0xc4, 0x5d, + 0x60, 0x3a, 0x3a, 0x68, + 0x04, 0x4d, 0x35, 0x78, + 0x01, 0x34, 0xc1, 0x31, + 0x00, 0x32, 0x21, 0x60, + 0x01, 0x35, 0xc1, 0x31, + 0x00, 0x33, 0x21, 0x60, + 0xfb, 0x4d, 0x9b, 0x0a, + 0x00, 0xe2, 0x34, 0x40, + 0x50, 0x4b, 0x3a, 0x68, + 0xff, 0x31, 0x3b, 0x70, + 0x02, 0x30, 0x51, 0x31, + 0xff, 0x8d, 0x2d, 0x70, + 0x02, 0x8c, 0x51, 0x31, + 0xff, 0x8d, 0x29, 0x60, + 0x02, 0x28, 0x19, 0x33, + 0x02, 0x30, 0x51, 0x32, + 0xff, 0xea, 0x62, 0x02, + 0x00, 0xe2, 0x3a, 0x40, + 0xff, 0x21, 0x3b, 0x70, + 0x40, 0x4b, 0xaa, 0x69, + 0x00, 0xe2, 0x68, 0x59, + 0x40, 0x4b, 0xaa, 0x69, + 0x20, 0x4b, 0x96, 0x69, + 0xfc, 0x42, 0x44, 0x78, + 0x10, 0x40, 0x44, 0x78, + 0x00, 0xe2, 0xfc, 0x5d, + 0x20, 0x4d, 0x48, 0x78, + 0x00, 0xe2, 0xfc, 0x5d, 0x30, 0x3f, 0xc0, 0x09, - 0x30, 0xe0, 0x30, 0x60, + 0x30, 0xe0, 0x50, 0x60, 0x7f, 0x4a, 0x94, 0x08, - 0x00, 0xe2, 0x32, 0x40, + 0x00, 0xe2, 0x52, 0x40, 0xc0, 0x4a, 0x94, 0x00, - 0x00, 0xe2, 0x3e, 0x58, - 0x00, 0xe2, 0x56, 0x58, - 0x00, 0xe2, 0x66, 0x58, + 0x00, 0xe2, 0x5e, 0x58, + 0x00, 0xe2, 0x76, 0x58, + 0x00, 0xe2, 0x86, 0x58, 0x00, 0xe2, 0x06, 0x40, - 0x33, 0xea, 0x44, 0x59, + 0x33, 0xea, 0x5e, 0x59, 0x33, 0xea, 0x00, 0x00, - 0x01, 0x52, 0x64, 0x78, + 0x01, 0x52, 0x84, 0x78, 0x02, 0x58, 0x50, 0x31, 0xff, 0xea, 0x10, 0x0b, - 0xff, 0x97, 0x4f, 0x78, - 0x50, 0x4b, 0x4a, 0x68, + 0xff, 0x97, 0x6f, 0x78, + 0x50, 0x4b, 0x6a, 0x68, 0xbf, 0x3a, 0x74, 0x08, - 0x14, 0xea, 0x50, 0x59, + 0x14, 0xea, 0x64, 0x59, 0x14, 0xea, 0x04, 0x00, 0x08, 0x92, 0x25, 0x03, - 0xff, 0x90, 0x3f, 0x68, - 0x00, 0xe2, 0x56, 0x5b, - 0x00, 0xe2, 0x3e, 0x40, - 0x00, 0xea, 0x44, 0x59, + 0xff, 0x90, 0x5f, 0x68, + 0x00, 0xe2, 0x76, 0x5b, + 0x00, 0xe2, 0x5e, 0x40, + 0x00, 0xea, 0x5e, 0x59, 0x01, 0xea, 0x00, 0x30, - 0x80, 0xf9, 0x5e, 0x68, - 0x00, 0xe2, 0x42, 0x59, - 0x11, 0xea, 0x44, 0x59, + 0x80, 0xf9, 0x7e, 0x68, + 0x00, 0xe2, 0x5c, 0x59, + 0x11, 0xea, 0x5e, 0x59, 0x11, 0xea, 0x00, 0x00, - 0x80, 0xf9, 0x42, 0x79, + 0x80, 0xf9, 0x5c, 0x79, 0xff, 0xea, 0xd4, 0x0d, - 0x22, 0xea, 0x44, 0x59, + 0x22, 0xea, 0x5e, 0x59, 0x22, 0xea, 0x00, 0x00, - 0x10, 0x16, 0x70, 0x78, - 0x01, 0x0b, 0xa2, 0x32, + 0x10, 0x16, 0x90, 0x78, 0x10, 0x16, 0x2c, 0x00, - 0x18, 0xad, 0x00, 0x79, - 0x04, 0xad, 0xca, 0x68, - 0x80, 0xad, 0x64, 0x78, - 0x10, 0xad, 0x98, 0x78, - 0xff, 0x88, 0x83, 0x68, + 0x01, 0x0b, 0xae, 0x32, + 0x18, 0xad, 0x12, 0x79, + 0x04, 0xad, 0xdc, 0x68, + 0x80, 0xad, 0x84, 0x78, + 0x10, 0xad, 0xaa, 0x78, 0xe7, 0xad, 0x5a, 0x09, 0x02, 0x8c, 0x59, 0x32, + 0xff, 0x8d, 0xa1, 0x60, + 0xff, 0xea, 0x5e, 0x02, + 0xff, 0x88, 0xa7, 0x78, + 0x02, 0x30, 0x19, 0x33, + 0x02, 0xa8, 0x60, 0x36, 0x02, 0x28, 0x19, 0x33, 0x02, 0xa8, 0x50, 0x36, - 0x33, 0xea, 0x44, 0x59, - 0x33, 0xea, 0x00, 0x00, - 0x40, 0x3a, 0x64, 0x68, - 0x50, 0x4b, 0x64, 0x68, - 0x22, 0xea, 0x44, 0x59, - 0x22, 0xea, 0x00, 0x00, - 0xe7, 0xad, 0x5a, 0x09, - 0x02, 0x8c, 0x59, 0x32, - 0x1a, 0xea, 0x50, 0x59, - 0x1a, 0xea, 0x04, 0x00, - 0xff, 0xea, 0xd4, 0x0d, 0xe7, 0xad, 0x5a, 0x09, - 0x00, 0xe2, 0xa6, 0x58, + 0x00, 0xe2, 0xb8, 0x58, 0xff, 0xea, 0x56, 0x02, - 0x04, 0x7c, 0x78, 0x32, - 0x20, 0x16, 0x64, 0x78, - 0x04, 0x38, 0x79, 0x32, - 0x80, 0x37, 0x6f, 0x16, - 0xff, 0x2d, 0xb5, 0x60, - 0xff, 0x29, 0xb5, 0x60, - 0x40, 0x51, 0xc5, 0x78, - 0xff, 0x4f, 0xb5, 0x68, - 0xff, 0x4d, 0xc1, 0x19, - 0x00, 0x4e, 0xd5, 0x19, - 0x00, 0xe2, 0xc4, 0x50, - 0x01, 0x4c, 0xc1, 0x31, - 0x00, 0x50, 0xd5, 0x19, - 0x00, 0xe2, 0xc4, 0x48, - 0x80, 0x18, 0x64, 0x78, - 0x02, 0x4a, 0x1d, 0x30, + 0x04, 0x7c, 0x88, 0x32, + 0x20, 0x16, 0x84, 0x78, + 0x04, 0x40, 0x89, 0x32, + 0x80, 0x3d, 0x7b, 0x16, + 0xff, 0x2d, 0xc7, 0x60, + 0xff, 0x29, 0xc7, 0x60, + 0x40, 0x57, 0xd7, 0x78, + 0xff, 0x55, 0xc7, 0x68, + 0xff, 0x53, 0xc1, 0x19, + 0x00, 0x54, 0xd5, 0x19, + 0x00, 0xe2, 0xd6, 0x50, + 0x01, 0x52, 0xc1, 0x31, + 0x00, 0x56, 0xd5, 0x19, + 0x00, 0xe2, 0xd6, 0x48, + 0x80, 0x18, 0x84, 0x78, + 0x02, 0x50, 0x1d, 0x30, 0x10, 0xea, 0x18, 0x00, 0x60, 0x18, 0x30, 0x00, 0x7f, 0x18, 0x30, 0x0c, 0x02, 0xea, 0x02, 0x00, - 0xff, 0xea, 0xa0, 0x0a, + 0xff, 0xea, 0xac, 0x0a, 0x80, 0x18, 0x30, 0x04, - 0x40, 0xad, 0x64, 0x78, + 0x40, 0xad, 0x84, 0x78, 0xe7, 0xad, 0x5a, 0x09, 0x02, 0xa8, 0x40, 0x31, 0xff, 0xea, 0xc0, 0x09, - 0x01, 0x4e, 0x9d, 0x1a, - 0x00, 0x4f, 0x9f, 0x22, + 0x01, 0x54, 0xa9, 0x1a, + 0x00, 0x55, 0xab, 0x22, 0x01, 0x94, 0x6d, 0x33, - 0x01, 0xea, 0x20, 0x33, + 0xff, 0xea, 0x20, 0x0b, 0x04, 0xac, 0x49, 0x32, 0xff, 0xea, 0x5a, 0x03, 0xff, 0xea, 0x5e, 0x03, 0x01, 0x10, 0xd4, 0x31, - 0x10, 0x92, 0xf5, 0x68, + 0x10, 0x92, 0x07, 0x69, 0x3d, 0x93, 0xc5, 0x29, 0xfe, 0xe2, 0xc4, 0x09, 0x01, 0xea, 0xc6, 0x01, 0x02, 0xe2, 0xc8, 0x31, 0x02, 0xec, 0x50, 0x31, 0x02, 0xa0, 0xda, 0x31, - 0xff, 0xa9, 0xf4, 0x70, + 0xff, 0xa9, 0x06, 0x71, 0x02, 0xa0, 0x58, 0x37, - 0xff, 0x21, 0xfd, 0x70, + 0xff, 0x21, 0x0f, 0x71, 0x02, 0x22, 0x51, 0x31, 0x02, 0xa0, 0x5c, 0x33, 0x02, 0xa0, 0x44, 0x36, 0x02, 0xa0, 0x40, 0x32, 0x02, 0xa0, 0x44, 0x36, - 0x04, 0x47, 0x05, 0x69, - 0x40, 0x16, 0x30, 0x69, - 0xff, 0x2d, 0x35, 0x61, - 0xff, 0x29, 0x65, 0x70, - 0x01, 0x37, 0xc1, 0x31, + 0x04, 0x4d, 0x17, 0x69, + 0x40, 0x16, 0x48, 0x69, + 0xff, 0x2d, 0x4d, 0x61, + 0xff, 0x29, 0x85, 0x70, 0x02, 0x28, 0x55, 0x32, 0x01, 0xea, 0x5a, 0x01, - 0x04, 0x3c, 0xf9, 0x30, + 0x04, 0x44, 0xf9, 0x30, + 0x01, 0x44, 0xc1, 0x31, 0x02, 0x28, 0x51, 0x31, - 0x01, 0xa8, 0x60, 0x31, - 0x00, 0xa9, 0x60, 0x01, + 0x02, 0xa8, 0x60, 0x31, + 0x01, 0xa4, 0x61, 0x31, + 0x01, 0x3d, 0x61, 0x31, 0x01, 0x14, 0xd4, 0x31, - 0x01, 0x50, 0xa1, 0x1a, - 0xff, 0x4e, 0x9d, 0x1a, - 0xff, 0x4f, 0x9f, 0x22, - 0xff, 0x8d, 0x29, 0x71, - 0x80, 0xac, 0x28, 0x71, - 0x20, 0x16, 0x28, 0x69, + 0x01, 0x56, 0xad, 0x1a, + 0xff, 0x54, 0xa9, 0x1a, + 0xff, 0x55, 0xab, 0x22, + 0xff, 0x8d, 0x41, 0x71, + 0x80, 0xac, 0x40, 0x71, + 0x20, 0x16, 0x40, 0x69, + 0x00, 0xac, 0xc4, 0x19, + 0x07, 0xe2, 0x40, 0xf9, 0x02, 0x8c, 0x51, 0x31, - 0x00, 0xe2, 0x12, 0x41, + 0x00, 0xe2, 0x24, 0x41, 0x01, 0xac, 0x08, 0x31, 0x09, 0xea, 0x5a, 0x01, 0x02, 0x8c, 0x51, 0x32, 0xff, 0xea, 0x1a, 0x07, 0x04, 0x24, 0xf9, 0x30, - 0x1d, 0xea, 0x3a, 0x41, + 0x1d, 0xea, 0x52, 0x41, 0x02, 0x2c, 0x51, 0x31, 0x04, 0xa8, 0xf9, 0x30, - 0x19, 0xea, 0x3a, 0x41, + 0x19, 0xea, 0x52, 0x41, 0x06, 0xea, 0x08, 0x81, 0x01, 0xe2, 0x5a, 0x35, - 0x02, 0xf2, 0xf0, 0x35, + 0x02, 0xf2, 0xf0, 0x31, + 0xff, 0xea, 0xd4, 0x0d, 0x02, 0xf2, 0xf0, 0x31, 0x02, 0xf8, 0xe4, 0x35, 0x80, 0xea, 0xb2, 0x01, 0x01, 0xe2, 0x00, 0x30, 0xff, 0xea, 0xb2, 0x0d, - 0x80, 0xea, 0xb2, 0x01, - 0x11, 0x00, 0x00, 0x10, - 0xff, 0xea, 0xb2, 0x0d, 0x01, 0xe2, 0x04, 0x30, 0x01, 0xea, 0x04, 0x34, 0x02, 0x20, 0xbd, 0x30, 0x02, 0x20, 0xb9, 0x30, 0x02, 0x20, 0x51, 0x31, 0x4c, 0x93, 0xd7, 0x28, - 0x10, 0x92, 0x63, 0x79, + 0x10, 0x92, 0x77, 0x79, 0x01, 0x6b, 0xc0, 0x30, 0x02, 0x64, 0xc8, 0x00, 0x40, 0x3a, 0x74, 0x04, - 0x00, 0xe2, 0x56, 0x58, - 0x33, 0xea, 0x44, 0x59, + 0x00, 0xe2, 0x76, 0x58, + 0x33, 0xea, 0x5e, 0x59, 0x33, 0xea, 0x00, 0x00, 0x30, 0x3f, 0xc0, 0x09, - 0x30, 0xe0, 0x64, 0x61, - 0x20, 0x3f, 0x7a, 0x69, - 0x10, 0x3f, 0x64, 0x79, + 0x30, 0xe0, 0x78, 0x61, + 0x20, 0x3f, 0x8e, 0x69, + 0x10, 0x3f, 0x78, 0x79, 0x02, 0xea, 0x7e, 0x00, - 0x00, 0xea, 0x44, 0x59, + 0x00, 0xea, 0x5e, 0x59, 0x01, 0xea, 0x00, 0x30, - 0x02, 0x48, 0x51, 0x35, + 0x02, 0x4e, 0x51, 0x35, 0x01, 0xea, 0x7e, 0x00, - 0x11, 0xea, 0x44, 0x59, + 0x11, 0xea, 0x5e, 0x59, 0x11, 0xea, 0x00, 0x00, - 0x02, 0x48, 0x51, 0x35, + 0x02, 0x4e, 0x51, 0x35, + 0xc0, 0x4a, 0x94, 0x00, + 0x04, 0x41, 0x9c, 0x79, 0x08, 0xea, 0x98, 0x00, 0x08, 0x57, 0xae, 0x00, 0x08, 0x3c, 0x78, 0x00, - 0xf0, 0x49, 0x68, 0x0a, + 0xf0, 0x49, 0x74, 0x0a, 0x0f, 0x67, 0xc0, 0x09, - 0x00, 0x34, 0x69, 0x02, + 0x00, 0x3a, 0x75, 0x02, 0x20, 0xea, 0x96, 0x00, - 0x00, 0xe2, 0xf8, 0x41, - 0x40, 0x3a, 0xae, 0x69, + 0x00, 0xe2, 0x14, 0x42, + 0xc0, 0x4a, 0x94, 0x00, + 0x40, 0x3a, 0xc8, 0x69, 0x02, 0x55, 0x06, 0x68, - 0x02, 0x56, 0xae, 0x69, - 0xff, 0x5b, 0xae, 0x61, + 0x02, 0x56, 0xc8, 0x69, + 0xff, 0x5b, 0xc8, 0x61, 0x02, 0x20, 0x51, 0x31, 0x80, 0xea, 0xb2, 0x01, 0x44, 0xea, 0x00, 0x00, @@ -218,237 +231,246 @@ static uint8_t seqprog[] = { 0x33, 0xea, 0x00, 0x00, 0xff, 0xea, 0xb2, 0x09, 0xff, 0xe0, 0xc0, 0x19, - 0xff, 0xe0, 0xb0, 0x79, + 0xff, 0xe0, 0xca, 0x79, 0x02, 0xac, 0x51, 0x31, - 0x00, 0xe2, 0xa6, 0x41, + 0x00, 0xe2, 0xc0, 0x41, 0x02, 0x5e, 0x50, 0x31, 0x02, 0xa8, 0xb8, 0x30, 0x02, 0x5c, 0x50, 0x31, - 0xff, 0xad, 0xc1, 0x71, + 0xff, 0xad, 0xdb, 0x71, 0x02, 0xac, 0x41, 0x31, 0x02, 0x22, 0x51, 0x31, 0x02, 0xa0, 0x5c, 0x33, 0x02, 0xa0, 0x44, 0x32, - 0x00, 0xe2, 0xca, 0x41, - 0x10, 0x92, 0xcb, 0x69, + 0x00, 0xe2, 0xe4, 0x41, + 0x10, 0x92, 0xe5, 0x69, 0x3d, 0x93, 0xc9, 0x29, 0x01, 0xe4, 0xc8, 0x01, 0x01, 0xea, 0xca, 0x01, 0xff, 0xea, 0xda, 0x01, 0x02, 0x20, 0x51, 0x31, 0x02, 0xae, 0x41, 0x32, - 0xff, 0x21, 0xd3, 0x61, + 0xff, 0x21, 0xed, 0x61, 0xff, 0xea, 0x46, 0x02, 0x02, 0x5c, 0x50, 0x31, 0x40, 0xea, 0x96, 0x00, - 0x02, 0x56, 0xcc, 0x6d, - 0x01, 0x55, 0xcc, 0x6d, - 0x10, 0x92, 0xdf, 0x79, - 0x10, 0x40, 0xe8, 0x69, - 0x01, 0x56, 0xe8, 0x79, + 0x02, 0x56, 0x04, 0x6e, + 0x01, 0x55, 0x04, 0x6e, + 0x10, 0x92, 0xf9, 0x79, + 0x10, 0x40, 0x02, 0x6a, + 0x01, 0x56, 0x02, 0x7a, 0xff, 0x97, 0x07, 0x78, - 0x13, 0xea, 0x50, 0x59, + 0x13, 0xea, 0x64, 0x59, 0x13, 0xea, 0x04, 0x00, 0x00, 0xe2, 0x06, 0x40, 0xbf, 0x3a, 0x74, 0x08, + 0x04, 0x41, 0x08, 0x7a, 0x08, 0xea, 0x98, 0x00, 0x08, 0x57, 0xae, 0x00, - 0x01, 0x93, 0x69, 0x32, - 0x01, 0x94, 0x6b, 0x32, - 0x40, 0xea, 0x66, 0x02, + 0x01, 0x93, 0x75, 0x32, + 0x01, 0x94, 0x77, 0x32, + 0x40, 0xea, 0x72, 0x02, 0x08, 0x3c, 0x78, 0x00, - 0x80, 0xea, 0x62, 0x02, - 0x00, 0xe2, 0xb8, 0x5b, - 0x01, 0x36, 0xc1, 0x31, - 0x9f, 0xe0, 0x4c, 0x7c, - 0x80, 0xe0, 0x0c, 0x72, - 0xa0, 0xe0, 0x44, 0x72, - 0xc0, 0xe0, 0x3a, 0x72, - 0xe0, 0xe0, 0x74, 0x72, - 0x01, 0xea, 0x50, 0x59, + 0x80, 0xea, 0x6e, 0x02, + 0x00, 0xe2, 0xe2, 0x5b, + 0x01, 0x3c, 0xc1, 0x31, + 0x9f, 0xe0, 0x84, 0x7c, + 0x80, 0xe0, 0x28, 0x72, + 0xa0, 0xe0, 0x64, 0x72, + 0xc0, 0xe0, 0x5a, 0x72, + 0xe0, 0xe0, 0x94, 0x72, + 0x01, 0xea, 0x64, 0x59, 0x01, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xf8, 0x41, - 0x80, 0x33, 0x13, 0x7a, - 0x03, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0x14, 0x42, + 0x80, 0x39, 0x2f, 0x7a, + 0x03, 0xea, 0x64, 0x59, 0x03, 0xea, 0x04, 0x00, - 0xee, 0x00, 0x1a, 0x6a, + 0xee, 0x00, 0x36, 0x6a, 0x05, 0xea, 0xb4, 0x00, - 0x33, 0xea, 0x44, 0x59, + 0x33, 0xea, 0x5e, 0x59, 0x33, 0xea, 0x00, 0x00, - 0x02, 0xa8, 0x90, 0x32, - 0x00, 0xe2, 0x6a, 0x59, + 0x02, 0xa8, 0x9c, 0x32, + 0x00, 0xe2, 0x7e, 0x59, 0xef, 0x96, 0xd5, 0x19, - 0x00, 0xe2, 0x2a, 0x52, + 0x00, 0xe2, 0x46, 0x52, 0x09, 0x80, 0xe1, 0x30, 0x02, 0xea, 0x36, 0x00, 0xa8, 0xea, 0x32, 0x00, - 0x00, 0xe2, 0x30, 0x42, + 0x00, 0xe2, 0x4c, 0x42, 0x01, 0x96, 0xd1, 0x30, 0x10, 0x80, 0x89, 0x31, 0x20, 0xea, 0x32, 0x00, - 0xbf, 0x33, 0x67, 0x0a, - 0x20, 0x19, 0x32, 0x6a, - 0x02, 0x4d, 0xf8, 0x69, - 0x40, 0x33, 0x67, 0x02, - 0x00, 0xe2, 0xf8, 0x41, - 0x80, 0x33, 0xb5, 0x6a, + 0xbf, 0x39, 0x73, 0x0a, + 0x10, 0x4c, 0x56, 0x6a, + 0x20, 0x19, 0x4e, 0x6a, + 0x20, 0x19, 0x52, 0x6a, + 0x02, 0x4d, 0x14, 0x6a, + 0x40, 0x39, 0x73, 0x02, + 0x00, 0xe2, 0x14, 0x42, + 0x80, 0x39, 0xd5, 0x6a, 0x01, 0x44, 0x10, 0x33, 0x08, 0x92, 0x25, 0x03, - 0x00, 0xe2, 0xf8, 0x41, + 0x00, 0xe2, 0x14, 0x42, 0x10, 0xea, 0x80, 0x00, - 0x01, 0x31, 0xc5, 0x31, - 0x80, 0xe2, 0x60, 0x62, - 0x10, 0x92, 0x85, 0x6a, + 0x01, 0x37, 0xc5, 0x31, + 0x80, 0xe2, 0x80, 0x62, + 0x10, 0x92, 0xa5, 0x6a, 0xc0, 0x94, 0xc5, 0x01, - 0x40, 0x92, 0x51, 0x6a, + 0x40, 0x92, 0x71, 0x6a, 0xbf, 0xe2, 0xc4, 0x09, - 0x20, 0x92, 0x65, 0x7a, + 0x20, 0x92, 0x85, 0x7a, 0x01, 0xe2, 0x88, 0x30, - 0x00, 0xe2, 0xb8, 0x5b, - 0xa0, 0x36, 0x6d, 0x62, + 0x00, 0xe2, 0xe2, 0x5b, + 0xa0, 0x3c, 0x8d, 0x62, 0x23, 0x92, 0x89, 0x08, - 0x00, 0xe2, 0xb8, 0x5b, - 0xa0, 0x36, 0x6d, 0x62, - 0x00, 0xa8, 0x64, 0x42, - 0xff, 0xe2, 0x64, 0x62, - 0x00, 0xe2, 0x84, 0x42, + 0x00, 0xe2, 0xe2, 0x5b, + 0xa0, 0x3c, 0x8d, 0x62, + 0x00, 0xa8, 0x84, 0x42, + 0xff, 0xe2, 0x84, 0x62, + 0x00, 0xe2, 0xa4, 0x42, 0x40, 0xea, 0x98, 0x00, 0x01, 0xe2, 0x88, 0x30, - 0x00, 0xe2, 0xb8, 0x5b, - 0xa0, 0x36, 0x43, 0x72, + 0x00, 0xe2, 0xe2, 0x5b, + 0xa0, 0x3c, 0x63, 0x72, 0x40, 0xea, 0x98, 0x00, - 0x01, 0x31, 0x89, 0x32, - 0x08, 0xea, 0x62, 0x02, - 0x00, 0xe2, 0xf8, 0x41, - 0xe0, 0xea, 0xd4, 0x5b, - 0x80, 0xe0, 0xc0, 0x6a, - 0x04, 0xe0, 0x66, 0x73, - 0x02, 0xe0, 0x96, 0x73, - 0x00, 0xea, 0x1e, 0x73, - 0x03, 0xe0, 0xa6, 0x73, - 0x23, 0xe0, 0x96, 0x72, - 0x08, 0xe0, 0xbc, 0x72, - 0x00, 0xe2, 0xb8, 0x5b, - 0x07, 0xea, 0x50, 0x59, + 0x01, 0x37, 0x95, 0x32, + 0x08, 0xea, 0x6e, 0x02, + 0x00, 0xe2, 0x14, 0x42, + 0xe0, 0xea, 0xfe, 0x5b, + 0x80, 0xe0, 0xe0, 0x6a, + 0x04, 0xe0, 0x92, 0x73, + 0x02, 0xe0, 0xc4, 0x73, + 0x00, 0xea, 0x3e, 0x73, + 0x03, 0xe0, 0xd4, 0x73, + 0x23, 0xe0, 0xb6, 0x72, + 0x08, 0xe0, 0xdc, 0x72, + 0x00, 0xe2, 0xe2, 0x5b, + 0x07, 0xea, 0x64, 0x59, 0x07, 0xea, 0x04, 0x00, - 0x08, 0x42, 0xf9, 0x71, - 0x04, 0x42, 0x93, 0x62, - 0x01, 0x43, 0x89, 0x30, - 0x00, 0xe2, 0x84, 0x42, + 0x08, 0x48, 0x15, 0x72, + 0x04, 0x48, 0xb3, 0x62, + 0x01, 0x49, 0x89, 0x30, + 0x00, 0xe2, 0xa4, 0x42, 0x01, 0x44, 0xd4, 0x31, - 0x00, 0xe2, 0x84, 0x42, - 0x01, 0x00, 0x60, 0x32, - 0x33, 0xea, 0x44, 0x59, + 0x00, 0xe2, 0xa4, 0x42, + 0x01, 0x00, 0x6c, 0x32, + 0x33, 0xea, 0x5e, 0x59, 0x33, 0xea, 0x00, 0x00, - 0x4c, 0x34, 0xc1, 0x28, + 0x4c, 0x3a, 0xc1, 0x28, 0x01, 0x64, 0xc0, 0x31, - 0x00, 0x30, 0x45, 0x59, - 0x01, 0x30, 0x01, 0x30, - 0x01, 0xe0, 0xba, 0x7a, - 0xa0, 0xea, 0xca, 0x5b, - 0x01, 0xa0, 0xba, 0x62, - 0x01, 0x84, 0xaf, 0x7a, - 0x01, 0x95, 0xbd, 0x6a, - 0x05, 0xea, 0x50, 0x59, + 0x00, 0x36, 0x5f, 0x59, + 0x01, 0x36, 0x01, 0x30, + 0x01, 0xe0, 0xda, 0x7a, + 0xa0, 0xea, 0xf4, 0x5b, + 0x01, 0xa0, 0xda, 0x62, + 0x01, 0x84, 0xcf, 0x7a, + 0x01, 0x95, 0xdd, 0x6a, + 0x05, 0xea, 0x64, 0x59, 0x05, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xbc, 0x42, - 0x03, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0xdc, 0x42, + 0x03, 0xea, 0x64, 0x59, 0x03, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xbc, 0x42, - 0x07, 0xea, 0xdc, 0x5b, + 0x00, 0xe2, 0xdc, 0x42, + 0x07, 0xea, 0x06, 0x5c, 0x01, 0x44, 0xd4, 0x31, - 0x00, 0xe2, 0xf8, 0x41, - 0x3f, 0xe0, 0x6a, 0x0a, - 0xc0, 0x34, 0xc1, 0x09, - 0x00, 0x35, 0x51, 0x01, + 0x00, 0xe2, 0x14, 0x42, + 0x3f, 0xe0, 0x76, 0x0a, + 0xc0, 0x3a, 0xc1, 0x09, + 0x00, 0x3b, 0x51, 0x01, 0xff, 0xea, 0x52, 0x09, - 0x30, 0x34, 0xc5, 0x09, + 0x30, 0x3a, 0xc5, 0x09, 0x3d, 0xe2, 0xc4, 0x29, 0xb8, 0xe2, 0xc4, 0x19, 0x01, 0xea, 0xc6, 0x01, 0x02, 0xe2, 0xc8, 0x31, 0x02, 0xec, 0x40, 0x31, - 0xff, 0xa1, 0xdc, 0x72, + 0xff, 0xa1, 0xfc, 0x72, 0x02, 0xe8, 0xda, 0x31, 0x02, 0xa0, 0x50, 0x31, - 0x00, 0xe2, 0xfe, 0x42, - 0x80, 0x33, 0x67, 0x02, + 0x00, 0xe2, 0x1e, 0x43, + 0x80, 0x39, 0x73, 0x02, 0x01, 0x44, 0xd4, 0x31, - 0x00, 0xe2, 0xb8, 0x5b, - 0x01, 0x33, 0x67, 0x02, - 0xe0, 0x36, 0x19, 0x63, - 0x02, 0x33, 0x67, 0x02, - 0x20, 0x46, 0x12, 0x63, + 0x00, 0xe2, 0xe2, 0x5b, + 0x01, 0x39, 0x73, 0x02, + 0xe0, 0x3c, 0x39, 0x63, + 0x02, 0x39, 0x73, 0x02, + 0x20, 0x46, 0x32, 0x63, 0xff, 0xea, 0x52, 0x09, - 0xa8, 0xea, 0xca, 0x5b, - 0x04, 0x92, 0xf9, 0x7a, - 0x01, 0x34, 0xc1, 0x31, - 0x00, 0x93, 0xf9, 0x62, - 0x01, 0x35, 0xc1, 0x31, - 0x00, 0x94, 0x03, 0x73, + 0xa8, 0xea, 0xf4, 0x5b, + 0x04, 0x92, 0x19, 0x7b, + 0x01, 0x3a, 0xc1, 0x31, + 0x00, 0x93, 0x19, 0x63, + 0x01, 0x3b, 0xc1, 0x31, + 0x00, 0x94, 0x23, 0x73, 0x01, 0xa9, 0x52, 0x11, - 0xff, 0xa9, 0xee, 0x6a, - 0x00, 0xe2, 0x12, 0x43, - 0x10, 0x33, 0x67, 0x02, - 0x04, 0x92, 0x13, 0x7b, + 0xff, 0xa9, 0x0e, 0x6b, + 0x00, 0xe2, 0x32, 0x43, + 0x10, 0x39, 0x73, 0x02, + 0x04, 0x92, 0x33, 0x7b, 0xfb, 0x92, 0x25, 0x0b, - 0xff, 0xea, 0x66, 0x0a, - 0x01, 0xa4, 0x0d, 0x6b, - 0x02, 0xa8, 0x90, 0x32, - 0x00, 0xe2, 0x6a, 0x59, - 0x10, 0x92, 0xbd, 0x7a, - 0xff, 0xea, 0xdc, 0x5b, - 0x00, 0xe2, 0xbc, 0x42, - 0x04, 0xea, 0x50, 0x59, + 0xff, 0xea, 0x72, 0x0a, + 0x01, 0xa4, 0x2d, 0x6b, + 0x02, 0xa8, 0x9c, 0x32, + 0x00, 0xe2, 0x7e, 0x59, + 0x10, 0x92, 0xdd, 0x7a, + 0xff, 0xea, 0x06, 0x5c, + 0x00, 0xe2, 0xdc, 0x42, + 0x04, 0xea, 0x64, 0x59, 0x04, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xbc, 0x42, - 0x04, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0xdc, 0x42, + 0x04, 0xea, 0x64, 0x59, 0x04, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xf8, 0x41, - 0x08, 0x92, 0xb5, 0x7a, - 0xc0, 0x33, 0x29, 0x7b, - 0x80, 0x33, 0xb5, 0x6a, - 0xff, 0x88, 0x29, 0x6b, - 0x40, 0x33, 0xb5, 0x6a, - 0x10, 0x92, 0x2f, 0x7b, - 0x0a, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0x14, 0x42, + 0x08, 0x92, 0xd5, 0x7a, + 0xc0, 0x39, 0x49, 0x7b, + 0x80, 0x39, 0xd5, 0x6a, + 0xff, 0x88, 0x49, 0x6b, + 0x40, 0x39, 0xd5, 0x6a, + 0x10, 0x92, 0x4f, 0x7b, + 0x0a, 0xea, 0x64, 0x59, 0x0a, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x4e, 0x5b, - 0x00, 0xe2, 0x82, 0x43, - 0x50, 0x4b, 0x36, 0x6b, + 0x00, 0xe2, 0x6e, 0x5b, + 0x00, 0xe2, 0xae, 0x43, + 0x50, 0x4b, 0x56, 0x6b, 0xbf, 0x3a, 0x74, 0x08, 0x01, 0xe0, 0xf4, 0x31, 0xff, 0xea, 0xc0, 0x09, - 0x01, 0x2e, 0x5d, 0x1a, - 0x00, 0x2f, 0x5f, 0x22, - 0x04, 0x47, 0x8f, 0x02, + 0x01, 0x32, 0x65, 0x1a, + 0x00, 0x33, 0x67, 0x22, + 0x04, 0x4d, 0x9b, 0x02, 0x01, 0xfa, 0xc0, 0x35, - 0x02, 0xa8, 0x84, 0x32, + 0x02, 0xa8, 0x90, 0x32, 0x02, 0xea, 0xb4, 0x00, - 0x33, 0xea, 0x44, 0x59, + 0x33, 0xea, 0x5e, 0x59, 0x33, 0xea, 0x00, 0x00, - 0x02, 0x42, 0x51, 0x31, - 0xff, 0x90, 0x65, 0x68, - 0xff, 0x88, 0x5b, 0x6b, - 0x01, 0xa4, 0x57, 0x6b, - 0x02, 0xa4, 0x5f, 0x6b, - 0x01, 0x84, 0x5f, 0x7b, + 0x02, 0x48, 0x51, 0x31, + 0xff, 0x90, 0x85, 0x68, + 0xff, 0x88, 0x7b, 0x6b, + 0x01, 0xa4, 0x77, 0x6b, + 0x02, 0xa4, 0x7f, 0x6b, + 0x01, 0x84, 0x7f, 0x7b, 0x02, 0x28, 0x19, 0x33, 0x02, 0xa8, 0x50, 0x36, - 0xff, 0x88, 0x5f, 0x73, - 0x00, 0xe2, 0x32, 0x5b, + 0xff, 0x88, 0x7f, 0x73, + 0x00, 0xe2, 0x52, 0x5b, 0x02, 0xa8, 0x20, 0x33, - 0x02, 0x2c, 0x19, 0x33, + 0x04, 0xa4, 0x49, 0x03, + 0xff, 0xea, 0x1a, 0x03, + 0xff, 0x2d, 0x8b, 0x63, 0x02, 0xa8, 0x58, 0x32, - 0x04, 0xa4, 0x49, 0x07, - 0xc0, 0x33, 0xb5, 0x6a, + 0x02, 0xa8, 0x5c, 0x36, + 0x02, 0xa8, 0x40, 0x31, + 0x02, 0x2e, 0x51, 0x31, + 0x02, 0xa0, 0x18, 0x33, + 0x02, 0xa0, 0x5c, 0x36, + 0xc0, 0x39, 0xd5, 0x6a, 0x04, 0x92, 0x25, 0x03, - 0x20, 0x92, 0x83, 0x6b, + 0x20, 0x92, 0xaf, 0x6b, 0x02, 0xa8, 0x40, 0x31, - 0xc0, 0x34, 0xc1, 0x09, - 0x00, 0x35, 0x51, 0x01, + 0xc0, 0x3a, 0xc1, 0x09, + 0x00, 0x3b, 0x51, 0x01, 0xff, 0xea, 0x52, 0x09, - 0x30, 0x34, 0xc5, 0x09, + 0x30, 0x3a, 0xc5, 0x09, 0x3d, 0xe2, 0xc4, 0x29, 0xb8, 0xe2, 0xc4, 0x19, 0x01, 0xea, 0xc6, 0x01, @@ -458,69 +480,75 @@ static uint8_t seqprog[] = { 0xf7, 0x57, 0xae, 0x08, 0x08, 0xea, 0x98, 0x00, 0x01, 0x44, 0xd4, 0x31, - 0xee, 0x00, 0x8c, 0x6b, + 0xee, 0x00, 0xb8, 0x6b, 0x02, 0xea, 0xb4, 0x00, - 0x00, 0xe2, 0xb4, 0x5b, - 0x09, 0x4c, 0x8e, 0x7b, + 0xc0, 0xea, 0x72, 0x02, + 0x09, 0x4c, 0xba, 0x7b, + 0x01, 0xea, 0x78, 0x02, 0x08, 0x4c, 0x06, 0x68, - 0x0b, 0xea, 0x50, 0x59, + 0x0b, 0xea, 0x64, 0x59, 0x0b, 0xea, 0x04, 0x00, 0x01, 0x44, 0xd4, 0x31, - 0x20, 0x33, 0xf9, 0x79, - 0x00, 0xe2, 0x9e, 0x5b, - 0x00, 0xe2, 0xf8, 0x41, - 0x01, 0x84, 0xa3, 0x7b, + 0x20, 0x39, 0x15, 0x7a, + 0x00, 0xe2, 0xcc, 0x5b, + 0x00, 0xe2, 0x14, 0x42, + 0x01, 0x84, 0xd1, 0x7b, 0x01, 0xa4, 0x49, 0x07, 0x08, 0x60, 0x30, 0x33, 0x08, 0x80, 0x41, 0x37, - 0xdf, 0x33, 0x67, 0x0a, - 0xee, 0x00, 0xb0, 0x6b, + 0xdf, 0x39, 0x73, 0x0a, + 0xee, 0x00, 0xde, 0x6b, 0x05, 0xea, 0xb4, 0x00, - 0x33, 0xea, 0x44, 0x59, + 0x33, 0xea, 0x5e, 0x59, 0x33, 0xea, 0x00, 0x00, - 0x00, 0xe2, 0x6a, 0x59, - 0x00, 0xe2, 0xbc, 0x42, - 0x01, 0xea, 0x6c, 0x02, - 0xc0, 0xea, 0x66, 0x06, - 0xff, 0x42, 0xc4, 0x6b, - 0x01, 0x41, 0xb8, 0x6b, - 0x02, 0x41, 0xb8, 0x7b, - 0xff, 0x42, 0xc4, 0x6b, - 0x01, 0x41, 0xb8, 0x6b, - 0x02, 0x41, 0xb8, 0x7b, - 0xff, 0x42, 0xc4, 0x7b, - 0x04, 0x4c, 0xb8, 0x6b, - 0xe0, 0x41, 0x6c, 0x0e, + 0x00, 0xe2, 0x7e, 0x59, + 0x00, 0xe2, 0xdc, 0x42, + 0xff, 0x42, 0xee, 0x6b, + 0x01, 0x41, 0xe2, 0x6b, + 0x02, 0x41, 0xe2, 0x7b, + 0xff, 0x42, 0xee, 0x6b, + 0x01, 0x41, 0xe2, 0x6b, + 0x02, 0x41, 0xe2, 0x7b, + 0xff, 0x42, 0xee, 0x7b, + 0x04, 0x4c, 0xe2, 0x6b, + 0xe0, 0x41, 0x78, 0x0e, 0x01, 0x44, 0xd4, 0x31, - 0xff, 0x42, 0xcc, 0x7b, - 0x04, 0x4c, 0xcc, 0x6b, - 0xe0, 0x41, 0x6c, 0x0a, - 0xe0, 0x36, 0xf9, 0x61, + 0xff, 0x42, 0xf6, 0x7b, + 0x04, 0x4c, 0xf6, 0x6b, + 0xe0, 0x41, 0x78, 0x0a, + 0xe0, 0x3c, 0x15, 0x62, 0xff, 0xea, 0xca, 0x09, 0x01, 0xe2, 0xc8, 0x31, 0x01, 0x46, 0xda, 0x35, 0x01, 0x44, 0xd4, 0x35, 0x10, 0xea, 0x80, 0x00, - 0x01, 0xe2, 0x62, 0x36, - 0x04, 0xa6, 0xe4, 0x7b, + 0x01, 0xe2, 0x6e, 0x36, + 0x04, 0xa6, 0x0e, 0x7c, 0xff, 0xea, 0x5a, 0x09, 0xff, 0xea, 0x4c, 0x0d, - 0x01, 0xa6, 0x02, 0x6c, - 0x10, 0xad, 0x64, 0x78, - 0x80, 0xad, 0xfa, 0x6b, - 0x08, 0xad, 0x64, 0x68, + 0x01, 0xa6, 0x3a, 0x6c, + 0x10, 0xad, 0x84, 0x78, + 0x80, 0xad, 0x32, 0x6c, + 0x08, 0xad, 0x84, 0x68, + 0x20, 0x19, 0x26, 0x7c, + 0x80, 0xea, 0xb2, 0x01, + 0x11, 0x00, 0x00, 0x10, + 0x02, 0xa6, 0x22, 0x7c, + 0xff, 0xea, 0xb2, 0x0d, + 0x11, 0x00, 0x00, 0x10, + 0xff, 0xea, 0xb2, 0x09, 0x04, 0x84, 0xf9, 0x30, 0x00, 0xea, 0x08, 0x81, 0xff, 0xea, 0xd4, 0x09, 0x02, 0x84, 0xf9, 0x88, 0x0d, 0xea, 0x5a, 0x01, 0x04, 0xa6, 0x4c, 0x05, - 0x04, 0xa6, 0x64, 0x78, + 0x04, 0xa6, 0x84, 0x78, 0xff, 0xea, 0x5a, 0x09, 0x03, 0x84, 0x59, 0x89, 0x03, 0xea, 0x4c, 0x01, - 0x80, 0x1a, 0x64, 0x78, - 0x08, 0x19, 0x64, 0x78, + 0x80, 0x1a, 0x84, 0x78, + 0x08, 0x19, 0x84, 0x78, 0x08, 0xb0, 0xe0, 0x30, 0x04, 0xb0, 0xe0, 0x30, 0x03, 0xb0, 0xf0, 0x30, @@ -533,259 +561,259 @@ static uint8_t seqprog[] = { 0x00, 0x86, 0x0d, 0x23, 0x00, 0x87, 0x0f, 0x23, 0x01, 0x84, 0xc5, 0x31, - 0x80, 0x83, 0x25, 0x7c, + 0x80, 0x83, 0x5d, 0x7c, 0x02, 0xe2, 0xc4, 0x01, 0xff, 0xea, 0x4c, 0x09, 0x01, 0xe2, 0x36, 0x30, 0xc8, 0x19, 0x32, 0x00, 0x88, 0x19, 0x32, 0x00, 0x01, 0xac, 0xd4, 0x99, - 0x00, 0xe2, 0x64, 0x50, + 0x00, 0xe2, 0x84, 0x50, 0xfe, 0xa6, 0x4c, 0x0d, 0x0b, 0x98, 0xe1, 0x30, 0xfd, 0xa4, 0x49, 0x09, - 0x80, 0xa3, 0x39, 0x7c, + 0x80, 0xa3, 0x71, 0x7c, 0x02, 0xa4, 0x48, 0x01, 0x01, 0xa4, 0x36, 0x30, 0xa8, 0xea, 0x32, 0x00, 0xfd, 0xa4, 0x49, 0x0b, 0x05, 0xa3, 0x07, 0x33, - 0x80, 0x83, 0x45, 0x6c, + 0x80, 0x83, 0x7d, 0x6c, 0x02, 0xea, 0x4c, 0x05, 0xff, 0xea, 0x4c, 0x0d, - 0x00, 0xe2, 0x3e, 0x59, - 0x02, 0xa6, 0xe6, 0x6b, + 0x00, 0xe2, 0x56, 0x59, + 0x02, 0xa6, 0x10, 0x6c, 0x80, 0xf9, 0xf2, 0x05, - 0xc0, 0x33, 0x53, 0x7c, - 0x03, 0xea, 0x50, 0x59, + 0xc0, 0x39, 0x8b, 0x7c, + 0x03, 0xea, 0x64, 0x59, 0x03, 0xea, 0x04, 0x00, - 0x20, 0x33, 0x77, 0x7c, - 0x01, 0x84, 0x5d, 0x6c, - 0x06, 0xea, 0x50, 0x59, + 0x20, 0x39, 0xaf, 0x7c, + 0x01, 0x84, 0x95, 0x6c, + 0x06, 0xea, 0x64, 0x59, 0x06, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x7a, 0x44, - 0x01, 0x00, 0x60, 0x32, - 0xee, 0x00, 0x66, 0x6c, + 0x00, 0xe2, 0xb2, 0x44, + 0x01, 0x00, 0x6c, 0x32, + 0xee, 0x00, 0x9e, 0x6c, 0x05, 0xea, 0xb4, 0x00, - 0x33, 0xea, 0x44, 0x59, + 0x33, 0xea, 0x5e, 0x59, 0x33, 0xea, 0x00, 0x00, 0x80, 0x3d, 0x7a, 0x00, - 0xfc, 0x42, 0x68, 0x7c, + 0xfc, 0x42, 0xa0, 0x7c, 0x7f, 0x3d, 0x7a, 0x08, - 0x00, 0x30, 0x45, 0x59, - 0x01, 0x30, 0x01, 0x30, - 0x09, 0xea, 0x50, 0x59, + 0x00, 0x36, 0x5f, 0x59, + 0x01, 0x36, 0x01, 0x30, + 0x09, 0xea, 0x64, 0x59, 0x09, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xf8, 0x41, - 0x01, 0xa4, 0x5d, 0x6c, - 0x00, 0xe2, 0x30, 0x5c, - 0x20, 0x33, 0x67, 0x02, - 0x01, 0x00, 0x60, 0x32, - 0x02, 0xa6, 0x82, 0x7c, - 0x00, 0xe2, 0x46, 0x5c, - 0x00, 0xe2, 0x56, 0x58, - 0x00, 0xe2, 0x66, 0x58, - 0x00, 0xe2, 0x3a, 0x58, - 0x00, 0x30, 0x45, 0x59, - 0x01, 0x30, 0x01, 0x30, - 0x20, 0x19, 0x82, 0x6c, - 0x00, 0xe2, 0xb2, 0x5c, - 0x04, 0x19, 0x9c, 0x6c, + 0x00, 0xe2, 0x14, 0x42, + 0x01, 0xa4, 0x95, 0x6c, + 0x00, 0xe2, 0x68, 0x5c, + 0x20, 0x39, 0x73, 0x02, + 0x01, 0x00, 0x6c, 0x32, + 0x02, 0xa6, 0xba, 0x7c, + 0x00, 0xe2, 0x7e, 0x5c, + 0x00, 0xe2, 0x76, 0x58, + 0x00, 0xe2, 0x86, 0x58, + 0x00, 0xe2, 0x5a, 0x58, + 0x00, 0x36, 0x5f, 0x59, + 0x01, 0x36, 0x01, 0x30, + 0x20, 0x19, 0xba, 0x6c, + 0x00, 0xe2, 0xea, 0x5c, + 0x04, 0x19, 0xd4, 0x6c, 0x02, 0x19, 0x32, 0x00, - 0x01, 0x84, 0x9d, 0x7c, - 0x01, 0x1b, 0x96, 0x7c, - 0x01, 0x1a, 0x9c, 0x6c, - 0x00, 0xe2, 0x4c, 0x44, - 0x80, 0x4b, 0xa2, 0x6c, - 0x01, 0x4c, 0x9e, 0x7c, - 0x03, 0x42, 0x4c, 0x6c, - 0x00, 0xe2, 0xe0, 0x5b, + 0x01, 0x84, 0xd5, 0x7c, + 0x01, 0x1b, 0xce, 0x7c, + 0x01, 0x1a, 0xd4, 0x6c, + 0x00, 0xe2, 0x84, 0x44, + 0x80, 0x4b, 0xda, 0x6c, + 0x01, 0x4c, 0xd6, 0x7c, + 0x03, 0x42, 0x84, 0x6c, + 0x00, 0xe2, 0x0a, 0x5c, 0x80, 0xf9, 0xf2, 0x01, - 0x04, 0x33, 0xf9, 0x79, - 0x00, 0xe2, 0xf8, 0x41, - 0x08, 0x5d, 0xba, 0x6c, - 0x00, 0xe2, 0x56, 0x58, - 0x00, 0x30, 0x45, 0x59, - 0x01, 0x30, 0x01, 0x30, - 0x02, 0x1b, 0xaa, 0x7c, - 0x08, 0x5d, 0xb8, 0x7c, + 0x04, 0x39, 0x15, 0x7a, + 0x00, 0xe2, 0x14, 0x42, + 0x08, 0x5d, 0xf2, 0x6c, + 0x00, 0xe2, 0x76, 0x58, + 0x00, 0x36, 0x5f, 0x59, + 0x01, 0x36, 0x01, 0x30, + 0x02, 0x1b, 0xe2, 0x7c, + 0x08, 0x5d, 0xf0, 0x7c, 0x03, 0x68, 0x00, 0x37, 0x01, 0x84, 0x09, 0x07, - 0x80, 0x1b, 0xc4, 0x7c, - 0x80, 0x84, 0xc5, 0x6c, + 0x80, 0x1b, 0xfc, 0x7c, + 0x80, 0x84, 0xfd, 0x6c, 0xff, 0x85, 0x0b, 0x1b, 0xff, 0x86, 0x0d, 0x23, 0xff, 0x87, 0x0f, 0x23, 0xf8, 0x1b, 0x08, 0x0b, 0xff, 0xea, 0x06, 0x0b, 0x03, 0x68, 0x00, 0x37, - 0x00, 0xe2, 0xc4, 0x58, + 0x00, 0xe2, 0xd6, 0x58, 0x10, 0xea, 0x18, 0x00, 0xf9, 0xd9, 0xb2, 0x0d, 0x01, 0xd9, 0xb2, 0x05, 0x01, 0x52, 0x48, 0x31, - 0x20, 0xa4, 0xee, 0x7c, - 0x20, 0x5b, 0xee, 0x7c, - 0x80, 0xf9, 0xfc, 0x7c, + 0x20, 0xa4, 0x26, 0x7d, + 0x20, 0x5b, 0x26, 0x7d, + 0x80, 0xf9, 0x34, 0x7d, 0x02, 0xea, 0xb4, 0x00, 0x11, 0x00, 0x00, 0x10, - 0x04, 0x19, 0x08, 0x7d, + 0x04, 0x19, 0x40, 0x7d, 0xdf, 0x19, 0x32, 0x08, - 0x60, 0x5b, 0xe6, 0x6c, - 0x01, 0x4c, 0xe2, 0x7c, + 0x60, 0x5b, 0x40, 0x6d, + 0x01, 0x4c, 0x1a, 0x7d, 0x20, 0x19, 0x32, 0x00, 0x01, 0xd9, 0xb2, 0x05, 0x02, 0xea, 0xb4, 0x00, 0x01, 0xd9, 0xb2, 0x05, - 0x10, 0x5b, 0x00, 0x6d, - 0x08, 0x5b, 0x0a, 0x6d, - 0x20, 0x5b, 0xfa, 0x6c, - 0x02, 0x5b, 0x2a, 0x6d, - 0x0e, 0xea, 0x50, 0x59, + 0x10, 0x5b, 0x38, 0x6d, + 0x08, 0x5b, 0x42, 0x6d, + 0x20, 0x5b, 0x32, 0x6d, + 0x02, 0x5b, 0x62, 0x6d, + 0x0e, 0xea, 0x64, 0x59, 0x0e, 0xea, 0x04, 0x00, - 0x80, 0xf9, 0xea, 0x6c, + 0x80, 0xf9, 0x22, 0x6d, 0xdf, 0x5c, 0xb8, 0x08, 0x01, 0xd9, 0xb2, 0x05, - 0x01, 0xa4, 0xe5, 0x6d, - 0x00, 0xe2, 0x30, 0x5c, - 0x00, 0xe2, 0x34, 0x5d, + 0x01, 0xa4, 0x1d, 0x6e, + 0x00, 0xe2, 0x68, 0x5c, + 0x00, 0xe2, 0x6c, 0x5d, 0x01, 0x90, 0x21, 0x1b, 0x01, 0xd9, 0xb2, 0x05, - 0x00, 0xe2, 0x32, 0x5b, + 0x00, 0xe2, 0x52, 0x5b, 0xf3, 0x96, 0xd5, 0x19, - 0x00, 0xe2, 0x18, 0x55, - 0x80, 0x96, 0x19, 0x6d, - 0x0f, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0x50, 0x55, + 0x80, 0x96, 0x51, 0x6d, + 0x0f, 0xea, 0x64, 0x59, 0x0f, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x20, 0x45, + 0x00, 0xe2, 0x58, 0x45, 0x04, 0x8c, 0xe1, 0x30, 0x01, 0xea, 0xf2, 0x00, 0x02, 0xea, 0x36, 0x00, 0xa8, 0xea, 0x32, 0x00, - 0xff, 0x97, 0x27, 0x7d, - 0x14, 0xea, 0x50, 0x59, + 0xff, 0x97, 0x5f, 0x7d, + 0x14, 0xea, 0x64, 0x59, 0x14, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x96, 0x5d, + 0x00, 0xe2, 0xce, 0x5d, 0x01, 0xd9, 0xb2, 0x05, 0x09, 0x80, 0xe1, 0x30, 0x02, 0xea, 0x36, 0x00, 0xa8, 0xea, 0x32, 0x00, - 0x00, 0xe2, 0x8e, 0x5d, + 0x00, 0xe2, 0xc6, 0x5d, 0x01, 0xd9, 0xb2, 0x05, - 0x02, 0xa6, 0x44, 0x7d, - 0x00, 0xe2, 0x3e, 0x59, - 0x20, 0x5b, 0x52, 0x6d, - 0xfc, 0x42, 0x3e, 0x7d, - 0x10, 0x40, 0x40, 0x6d, - 0x20, 0x4d, 0x42, 0x7d, - 0x08, 0x5d, 0x52, 0x6d, - 0x02, 0xa6, 0xe6, 0x6b, - 0x00, 0xe2, 0x3e, 0x59, - 0x20, 0x5b, 0x52, 0x6d, - 0x01, 0x1b, 0x72, 0x6d, - 0xfc, 0x42, 0x4e, 0x7d, - 0x10, 0x40, 0x50, 0x6d, - 0x20, 0x4d, 0x64, 0x78, - 0x08, 0x5d, 0x64, 0x78, + 0x02, 0xa6, 0x7c, 0x7d, + 0x00, 0xe2, 0x56, 0x59, + 0x20, 0x5b, 0x8a, 0x6d, + 0xfc, 0x42, 0x76, 0x7d, + 0x10, 0x40, 0x78, 0x6d, + 0x20, 0x4d, 0x7a, 0x7d, + 0x08, 0x5d, 0x8a, 0x6d, + 0x02, 0xa6, 0x10, 0x6c, + 0x00, 0xe2, 0x56, 0x59, + 0x20, 0x5b, 0x8a, 0x6d, + 0x01, 0x1b, 0xaa, 0x6d, + 0xfc, 0x42, 0x86, 0x7d, + 0x10, 0x40, 0x88, 0x6d, + 0x20, 0x4d, 0x84, 0x78, + 0x08, 0x5d, 0x84, 0x78, 0x02, 0x19, 0x32, 0x00, 0x01, 0x5b, 0x40, 0x31, - 0x00, 0xe2, 0xb2, 0x5c, - 0x00, 0xe2, 0x9e, 0x5b, + 0x00, 0xe2, 0xea, 0x5c, + 0x00, 0xe2, 0xcc, 0x5b, 0x20, 0xea, 0xb6, 0x00, - 0x00, 0xe2, 0xe0, 0x5b, + 0x00, 0xe2, 0x0a, 0x5c, 0x20, 0x5c, 0xb8, 0x00, - 0x04, 0x19, 0x68, 0x6d, - 0x01, 0x1a, 0x68, 0x6d, - 0x00, 0xe2, 0x3e, 0x59, - 0x01, 0x1a, 0x64, 0x78, + 0x04, 0x19, 0xa0, 0x6d, + 0x01, 0x1a, 0xa0, 0x6d, + 0x00, 0xe2, 0x56, 0x59, + 0x01, 0x1a, 0x84, 0x78, 0x80, 0xf9, 0xf2, 0x01, - 0x20, 0xa0, 0xcc, 0x7d, + 0x20, 0xa0, 0x04, 0x7e, 0xff, 0x90, 0x21, 0x1b, - 0x08, 0x92, 0x43, 0x6b, + 0x08, 0x92, 0x63, 0x6b, 0x02, 0xea, 0xb4, 0x04, 0x01, 0xa4, 0x49, 0x03, - 0x40, 0x5b, 0x82, 0x6d, - 0x00, 0xe2, 0x3e, 0x59, - 0x40, 0x5b, 0x82, 0x6d, - 0x04, 0x5d, 0xe6, 0x7d, - 0x01, 0x1a, 0xe6, 0x7d, - 0x20, 0x4d, 0x64, 0x78, - 0x40, 0x5b, 0xcc, 0x7d, - 0x04, 0x5d, 0xe6, 0x7d, - 0x01, 0x1a, 0xe6, 0x7d, + 0x40, 0x5b, 0xba, 0x6d, + 0x00, 0xe2, 0x56, 0x59, + 0x40, 0x5b, 0xba, 0x6d, + 0x04, 0x5d, 0x1e, 0x7e, + 0x01, 0x1a, 0x1e, 0x7e, + 0x20, 0x4d, 0x84, 0x78, + 0x40, 0x5b, 0x04, 0x7e, + 0x04, 0x5d, 0x1e, 0x7e, + 0x01, 0x1a, 0x1e, 0x7e, 0x80, 0xf9, 0xf2, 0x01, 0xff, 0x90, 0x21, 0x1b, - 0x08, 0x92, 0x43, 0x6b, + 0x08, 0x92, 0x63, 0x6b, 0x02, 0xea, 0xb4, 0x04, - 0x00, 0xe2, 0x3e, 0x59, - 0x01, 0x1b, 0x64, 0x78, + 0x00, 0xe2, 0x56, 0x59, + 0x01, 0x1b, 0x84, 0x78, 0x80, 0xf9, 0xf2, 0x01, 0x02, 0xea, 0xb4, 0x04, - 0x00, 0xe2, 0x3e, 0x59, - 0x01, 0x1b, 0xaa, 0x6d, - 0x40, 0x5b, 0xb8, 0x7d, - 0x01, 0x1b, 0xaa, 0x6d, + 0x00, 0xe2, 0x56, 0x59, + 0x01, 0x1b, 0xe2, 0x6d, + 0x40, 0x5b, 0xf0, 0x7d, + 0x01, 0x1b, 0xe2, 0x6d, 0x02, 0x19, 0x32, 0x00, - 0x01, 0x1a, 0x64, 0x78, + 0x01, 0x1a, 0x84, 0x78, 0x80, 0xf9, 0xf2, 0x01, 0xff, 0xea, 0x10, 0x03, 0x08, 0x92, 0x25, 0x03, - 0x00, 0xe2, 0x42, 0x43, - 0x01, 0x1a, 0xb4, 0x7d, - 0x40, 0x5b, 0xb0, 0x7d, - 0x01, 0x1a, 0x9e, 0x6d, - 0xfc, 0x42, 0x64, 0x78, - 0x01, 0x1a, 0xb8, 0x6d, - 0x10, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0x62, 0x43, + 0x01, 0x1a, 0xec, 0x7d, + 0x40, 0x5b, 0xe8, 0x7d, + 0x01, 0x1a, 0xd6, 0x6d, + 0xfc, 0x42, 0x84, 0x78, + 0x01, 0x1a, 0xf0, 0x6d, + 0x10, 0xea, 0x64, 0x59, 0x10, 0xea, 0x04, 0x00, - 0xfc, 0x42, 0x64, 0x78, - 0x10, 0x40, 0xbe, 0x6d, - 0x20, 0x4d, 0x64, 0x78, - 0x40, 0x5b, 0x9e, 0x6d, - 0x01, 0x1a, 0x64, 0x78, + 0xfc, 0x42, 0x84, 0x78, + 0x10, 0x40, 0xf6, 0x6d, + 0x20, 0x4d, 0x84, 0x78, + 0x40, 0x5b, 0xd6, 0x6d, + 0x01, 0x1a, 0x84, 0x78, 0x01, 0x90, 0x21, 0x1b, 0x30, 0x3f, 0xc0, 0x09, - 0x30, 0xe0, 0x64, 0x60, - 0x40, 0x4b, 0x64, 0x68, + 0x30, 0xe0, 0x84, 0x60, + 0x40, 0x4b, 0x84, 0x68, 0xff, 0xea, 0x52, 0x01, - 0xee, 0x00, 0xd2, 0x6d, + 0xee, 0x00, 0x0c, 0x6e, 0x80, 0xf9, 0xf2, 0x01, 0xff, 0x90, 0x21, 0x1b, 0x02, 0xea, 0xb4, 0x00, 0x20, 0xea, 0x9a, 0x00, - 0xf3, 0x42, 0xde, 0x6d, - 0x12, 0xea, 0x50, 0x59, + 0xf3, 0x42, 0x16, 0x6e, + 0x12, 0xea, 0x64, 0x59, 0x12, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xf8, 0x41, - 0x0d, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0x14, 0x42, + 0x0d, 0xea, 0x64, 0x59, 0x0d, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xf8, 0x41, + 0x00, 0xe2, 0x14, 0x42, 0x01, 0x90, 0x21, 0x1b, - 0x11, 0xea, 0x50, 0x59, + 0x11, 0xea, 0x64, 0x59, 0x11, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x32, 0x5b, + 0x00, 0xe2, 0x52, 0x5b, 0x08, 0x5a, 0xb4, 0x00, - 0x00, 0xe2, 0x0c, 0x5e, + 0x00, 0xe2, 0x44, 0x5e, 0xa8, 0xea, 0x32, 0x00, - 0x00, 0xe2, 0x3e, 0x59, - 0x80, 0x1a, 0xfa, 0x7d, - 0x00, 0xe2, 0x0c, 0x5e, + 0x00, 0xe2, 0x56, 0x59, + 0x80, 0x1a, 0x32, 0x7e, + 0x00, 0xe2, 0x44, 0x5e, 0x80, 0x19, 0x32, 0x00, - 0x40, 0x5b, 0x00, 0x6e, - 0x08, 0x5a, 0x00, 0x7e, - 0x20, 0x4d, 0x64, 0x78, + 0x40, 0x5b, 0x38, 0x6e, + 0x08, 0x5a, 0x38, 0x7e, + 0x20, 0x4d, 0x84, 0x78, 0x02, 0x84, 0x09, 0x03, - 0x40, 0x5b, 0xcc, 0x7d, + 0x40, 0x5b, 0x04, 0x7e, 0xff, 0x90, 0x21, 0x1b, 0x80, 0xf9, 0xf2, 0x01, - 0x08, 0x92, 0x43, 0x6b, + 0x08, 0x92, 0x63, 0x6b, 0x02, 0xea, 0xb4, 0x04, - 0x01, 0x38, 0xe1, 0x30, - 0x05, 0x39, 0xe3, 0x98, + 0x01, 0x40, 0xe1, 0x30, + 0x05, 0x41, 0xe3, 0x98, 0x01, 0xe0, 0xf4, 0x31, 0xff, 0xea, 0xc0, 0x09, - 0x00, 0x3a, 0xe5, 0x20, - 0x00, 0x3b, 0xe7, 0x20, + 0x00, 0x42, 0xe5, 0x20, + 0x00, 0x43, 0xe7, 0x20, 0x01, 0xfa, 0xc0, 0x31, 0x04, 0xea, 0xe8, 0x30, 0xff, 0xea, 0xf0, 0x08, @@ -794,12 +822,20 @@ static uint8_t seqprog[] = { }; typedef int ahd_patch_func_t (struct ahd_softc *ahd); +static ahd_patch_func_t ahd_patch23_func; + +static int +ahd_patch23_func(struct ahd_softc *ahd) +{ + return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0); +} + static ahd_patch_func_t ahd_patch22_func; static int ahd_patch22_func(struct ahd_softc *ahd) { - return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0); + return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) == 0); } static ahd_patch_func_t ahd_patch21_func; @@ -807,7 +843,7 @@ static ahd_patch_func_t ahd_patch21_func; static int ahd_patch21_func(struct ahd_softc *ahd) { - return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) == 0); + return ((ahd->flags & AHD_INITIATORROLE) != 0); } static ahd_patch_func_t ahd_patch20_func; @@ -815,7 +851,7 @@ static ahd_patch_func_t ahd_patch20_func; static int ahd_patch20_func(struct ahd_softc *ahd) { - return ((ahd->features & AHD_RTI) == 0); + return ((ahd->flags & AHD_TARGETROLE) != 0); } static ahd_patch_func_t ahd_patch19_func; @@ -823,7 +859,7 @@ static ahd_patch_func_t ahd_patch19_func; static int ahd_patch19_func(struct ahd_softc *ahd) { - return ((ahd->flags & AHD_INITIATORROLE) != 0); + return ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0); } static ahd_patch_func_t ahd_patch18_func; @@ -831,7 +867,7 @@ static ahd_patch_func_t ahd_patch18_func; static int ahd_patch18_func(struct ahd_softc *ahd) { - return ((ahd->flags & AHD_TARGETROLE) != 0); + return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0); } static ahd_patch_func_t ahd_patch17_func; @@ -839,7 +875,7 @@ static ahd_patch_func_t ahd_patch17_func; static int ahd_patch17_func(struct ahd_softc *ahd) { - return ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0); + return ((ahd->flags & AHD_39BIT_ADDRESSING) != 0); } static ahd_patch_func_t ahd_patch16_func; @@ -847,7 +883,7 @@ static ahd_patch_func_t ahd_patch16_func; static int ahd_patch16_func(struct ahd_softc *ahd) { - return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0); + return ((ahd->flags & AHD_64BIT_ADDRESSING) != 0); } static ahd_patch_func_t ahd_patch15_func; @@ -855,7 +891,7 @@ static ahd_patch_func_t ahd_patch15_func; static int ahd_patch15_func(struct ahd_softc *ahd) { - return ((ahd->flags & AHD_39BIT_ADDRESSING) != 0); + return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) == 0); } static ahd_patch_func_t ahd_patch14_func; @@ -863,7 +899,7 @@ static ahd_patch_func_t ahd_patch14_func; static int ahd_patch14_func(struct ahd_softc *ahd) { - return ((ahd->flags & AHD_64BIT_ADDRESSING) != 0); + return ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0); } static ahd_patch_func_t ahd_patch13_func; @@ -871,7 +907,7 @@ static ahd_patch_func_t ahd_patch13_func; static int ahd_patch13_func(struct ahd_softc *ahd) { - return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) == 0); + return ((ahd->features & AHD_RTI) == 0); } static ahd_patch_func_t ahd_patch12_func; @@ -879,7 +915,7 @@ static ahd_patch_func_t ahd_patch12_func; static int ahd_patch12_func(struct ahd_softc *ahd) { - return ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0); + return ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0); } static ahd_patch_func_t ahd_patch11_func; @@ -887,7 +923,7 @@ static ahd_patch_func_t ahd_patch11_func; static int ahd_patch11_func(struct ahd_softc *ahd) { - return ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0); + return ((ahd->bugs & AHD_BUSFREEREV_BUG) == 0); } static ahd_patch_func_t ahd_patch10_func; @@ -895,7 +931,7 @@ static ahd_patch_func_t ahd_patch10_func; static int ahd_patch10_func(struct ahd_softc *ahd) { - return ((ahd->bugs & AHD_BUSFREEREV_BUG) == 0); + return ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0); } static ahd_patch_func_t ahd_patch9_func; @@ -903,7 +939,7 @@ static ahd_patch_func_t ahd_patch9_func; static int ahd_patch9_func(struct ahd_softc *ahd) { - return ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0); + return ((ahd->features & AHD_FAST_CDB_DELIVERY) != 0); } static ahd_patch_func_t ahd_patch8_func; @@ -992,147 +1028,149 @@ static struct patch { { ahd_patch0_func, 5, 1, 1 }, { ahd_patch2_func, 6, 1, 2 }, { ahd_patch0_func, 7, 1, 1 }, - { ahd_patch3_func, 20, 5, 1 }, - { ahd_patch2_func, 29, 1, 2 }, - { ahd_patch0_func, 30, 1, 1 }, - { ahd_patch1_func, 37, 1, 2 }, - { ahd_patch0_func, 38, 1, 1 }, - { ahd_patch2_func, 43, 1, 2 }, - { ahd_patch0_func, 44, 1, 1 }, - { ahd_patch2_func, 47, 1, 2 }, - { ahd_patch0_func, 48, 1, 1 }, - { ahd_patch2_func, 51, 1, 2 }, - { ahd_patch0_func, 52, 1, 1 }, - { ahd_patch2_func, 65, 1, 2 }, - { ahd_patch0_func, 66, 1, 1 }, - { ahd_patch2_func, 69, 1, 2 }, - { ahd_patch0_func, 70, 1, 1 }, - { ahd_patch1_func, 73, 1, 2 }, - { ahd_patch0_func, 74, 1, 1 }, - { ahd_patch4_func, 107, 1, 1 }, - { ahd_patch2_func, 162, 6, 1 }, - { ahd_patch1_func, 168, 2, 1 }, - { ahd_patch5_func, 170, 1, 1 }, - { ahd_patch2_func, 179, 1, 2 }, - { ahd_patch0_func, 180, 1, 1 }, - { ahd_patch6_func, 181, 2, 2 }, - { ahd_patch0_func, 183, 6, 3 }, - { ahd_patch2_func, 186, 1, 2 }, - { ahd_patch0_func, 187, 1, 1 }, - { ahd_patch2_func, 190, 1, 2 }, - { ahd_patch0_func, 191, 1, 1 }, - { ahd_patch7_func, 193, 2, 1 }, - { ahd_patch5_func, 201, 16, 2 }, - { ahd_patch0_func, 217, 1, 1 }, - { ahd_patch8_func, 237, 2, 1 }, - { ahd_patch1_func, 241, 1, 2 }, - { ahd_patch0_func, 242, 1, 1 }, - { ahd_patch7_func, 245, 2, 1 }, - { ahd_patch1_func, 259, 1, 2 }, - { ahd_patch0_func, 260, 1, 1 }, - { ahd_patch1_func, 263, 1, 2 }, - { ahd_patch0_func, 264, 1, 1 }, - { ahd_patch2_func, 267, 1, 2 }, - { ahd_patch0_func, 268, 1, 1 }, - { ahd_patch1_func, 323, 1, 2 }, - { ahd_patch0_func, 324, 1, 1 }, - { ahd_patch2_func, 332, 1, 2 }, - { ahd_patch0_func, 333, 1, 1 }, - { ahd_patch2_func, 336, 1, 2 }, - { ahd_patch0_func, 337, 1, 1 }, - { ahd_patch1_func, 343, 1, 2 }, - { ahd_patch0_func, 344, 1, 1 }, - { ahd_patch1_func, 346, 1, 2 }, - { ahd_patch0_func, 347, 1, 1 }, - { ahd_patch9_func, 366, 1, 1 }, - { ahd_patch9_func, 369, 1, 1 }, - { ahd_patch9_func, 371, 1, 1 }, - { ahd_patch9_func, 383, 1, 1 }, - { ahd_patch1_func, 393, 1, 2 }, - { ahd_patch0_func, 394, 1, 1 }, - { ahd_patch1_func, 396, 1, 2 }, - { ahd_patch0_func, 397, 1, 1 }, - { ahd_patch1_func, 405, 1, 2 }, - { ahd_patch0_func, 406, 1, 1 }, - { ahd_patch2_func, 419, 1, 2 }, - { ahd_patch0_func, 420, 1, 1 }, - { ahd_patch10_func, 450, 1, 1 }, - { ahd_patch1_func, 457, 1, 2 }, - { ahd_patch0_func, 458, 1, 1 }, - { ahd_patch2_func, 470, 1, 2 }, - { ahd_patch0_func, 471, 1, 1 }, - { ahd_patch11_func, 476, 6, 2 }, - { ahd_patch0_func, 482, 1, 1 }, - { ahd_patch12_func, 505, 1, 1 }, - { ahd_patch13_func, 514, 1, 1 }, - { ahd_patch14_func, 515, 1, 2 }, - { ahd_patch0_func, 516, 1, 1 }, - { ahd_patch15_func, 519, 1, 1 }, - { ahd_patch14_func, 520, 1, 1 }, - { ahd_patch16_func, 531, 1, 2 }, - { ahd_patch0_func, 532, 1, 1 }, - { ahd_patch1_func, 551, 1, 2 }, - { ahd_patch0_func, 552, 1, 1 }, - { ahd_patch1_func, 555, 1, 2 }, - { ahd_patch0_func, 556, 1, 1 }, - { ahd_patch2_func, 561, 1, 2 }, - { ahd_patch0_func, 562, 1, 1 }, - { ahd_patch2_func, 566, 1, 2 }, - { ahd_patch0_func, 567, 1, 1 }, - { ahd_patch1_func, 568, 1, 2 }, - { ahd_patch0_func, 569, 1, 1 }, - { ahd_patch2_func, 580, 1, 2 }, - { ahd_patch0_func, 581, 1, 1 }, - { ahd_patch17_func, 585, 1, 1 }, - { ahd_patch18_func, 590, 1, 1 }, - { ahd_patch19_func, 591, 2, 1 }, - { ahd_patch18_func, 595, 1, 2 }, - { ahd_patch0_func, 596, 1, 1 }, - { ahd_patch2_func, 599, 1, 2 }, - { ahd_patch0_func, 600, 1, 1 }, - { ahd_patch2_func, 615, 1, 2 }, - { ahd_patch0_func, 616, 1, 1 }, - { ahd_patch20_func, 617, 14, 1 }, - { ahd_patch1_func, 635, 1, 2 }, - { ahd_patch0_func, 636, 1, 1 }, - { ahd_patch20_func, 637, 1, 1 }, - { ahd_patch1_func, 649, 1, 2 }, - { ahd_patch0_func, 650, 1, 1 }, - { ahd_patch1_func, 657, 1, 2 }, - { ahd_patch0_func, 658, 1, 1 }, - { ahd_patch17_func, 681, 1, 1 }, - { ahd_patch17_func, 719, 1, 1 }, - { ahd_patch1_func, 730, 1, 2 }, - { ahd_patch0_func, 731, 1, 1 }, - { ahd_patch1_func, 748, 1, 2 }, - { ahd_patch0_func, 749, 1, 1 }, - { ahd_patch1_func, 751, 1, 2 }, - { ahd_patch0_func, 752, 1, 1 }, - { ahd_patch1_func, 755, 1, 2 }, - { ahd_patch0_func, 756, 1, 1 }, - { ahd_patch21_func, 758, 1, 2 }, - { ahd_patch0_func, 759, 2, 1 }, - { ahd_patch22_func, 762, 4, 2 }, - { ahd_patch0_func, 766, 1, 1 }, - { ahd_patch22_func, 774, 11, 1 } + { ahd_patch3_func, 36, 5, 1 }, + { ahd_patch2_func, 45, 1, 2 }, + { ahd_patch0_func, 46, 1, 1 }, + { ahd_patch1_func, 53, 1, 2 }, + { ahd_patch0_func, 54, 1, 1 }, + { ahd_patch2_func, 59, 1, 2 }, + { ahd_patch0_func, 60, 1, 1 }, + { ahd_patch2_func, 63, 1, 2 }, + { ahd_patch0_func, 64, 1, 1 }, + { ahd_patch2_func, 67, 1, 2 }, + { ahd_patch0_func, 68, 1, 1 }, + { ahd_patch4_func, 116, 1, 1 }, + { ahd_patch2_func, 175, 3, 1 }, + { ahd_patch1_func, 178, 2, 1 }, + { ahd_patch5_func, 180, 1, 1 }, + { ahd_patch2_func, 189, 1, 2 }, + { ahd_patch0_func, 190, 1, 1 }, + { ahd_patch6_func, 191, 2, 2 }, + { ahd_patch0_func, 193, 6, 3 }, + { ahd_patch2_func, 196, 1, 2 }, + { ahd_patch0_func, 197, 1, 1 }, + { ahd_patch2_func, 200, 1, 2 }, + { ahd_patch0_func, 201, 1, 1 }, + { ahd_patch3_func, 203, 1, 1 }, + { ahd_patch7_func, 204, 3, 1 }, + { ahd_patch3_func, 213, 1, 1 }, + { ahd_patch5_func, 214, 16, 2 }, + { ahd_patch0_func, 230, 1, 1 }, + { ahd_patch8_func, 250, 2, 1 }, + { ahd_patch1_func, 254, 1, 2 }, + { ahd_patch0_func, 255, 1, 1 }, + { ahd_patch7_func, 258, 3, 1 }, + { ahd_patch1_func, 273, 1, 2 }, + { ahd_patch0_func, 274, 1, 1 }, + { ahd_patch1_func, 277, 1, 2 }, + { ahd_patch0_func, 278, 1, 1 }, + { ahd_patch2_func, 281, 1, 2 }, + { ahd_patch0_func, 282, 1, 1 }, + { ahd_patch9_func, 295, 2, 2 }, + { ahd_patch0_func, 297, 1, 1 }, + { ahd_patch1_func, 339, 1, 2 }, + { ahd_patch0_func, 340, 1, 1 }, + { ahd_patch2_func, 348, 1, 2 }, + { ahd_patch0_func, 349, 1, 1 }, + { ahd_patch2_func, 352, 1, 2 }, + { ahd_patch0_func, 353, 1, 1 }, + { ahd_patch1_func, 359, 1, 2 }, + { ahd_patch0_func, 360, 1, 1 }, + { ahd_patch1_func, 362, 1, 2 }, + { ahd_patch0_func, 363, 1, 1 }, + { ahd_patch10_func, 382, 1, 1 }, + { ahd_patch10_func, 385, 1, 1 }, + { ahd_patch10_func, 387, 1, 1 }, + { ahd_patch10_func, 399, 1, 1 }, + { ahd_patch1_func, 409, 1, 2 }, + { ahd_patch0_func, 410, 1, 1 }, + { ahd_patch1_func, 412, 1, 2 }, + { ahd_patch0_func, 413, 1, 1 }, + { ahd_patch1_func, 421, 1, 2 }, + { ahd_patch0_func, 422, 1, 1 }, + { ahd_patch2_func, 435, 1, 2 }, + { ahd_patch0_func, 436, 1, 1 }, + { ahd_patch11_func, 472, 1, 1 }, + { ahd_patch1_func, 480, 1, 2 }, + { ahd_patch0_func, 481, 1, 1 }, + { ahd_patch2_func, 493, 1, 2 }, + { ahd_patch0_func, 494, 1, 1 }, + { ahd_patch12_func, 497, 6, 2 }, + { ahd_patch0_func, 503, 1, 1 }, + { ahd_patch13_func, 524, 7, 1 }, + { ahd_patch14_func, 533, 1, 1 }, + { ahd_patch15_func, 542, 1, 1 }, + { ahd_patch16_func, 543, 1, 2 }, + { ahd_patch0_func, 544, 1, 1 }, + { ahd_patch17_func, 547, 1, 1 }, + { ahd_patch16_func, 548, 1, 1 }, + { ahd_patch18_func, 559, 1, 2 }, + { ahd_patch0_func, 560, 1, 1 }, + { ahd_patch1_func, 579, 1, 2 }, + { ahd_patch0_func, 580, 1, 1 }, + { ahd_patch1_func, 583, 1, 2 }, + { ahd_patch0_func, 584, 1, 1 }, + { ahd_patch2_func, 589, 1, 2 }, + { ahd_patch0_func, 590, 1, 1 }, + { ahd_patch2_func, 594, 1, 2 }, + { ahd_patch0_func, 595, 1, 1 }, + { ahd_patch1_func, 596, 1, 2 }, + { ahd_patch0_func, 597, 1, 1 }, + { ahd_patch2_func, 608, 1, 2 }, + { ahd_patch0_func, 609, 1, 1 }, + { ahd_patch19_func, 613, 1, 1 }, + { ahd_patch20_func, 618, 1, 1 }, + { ahd_patch21_func, 619, 2, 1 }, + { ahd_patch20_func, 623, 1, 2 }, + { ahd_patch0_func, 624, 1, 1 }, + { ahd_patch2_func, 627, 1, 2 }, + { ahd_patch0_func, 628, 1, 1 }, + { ahd_patch2_func, 643, 1, 2 }, + { ahd_patch0_func, 644, 1, 1 }, + { ahd_patch13_func, 645, 14, 1 }, + { ahd_patch1_func, 663, 1, 2 }, + { ahd_patch0_func, 664, 1, 1 }, + { ahd_patch13_func, 665, 1, 1 }, + { ahd_patch1_func, 677, 1, 2 }, + { ahd_patch0_func, 678, 1, 1 }, + { ahd_patch1_func, 685, 1, 2 }, + { ahd_patch0_func, 686, 1, 1 }, + { ahd_patch19_func, 709, 1, 1 }, + { ahd_patch19_func, 747, 1, 1 }, + { ahd_patch1_func, 758, 1, 2 }, + { ahd_patch0_func, 759, 1, 1 }, + { ahd_patch1_func, 776, 1, 2 }, + { ahd_patch0_func, 777, 1, 1 }, + { ahd_patch1_func, 779, 1, 2 }, + { ahd_patch0_func, 780, 1, 1 }, + { ahd_patch1_func, 783, 1, 2 }, + { ahd_patch0_func, 784, 1, 1 }, + { ahd_patch22_func, 786, 1, 2 }, + { ahd_patch0_func, 787, 2, 1 }, + { ahd_patch23_func, 790, 4, 2 }, + { ahd_patch0_func, 794, 1, 1 }, + { ahd_patch23_func, 802, 11, 1 } }; static struct cs { uint16_t begin; uint16_t end; } critical_sections[] = { - { 11, 12 }, - { 13, 14 }, - { 29, 42 }, - { 56, 59 }, - { 101, 128 }, - { 129, 157 }, - { 159, 162 }, - { 170, 178 }, - { 201, 250 }, - { 681, 697 }, - { 697, 711 }, - { 721, 725 } + { 17, 28 }, + { 29, 30 }, + { 47, 58 }, + { 61, 63 }, + { 65, 66 }, + { 72, 92 }, + { 110, 137 }, + { 138, 175 }, + { 180, 188 }, + { 213, 264 }, + { 425, 433 }, + { 443, 445 }, + { 448, 457 }, + { 709, 739 }, + { 749, 753 } }; static const int num_critical_sections = sizeof(critical_sections) -- GitLab From cd2f1e6980157638f66f427d577a1c368fd4dc12 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Thu, 12 Jan 2006 12:07:13 -0600 Subject: [PATCH 025/465] [SCSI] aic79xx: bump version to 3.0 This takes us past the old 1.x version of the SCSI driver and the 2.x version of the aic website version to reflect the full incorporation of both branches. Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic79xx_osm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h index bc44222d6cc..cb74fccc810 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.h +++ b/drivers/scsi/aic7xxx/aic79xx_osm.h @@ -252,7 +252,7 @@ ahd_scb_timer_reset(struct scb *scb, u_int usec) /***************************** SMP support ************************************/ #include -#define AIC79XX_DRIVER_VERSION "1.3.11" +#define AIC79XX_DRIVER_VERSION "3.0" /*************************** Device Data Structures ***************************/ /* -- GitLab From 745caf71d99c5d4ff4c9e4c0f74e64c429fed531 Mon Sep 17 00:00:00 2001 From: Petr Vandrovec Date: Wed, 11 Jan 2006 11:31:07 -0800 Subject: [PATCH 026/465] [SCSI] Pass proper device from BusLogic to SCSI layer While trying to get SUSE's SLES9 working on system with more than 4GB we've noticed that SCSI layer happilly passes addresses over 4GB to the buslogic driver, which is quite a big problem as buslogic can generate only 32bit busmastering cycles. Fortunately in the current kernels this problem does not exist anymore as SCSI layer now assumes 4GB capable device by default, but it is still good idea to pass correct device structure to the SCSI layer. If nothing else, /sys/block/sda/device now points to /sys/devices/pci0000:00/0000:00:10.0/host0/... instead of /sys/devices/platform/host0/... like it did in the past. Change does nothing for ISA based BusLogic adapters, they'll still end under platform (and they are probably broken for long time as I do not see anything forcing ISA 16MB limit for them). Signed-off-by: Petr Vandrovec Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/BusLogic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index 9d6040bfa06..1c459343292 100644 --- a/drivers/scsi/BusLogic.c +++ b/drivers/scsi/BusLogic.c @@ -2216,6 +2216,7 @@ static int __init BusLogic_init(void) HostAdapter->PCI_Address = ProbeInfo->PCI_Address; HostAdapter->Bus = ProbeInfo->Bus; HostAdapter->Device = ProbeInfo->Device; + HostAdapter->PCI_Device = ProbeInfo->PCI_Device; HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel; HostAdapter->AddressCount = BusLogic_HostAdapterAddressCount[HostAdapter->HostAdapterType]; /* @@ -2296,7 +2297,7 @@ static int __init BusLogic_init(void) scsi_host_put(Host); } else { BusLogic_InitializeHostStructure(HostAdapter, Host); - scsi_add_host(Host, NULL); + scsi_add_host(Host, HostAdapter->PCI_Device ? &HostAdapter->PCI_Device->dev : NULL); scsi_scan_host(Host); BusLogicHostAdapterCount++; } -- GitLab From ac7c66698a2c51e4c6a34b84621c79e7cb89e07d Mon Sep 17 00:00:00 2001 From: "ODonnell, Michael" Date: Wed, 11 Jan 2006 11:26:22 -0800 Subject: [PATCH 027/465] [PATCH] corruption during e100 MDI register access We have identified two related bugs in the e100 driver. Both bugs are related to manipulation of the MDI control register. The first problem is that the Ready bit is being ignored when writing to the Control register; we noticed this because the Linux bonding driver would occasionally come to the spurious conclusion that the link was down when querying Link State. It turned out that by failing to wait for a previous command to complete it was selecting what was essentially a random register in the MDI register set. When we added code that waits for the Ready bit (as shown in the patch file below) all such problems ceased. The second problem is that, although access to the MDI registers involves multiple steps which must not be intermixed, nothing was defending against two or more threads attempting simultaneous access. The most obvious situation where such interference could occur involves the watchdog versus ioctl paths, but there are probably others, so we recommend the locking shown in our patch file. Signed-off-by: Michael O'Donnell Cc: "David S. Miller" Cc: Jeff Garzik Cc: John Ronciak Cc: Ganesh Venkatesan Cc: Jesse Brandeburg Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/e100.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 22cd0455670..23de22631c6 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -132,6 +132,10 @@ * TODO: * o several entry points race with dev->close * o check for tx-no-resources/stop Q races with tx clean/wake Q + * + * FIXES: + * 2005/12/02 - Michael O'Donnell + * - Stratus87247: protect MDI control register manipulations */ #include @@ -578,6 +582,7 @@ struct nic { u16 leds; u16 eeprom_wc; u16 eeprom[256]; + spinlock_t mdio_lock; }; static inline void e100_write_flush(struct nic *nic) @@ -876,15 +881,35 @@ static u16 mdio_ctrl(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) { u32 data_out = 0; unsigned int i; + unsigned long flags; + + /* + * Stratus87247: we shouldn't be writing the MDI control + * register until the Ready bit shows True. Also, since + * manipulation of the MDI control registers is a multi-step + * procedure it should be done under lock. + */ + spin_lock_irqsave(&nic->mdio_lock, flags); + for (i = 100; i; --i) { + if (readl(&nic->csr->mdi_ctrl) & mdi_ready) + break; + udelay(20); + } + if (unlikely(!i)) { + printk("e100.mdio_ctrl(%s) won't go Ready\n", + nic->netdev->name ); + spin_unlock_irqrestore(&nic->mdio_lock, flags); + return 0; /* No way to indicate timeout error */ + } writel((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl); - for(i = 0; i < 100; i++) { + for (i = 0; i < 100; i++) { udelay(20); - if((data_out = readl(&nic->csr->mdi_ctrl)) & mdi_ready) + if ((data_out = readl(&nic->csr->mdi_ctrl)) & mdi_ready) break; } - + spin_unlock_irqrestore(&nic->mdio_lock, flags); DPRINTK(HW, DEBUG, "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n", dir == mdi_read ? "READ" : "WRITE", addr, reg, data, data_out); @@ -2562,6 +2587,7 @@ static int __devinit e100_probe(struct pci_dev *pdev, /* locks must be initialized before calling hw_reset */ spin_lock_init(&nic->cb_lock); spin_lock_init(&nic->cmd_lock); + spin_lock_init(&nic->mdio_lock); /* Reset the device before pci_set_master() in case device is in some * funky state and has an interrupt pending - hint: we don't have the -- GitLab From 9ad8b9d1520db4d317d791eeb8d6e47c366be82c Mon Sep 17 00:00:00 2001 From: dann frazier Date: Wed, 11 Jan 2006 11:26:24 -0800 Subject: [PATCH 028/465] [PATCH] CONFIG_AIRO needs CONFIG_CRYPTO airo.c currently has MICSUPPORT enabled, which requires CONFIG_CRYPTO. A user reported a build failure which is due to the lack of a Kconfig dependency. See http://bugs.debian.org/344205. This patch makes Kconfig enforce this dependency. Signed-off-by: dann frazier Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/wireless/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 24f7967aab6..c1a6e69f790 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -243,7 +243,7 @@ config IPW2200_DEBUG config AIRO tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards" - depends on NET_RADIO && ISA_DMA_API && (PCI || BROKEN) + depends on NET_RADIO && ISA_DMA_API && CRYPTO && (PCI || BROKEN) ---help--- This is the standard Linux driver to support Cisco/Aironet ISA and PCI 802.11 wireless cards. -- GitLab From 9c07b884b92c80e9d660b7b9282631fb626451e2 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 11 Jan 2006 11:26:25 -0800 Subject: [PATCH 029/465] [PATCH] gfar: fix compile error Missing include of to get definition of IPPROTO_UDP. Signed-off-by: Kumar Gala Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/gianfar.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 146f9513aea..637b73ad5e9 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -84,6 +84,7 @@ #include #include #include +#include #include #include -- GitLab From 1d5326774c9245fef77334a9e0f11cd4f8aa7b4e Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 11 Jan 2006 11:27:32 -0800 Subject: [PATCH 030/465] [PATCH] gianfar mii: Use proper resource for MII memory region We can now have the gianfar mii platform device have a proper resource for the IO memory region for its registers. Previously we passed this information that the platform_data structure because we couldn't handle overlapping memory regions for platform devices. Signed-off-by: Kumar Gala Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/gianfar_mii.c | 5 ++++- include/linux/fsl_devices.h | 3 --- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c index 04a462c2a5b..74e52fcbf80 100644 --- a/drivers/net/gianfar_mii.c +++ b/drivers/net/gianfar_mii.c @@ -128,6 +128,7 @@ int gfar_mdio_probe(struct device *dev) struct gianfar_mdio_data *pdata; struct gfar_mii *regs; struct mii_bus *new_bus; + struct resource *r; int err = 0; if (NULL == dev) @@ -151,8 +152,10 @@ int gfar_mdio_probe(struct device *dev) return -ENODEV; } + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + /* Set the PHY base address */ - regs = (struct gfar_mii *) ioremap(pdata->paddr, + regs = (struct gfar_mii *) ioremap(r->start, sizeof (struct gfar_mii)); if (NULL == regs) { diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h index 934aa9bda48..a7a2b855ba7 100644 --- a/include/linux/fsl_devices.h +++ b/include/linux/fsl_devices.h @@ -55,9 +55,6 @@ struct gianfar_platform_data { }; struct gianfar_mdio_data { - /* device specific information */ - u32 paddr; - /* board specific information */ int irq[32]; }; -- GitLab From a4d00f179fcec7065fe5742e9cebd6500886070f Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 11 Jan 2006 11:27:33 -0800 Subject: [PATCH 031/465] [PATCH] phy: Added a macro to represent the string format used to match a phy device Add the PHY_ID_FMT macro to ensure that the format of the id string used by a driver to match to its specific phy is consistent between the mdio_bus and the driver. Signed-off-by: Kumar Gala Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/phy/mdio_bus.c | 2 +- drivers/net/phy/phy.c | 2 +- include/linux/phy.h | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 02940c0fef6..459443b572c 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -81,7 +81,7 @@ int mdiobus_register(struct mii_bus *bus) phydev->dev.parent = bus->dev; phydev->dev.bus = &mdio_bus_type; - sprintf(phydev->dev.bus_id, "phy%d:%d", bus->id, i); + snprintf(phydev->dev.bus_id, BUS_ID_SIZE, PHY_ID_FMT, bus->id, i); phydev->bus = bus; diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index b8686e47f89..1474b7c5ac0 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -42,7 +42,7 @@ */ void phy_print_status(struct phy_device *phydev) { - pr_info("%s: Link is %s", phydev->dev.bus_id, + pr_info("PHY: %s - Link is %s", phydev->dev.bus_id, phydev->link ? "Up" : "Down"); if (phydev->link) printk(" - %d/%s", phydev->speed, diff --git a/include/linux/phy.h b/include/linux/phy.h index 92a9696fdeb..331521a10a2 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -53,6 +53,9 @@ #define PHY_MAX_ADDR 32 +/* Used when trying to connect to a specific phy (mii bus id:phy device id) */ +#define PHY_ID_FMT "%x:%02x" + /* The Bus class for PHYs. Devices which provide access to * PHYs should register using this structure */ struct mii_bus { -- GitLab From 4d3248a29cb78b31bb0520eb99b4be620e810a40 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 11 Jan 2006 11:27:33 -0800 Subject: [PATCH 032/465] [PATCH] gianfar: Use new PHY_ID_FMT macro Make the driver produce the string used by phy_connect and have board specific code pass the integer mii bus id and phy device id for the specific controller instance. Signed-off-by: Kumar Gala Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/gianfar.c | 5 ++++- include/linux/fsl_devices.h | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 637b73ad5e9..0c18dbd67d3 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -399,12 +399,15 @@ static int init_phy(struct net_device *dev) priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ? SUPPORTED_1000baseT_Full : 0; struct phy_device *phydev; + char phy_id[BUS_ID_SIZE]; priv->oldlink = 0; priv->oldspeed = 0; priv->oldduplex = -1; - phydev = phy_connect(dev, priv->einfo->bus_id, &adjust_link, 0); + snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, priv->einfo->bus_id, priv->einfo->phy_id); + + phydev = phy_connect(dev, phy_id, &adjust_link, 0); if (IS_ERR(phydev)) { printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h index a7a2b855ba7..a9f1cfd096f 100644 --- a/include/linux/fsl_devices.h +++ b/include/linux/fsl_devices.h @@ -50,7 +50,8 @@ struct gianfar_platform_data { /* board specific information */ u32 board_flags; - const char *bus_id; + u32 bus_id; + u32 phy_id; u8 mac_addr[6]; }; -- GitLab From c213460fd4781c04832c81416532d64ae2bfa88b Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn / snakebyte Date: Tue, 10 Jan 2006 13:16:03 +0100 Subject: [PATCH 033/465] [PATCH] replace MODULE_PARM in tulip/uli526x.c Replace the MODULE_PARM usage in uli526x.c with module_param. Signed-off-by: Eric Sesterhenn Signed-off-by: Jeff Garzik --- drivers/net/tulip/uli526x.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c index 1a431633625..98398166680 100644 --- a/drivers/net/tulip/uli526x.c +++ b/drivers/net/tulip/uli526x.c @@ -1689,9 +1689,9 @@ MODULE_AUTHOR("Peer Chen, peer.chen@uli.com.tw"); MODULE_DESCRIPTION("ULi M5261/M5263 fast ethernet driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(debug, "i"); -MODULE_PARM(mode, "i"); -MODULE_PARM(cr6set, "i"); +module_param(debug, int, 0644); +module_param(mode, int, 0); +module_param(cr6set, int, 0); MODULE_PARM_DESC(debug, "ULi M5261/M5263 enable debugging (0-1)"); MODULE_PARM_DESC(mode, "ULi M5261/M5263: Bit 0: 10/100Mbps, bit 2: duplex, bit 8: HomePNA"); -- GitLab From 9a6301c114aaab1df6de6fad9899bb89852a7592 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 10 Jan 2006 00:56:11 -0500 Subject: [PATCH 034/465] [PATCH] wireless/atmel: add IWENCODEEXT, IWAUTH, and association event support This patch allows the Atmel driver to work correctly with wpa_supplicant and other programs that require some conformance with WEXT-18. It should not affect current behavior of the driver. The patch does four things: 1) Implements SIOCSIWENCODEEXT, SIOCGIWENCODEEXT, SIOCSIWAUTH, and SIOCGIWAUTH calls for unencrypted and WEP operation 2) Accepts zero-filled addresses for SIOCSIWAP, which are legal and should turn off any previous forced WAP address 3) Sends association and de-association events to userspace at most of the appropriate times 4) Fixes erroneous order of CIPHER_SUITE_WEP_* arguments in one location which are actually unused anyway Signed-off-by: Dan Williams Signed-off-by: Jeff Garzik --- drivers/net/wireless/atmel.c | 227 ++++++++++++++++++++++++++++++++++- 1 file changed, 223 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index e4729ddf29f..f0ccfef6644 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c @@ -1407,6 +1407,17 @@ static int atmel_close(struct net_device *dev) { struct atmel_private *priv = netdev_priv(dev); + /* Send event to userspace that we are disassociating */ + if (priv->station_state == STATION_STATE_READY) { + union iwreq_data wrqu; + + wrqu.data.length = 0; + wrqu.data.flags = 0; + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); + wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); + } + atmel_enter_state(priv, STATION_STATE_DOWN); if (priv->bus_type == BUS_TYPE_PCCARD) @@ -1780,10 +1791,10 @@ static int atmel_set_encode(struct net_device *dev, priv->wep_is_on = 1; priv->exclude_unencrypted = 1; if (priv->wep_key_len[index] > 5) { - priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64; + priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128; priv->encryption_level = 2; } else { - priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128; + priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64; priv->encryption_level = 1; } } @@ -1853,6 +1864,181 @@ static int atmel_get_encode(struct net_device *dev, return 0; } +static int atmel_set_encodeext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct atmel_private *priv = netdev_priv(dev); + struct iw_point *encoding = &wrqu->encoding; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + int idx, key_len; + + /* Determine and validate the key index */ + idx = encoding->flags & IW_ENCODE_INDEX; + if (idx) { + if (idx < 1 || idx > WEP_KEYS) + return -EINVAL; + idx--; + } else + idx = priv->default_key; + + if ((encoding->flags & IW_ENCODE_DISABLED) || + ext->alg == IW_ENCODE_ALG_NONE) { + priv->wep_is_on = 0; + priv->encryption_level = 0; + priv->pairwise_cipher_suite = CIPHER_SUITE_NONE; + } + + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + priv->default_key = idx; + + /* Set the requested key */ + switch (ext->alg) { + case IW_ENCODE_ALG_NONE: + break; + case IW_ENCODE_ALG_WEP: + if (ext->key_len > 5) { + priv->wep_key_len[idx] = 13; + priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128; + priv->encryption_level = 2; + } else if (ext->key_len > 0) { + priv->wep_key_len[idx] = 5; + priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64; + priv->encryption_level = 1; + } else { + return -EINVAL; + } + priv->wep_is_on = 1; + memset(priv->wep_keys[idx], 0, 13); + key_len = min ((int)ext->key_len, priv->wep_key_len[idx]); + memcpy(priv->wep_keys[idx], ext->key, key_len); + break; + default: + return -EINVAL; + } + + return -EINPROGRESS; +} + +static int atmel_get_encodeext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct atmel_private *priv = netdev_priv(dev); + struct iw_point *encoding = &wrqu->encoding; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + int idx, max_key_len; + + max_key_len = encoding->length - sizeof(*ext); + if (max_key_len < 0) + return -EINVAL; + + idx = encoding->flags & IW_ENCODE_INDEX; + if (idx) { + if (idx < 1 || idx > WEP_KEYS) + return -EINVAL; + idx--; + } else + idx = priv->default_key; + + encoding->flags = idx + 1; + memset(ext, 0, sizeof(*ext)); + + if (!priv->wep_is_on) { + ext->alg = IW_ENCODE_ALG_NONE; + ext->key_len = 0; + encoding->flags |= IW_ENCODE_DISABLED; + } else { + if (priv->encryption_level > 0) + ext->alg = IW_ENCODE_ALG_WEP; + else + return -EINVAL; + + ext->key_len = priv->wep_key_len[idx]; + memcpy(ext->key, priv->wep_keys[idx], ext->key_len); + encoding->flags |= IW_ENCODE_ENABLED; + } + + return 0; +} + +static int atmel_set_auth(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct atmel_private *priv = netdev_priv(dev); + struct iw_param *param = &wrqu->param; + + switch (param->flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: + case IW_AUTH_CIPHER_PAIRWISE: + case IW_AUTH_CIPHER_GROUP: + case IW_AUTH_KEY_MGMT: + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + case IW_AUTH_PRIVACY_INVOKED: + /* + * atmel does not use these parameters + */ + break; + + case IW_AUTH_DROP_UNENCRYPTED: + priv->exclude_unencrypted = param->value ? 1 : 0; + break; + + case IW_AUTH_80211_AUTH_ALG: { + if (param->value & IW_AUTH_ALG_SHARED_KEY) { + priv->exclude_unencrypted = 1; + } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) { + priv->exclude_unencrypted = 0; + } else + return -EINVAL; + break; + } + + case IW_AUTH_WPA_ENABLED: + /* Silently accept disable of WPA */ + if (param->value > 0) + return -EOPNOTSUPP; + break; + + default: + return -EOPNOTSUPP; + } + return -EINPROGRESS; +} + +static int atmel_get_auth(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct atmel_private *priv = netdev_priv(dev); + struct iw_param *param = &wrqu->param; + + switch (param->flags & IW_AUTH_INDEX) { + case IW_AUTH_DROP_UNENCRYPTED: + param->value = priv->exclude_unencrypted; + break; + + case IW_AUTH_80211_AUTH_ALG: + if (priv->exclude_unencrypted == 1) + param->value = IW_AUTH_ALG_SHARED_KEY; + else + param->value = IW_AUTH_ALG_OPEN_SYSTEM; + break; + + case IW_AUTH_WPA_ENABLED: + param->value = 0; + break; + + default: + return -EOPNOTSUPP; + } + return 0; +} + + static int atmel_get_name(struct net_device *dev, struct iw_request_info *info, char *cwrq, @@ -2289,13 +2475,15 @@ static int atmel_set_wap(struct net_device *dev, { struct atmel_private *priv = netdev_priv(dev); int i; - static const u8 bcast[] = { 255, 255, 255, 255, 255, 255 }; + static const u8 any[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + static const u8 off[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; unsigned long flags; if (awrq->sa_family != ARPHRD_ETHER) return -EINVAL; - if (memcmp(bcast, awrq->sa_data, 6) == 0) { + if (!memcmp(any, awrq->sa_data, 6) || + !memcmp(off, awrq->sa_data, 6)) { del_timer_sync(&priv->management_timer); spin_lock_irqsave(&priv->irqlock, flags); atmel_scan(priv, 1); @@ -2378,6 +2566,15 @@ static const iw_handler atmel_handler[] = (iw_handler) atmel_get_encode, /* SIOCGIWENCODE */ (iw_handler) atmel_set_power, /* SIOCSIWPOWER */ (iw_handler) atmel_get_power, /* SIOCGIWPOWER */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* SIOCSIWGENIE */ + (iw_handler) NULL, /* SIOCGIWGENIE */ + (iw_handler) atmel_set_auth, /* SIOCSIWAUTH */ + (iw_handler) atmel_get_auth, /* SIOCGIWAUTH */ + (iw_handler) atmel_set_encodeext, /* SIOCSIWENCODEEXT */ + (iw_handler) atmel_get_encodeext, /* SIOCGIWENCODEEXT */ + (iw_handler) NULL, /* SIOCSIWPMKSA */ }; static const iw_handler atmel_private_handler[] = @@ -2924,6 +3121,8 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype) u16 ass_id = le16_to_cpu(ass_resp->ass_id); u16 rates_len = ass_resp->length > 4 ? 4 : ass_resp->length; + union iwreq_data wrqu; + if (frame_len < 8 + rates_len) return; @@ -2954,6 +3153,14 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype) priv->station_is_associated = 1; priv->station_was_associated = 1; atmel_enter_state(priv, STATION_STATE_READY); + + /* Send association event to userspace */ + wrqu.data.length = 0; + wrqu.data.flags = 0; + memcpy(wrqu.ap_addr.sa_data, priv->CurrentBSSID, ETH_ALEN); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); + return; } @@ -3632,6 +3839,7 @@ static int reset_atmel_card(struct net_device *dev) struct atmel_private *priv = netdev_priv(dev); u8 configuration; + int old_state = priv->station_state; /* data to add to the firmware names, in priority order this implemenents firmware versioning */ @@ -3792,6 +4000,17 @@ static int reset_atmel_card(struct net_device *dev) else build_wep_mib(priv); + if (old_state == STATION_STATE_READY) + { + union iwreq_data wrqu; + + wrqu.data.length = 0; + wrqu.data.flags = 0; + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); + wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); + } + return 1; } -- GitLab From 5af47b2ff124fdad9ba84baeb9f7eeebeb227b43 Mon Sep 17 00:00:00 2001 From: Jay Vosburgh Date: Mon, 9 Jan 2006 12:14:00 -0800 Subject: [PATCH 035/465] [PATCH] bonding: UPDATED hash-table corruption in bond_alb.c I believe I see the race Michael refers to (tlb_choose_channel may set head, which tlb_init_slave clears), although I was not able to reproduce it. I have updated his patch for the current netdev-2.6.git tree and added a version update. His original comment follows: Our systems have been crashing during testing of PCI HotPlug support in the various networking components. We've faulted in the bonding driver due to a bug in bond_alb.c:tlb_clear_slave() In that routine, the last modification to the TLB hash table is made without protection of the lock, allowing a race that can lead tlb_choose_channel() to select an invalid table element. -J Signed-off-by: Jeff Garzik --- drivers/net/bonding/bond_alb.c | 4 ++-- drivers/net/bonding/bonding.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 854ddfb90da..f2a63186ae0 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -169,9 +169,9 @@ static void tlb_clear_slave(struct bonding *bond, struct slave *slave, int save_ index = next_index; } - _unlock_tx_hashtbl(bond); - tlb_init_slave(slave); + + _unlock_tx_hashtbl(bond); } /* Must be called before starting the monitor timer */ diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index f20bb85c1ea..3dd78d048c3 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -22,8 +22,8 @@ #include "bond_3ad.h" #include "bond_alb.h" -#define DRV_VERSION "3.0.0" -#define DRV_RELDATE "November 8, 2005" +#define DRV_VERSION "3.0.1" +#define DRV_RELDATE "January 9, 2006" #define DRV_NAME "bonding" #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" -- GitLab From c9fa7d5d6cec7a45f9dc6c2f23500af50d5617c9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 27 Dec 2005 02:14:13 +0100 Subject: [PATCH 036/465] [PATCH] fix wrong comments in ieee80211.h The comments in ieee80211.h claim that one doesn't need to set the len parameter of the stats struct. But if one doesn't, the management frames are read far over the memory they actually occupy causing badness. Signed-Off-By: Johannes Berg Signed-off-by: Jeff Garzik --- include/net/ieee80211.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h index cde2f4f4f50..df05f468fa5 100644 --- a/include/net/ieee80211.h +++ b/include/net/ieee80211.h @@ -363,8 +363,9 @@ enum ieee80211_reasoncode { #define IEEE80211_OFDM_SHIFT_MASK_A 4 /* NOTE: This data is for statistical purposes; not all hardware provides this - * information for frames received. Not setting these will not cause - * any adverse affects. */ + * information for frames received. + * For ieee80211_rx_mgt, you need to set at least the 'len' parameter. + */ struct ieee80211_rx_stats { u32 mac_time; s8 rssi; @@ -1088,6 +1089,7 @@ extern int ieee80211_tx_frame(struct ieee80211_device *ieee, /* ieee80211_rx.c */ extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_rx_stats *rx_stats); +/* make sure to set stats->len */ extern void ieee80211_rx_mgt(struct ieee80211_device *ieee, struct ieee80211_hdr_4addr *header, struct ieee80211_rx_stats *stats); -- GitLab From 9f3f46b5fe83a56d380d4006dd2cd906bc186f91 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 9 Dec 2005 10:36:09 -0500 Subject: [PATCH 037/465] [PATCH] via-velocity: use NETIF_F_IP_CSUM (hardware only support IPv4) At least some versions of the via-velocity hardware only support checksumming IPv4 frames in hardware. However, the driver is currently setting the NETIF_F_HW_CSUM flag, which indicates support for more than just IPv4. This results in errors when trying to use IPv6 over via-velocity hardware. Signed-off-by: John W. Linville Signed-off-by: Jeff Garzik --- drivers/net/via-velocity.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 82c6b757d30..c2d5907dc8e 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -791,7 +791,7 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi #endif if (vptr->flags & VELOCITY_FLAGS_TX_CSUM) { - dev->features |= NETIF_F_HW_CSUM; + dev->features |= NETIF_F_IP_CSUM; } ret = register_netdev(dev); -- GitLab From b97bf3fd8f6a16966d4f18983b2c40993ff937d4 Mon Sep 17 00:00:00 2001 From: Per Liden Date: Mon, 2 Jan 2006 19:04:38 +0100 Subject: [PATCH 038/465] [TIPC] Initial merge TIPC (Transparent Inter Process Communication) is a protocol designed for intra cluster communication. For more information see http://tipc.sourceforge.net Signed-off-by: Per Liden --- include/linux/socket.h | 3 + include/linux/tipc.h | 598 ++++++ include/net/tipc/tipc.h | 255 +++ include/net/tipc/tipc_bearer.h | 92 + include/net/tipc/tipc_msg.h | 220 +++ include/net/tipc/tipc_port.h | 105 ++ net/Kconfig | 1 + net/Makefile | 1 + net/tipc/Kconfig | 112 ++ net/tipc/Makefile | 13 + net/tipc/addr.c | 91 + net/tipc/addr.h | 125 ++ net/tipc/bcast.c | 803 ++++++++ net/tipc/bcast.h | 220 +++ net/tipc/bearer.c | 689 +++++++ net/tipc/bearer.h | 169 ++ net/tipc/cluster.c | 573 ++++++ net/tipc/cluster.h | 89 + net/tipc/config.c | 715 ++++++++ net/tipc/config.h | 76 + net/tipc/core.c | 282 +++ net/tipc/core.h | 313 ++++ net/tipc/dbg.c | 392 ++++ net/tipc/dbg.h | 56 + net/tipc/discover.c | 339 ++++ net/tipc/discover.h | 55 + net/tipc/eth_media.c | 296 +++ net/tipc/handler.c | 129 ++ net/tipc/link.c | 3164 ++++++++++++++++++++++++++++++++ net/tipc/link.h | 293 +++ net/tipc/msg.c | 331 ++++ net/tipc/msg.h | 815 ++++++++ net/tipc/name_distr.c | 306 +++ net/tipc/name_distr.h | 45 + net/tipc/name_table.c | 1076 +++++++++++ net/tipc/name_table.h | 105 ++ net/tipc/net.c | 308 ++++ net/tipc/net.h | 63 + net/tipc/netlink.c | 107 ++ net/tipc/node.c | 676 +++++++ net/tipc/node.h | 141 ++ net/tipc/node_subscr.c | 76 + net/tipc/node_subscr.h | 60 + net/tipc/port.c | 1704 +++++++++++++++++ net/tipc/port.h | 206 +++ net/tipc/ref.c | 186 ++ net/tipc/ref.h | 128 ++ net/tipc/socket.c | 1722 +++++++++++++++++ net/tipc/subscr.c | 522 ++++++ net/tipc/subscr.h | 77 + net/tipc/user_reg.c | 262 +++ net/tipc/user_reg.h | 45 + net/tipc/zone.c | 166 ++ net/tipc/zone.h | 68 + 54 files changed, 19464 insertions(+) create mode 100644 include/linux/tipc.h create mode 100644 include/net/tipc/tipc.h create mode 100644 include/net/tipc/tipc_bearer.h create mode 100644 include/net/tipc/tipc_msg.h create mode 100644 include/net/tipc/tipc_port.h create mode 100644 net/tipc/Kconfig create mode 100644 net/tipc/Makefile create mode 100644 net/tipc/addr.c create mode 100644 net/tipc/addr.h create mode 100644 net/tipc/bcast.c create mode 100644 net/tipc/bcast.h create mode 100644 net/tipc/bearer.c create mode 100644 net/tipc/bearer.h create mode 100644 net/tipc/cluster.c create mode 100644 net/tipc/cluster.h create mode 100644 net/tipc/config.c create mode 100644 net/tipc/config.h create mode 100644 net/tipc/core.c create mode 100644 net/tipc/core.h create mode 100644 net/tipc/dbg.c create mode 100644 net/tipc/dbg.h create mode 100644 net/tipc/discover.c create mode 100644 net/tipc/discover.h create mode 100644 net/tipc/eth_media.c create mode 100644 net/tipc/handler.c create mode 100644 net/tipc/link.c create mode 100644 net/tipc/link.h create mode 100644 net/tipc/msg.c create mode 100644 net/tipc/msg.h create mode 100644 net/tipc/name_distr.c create mode 100644 net/tipc/name_distr.h create mode 100644 net/tipc/name_table.c create mode 100644 net/tipc/name_table.h create mode 100644 net/tipc/net.c create mode 100644 net/tipc/net.h create mode 100644 net/tipc/netlink.c create mode 100644 net/tipc/node.c create mode 100644 net/tipc/node.h create mode 100644 net/tipc/node_subscr.c create mode 100644 net/tipc/node_subscr.h create mode 100644 net/tipc/port.c create mode 100644 net/tipc/port.h create mode 100644 net/tipc/ref.c create mode 100644 net/tipc/ref.h create mode 100644 net/tipc/socket.c create mode 100644 net/tipc/subscr.c create mode 100644 net/tipc/subscr.h create mode 100644 net/tipc/user_reg.c create mode 100644 net/tipc/user_reg.h create mode 100644 net/tipc/zone.c create mode 100644 net/tipc/zone.h diff --git a/include/linux/socket.h b/include/linux/socket.h index 9f4019156fd..b02dda4ee83 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -186,6 +186,7 @@ struct ucred { #define AF_PPPOX 24 /* PPPoX sockets */ #define AF_WANPIPE 25 /* Wanpipe API Sockets */ #define AF_LLC 26 /* Linux LLC */ +#define AF_TIPC 30 /* TIPC sockets */ #define AF_BLUETOOTH 31 /* Bluetooth sockets */ #define AF_MAX 32 /* For now.. */ @@ -218,6 +219,7 @@ struct ucred { #define PF_PPPOX AF_PPPOX #define PF_WANPIPE AF_WANPIPE #define PF_LLC AF_LLC +#define PF_TIPC AF_TIPC #define PF_BLUETOOTH AF_BLUETOOTH #define PF_MAX AF_MAX @@ -279,6 +281,7 @@ struct ucred { #define SOL_LLC 268 #define SOL_DCCP 269 #define SOL_NETLINK 270 +#define SOL_TIPC 271 /* IPX options */ #define IPX_TYPE 1 diff --git a/include/linux/tipc.h b/include/linux/tipc.h new file mode 100644 index 00000000000..ca754f3317f --- /dev/null +++ b/include/linux/tipc.h @@ -0,0 +1,598 @@ +/* + * include/linux/tipc.h: Include file for TIPC users + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUX_TIPC_H_ +#define _LINUX_TIPC_H_ + +#include +#include +#include + +/* + * TIPC addressing primitives + */ + +struct tipc_portid { + __u32 ref; + __u32 node; +}; + +struct tipc_name { + __u32 type; + __u32 instance; +}; + +struct tipc_name_seq { + __u32 type; + __u32 lower; + __u32 upper; +}; + +static inline __u32 tipc_addr(unsigned int zone, + unsigned int cluster, + unsigned int node) +{ + return(zone << 24) | (cluster << 12) | node; +} + +static inline unsigned int tipc_zone(__u32 addr) +{ + return addr >> 24; +} + +static inline unsigned int tipc_cluster(__u32 addr) +{ + return(addr >> 12) & 0xfff; +} + +static inline unsigned int tipc_node(__u32 addr) +{ + return addr & 0xfff; +} + +/* + * Application-accessible port name types + */ + +#define TIPC_NET_EVENTS 0 /* network event subscription name type */ +#define TIPC_TOP_SRV 1 /* topology service name type */ +#define TIPC_RESERVED_TYPES 64 /* lowest user-publishable name type */ + +/* + * Publication scopes when binding port names and port name sequences + */ + +#define TIPC_ZONE_SCOPE 1 +#define TIPC_CLUSTER_SCOPE 2 +#define TIPC_NODE_SCOPE 3 + +/* + * Limiting values for messages + */ + +#define TIPC_MAX_USER_MSG_SIZE 66000 + +/* + * Message importance levels + */ + +#define TIPC_LOW_IMPORTANCE 0 /* default */ +#define TIPC_MEDIUM_IMPORTANCE 1 +#define TIPC_HIGH_IMPORTANCE 2 +#define TIPC_CRITICAL_IMPORTANCE 3 + +/* + * Msg rejection/connection shutdown reasons + */ + +#define TIPC_OK 0 +#define TIPC_ERR_NO_NAME 1 +#define TIPC_ERR_NO_PORT 2 +#define TIPC_ERR_NO_NODE 3 +#define TIPC_ERR_OVERLOAD 4 +#define TIPC_CONN_SHUTDOWN 5 + +/* + * TIPC topology subscription service definitions + */ + +#define TIPC_SUB_PORTS 0x01 /* filter for port availability */ +#define TIPC_SUB_SERVICE 0x02 /* filter for service availability */ +#if 0 +/* The following filter options are not currently implemented */ +#define TIPC_SUB_NO_BIND_EVTS 0x04 /* filter out "publish" events */ +#define TIPC_SUB_NO_UNBIND_EVTS 0x08 /* filter out "withdraw" events */ +#define TIPC_SUB_SINGLE_EVT 0x10 /* expire after first event */ +#endif + +#define TIPC_WAIT_FOREVER ~0 /* timeout for permanent subscription */ + +struct tipc_subscr { + struct tipc_name_seq seq; /* name sequence of interest */ + __u32 timeout; /* subscription duration (in ms) */ + __u32 filter; /* bitmask of filter options */ + char usr_handle[8]; /* available for subscriber use */ +}; + + +#define TIPC_PUBLISHED 1 /* publication event */ +#define TIPC_WITHDRAWN 2 /* withdraw event */ +#define TIPC_SUBSCR_TIMEOUT 3 /* subscription timeout event */ + +struct tipc_event { + __u32 event; /* event type */ + __u32 found_lower; /* matching name seq instances */ + __u32 found_upper; /* " " " " */ + struct tipc_portid port; /* associated port */ + struct tipc_subscr s; /* associated subscription */ +}; + +/* + * Socket API + */ + +#ifndef AF_TIPC +#define AF_TIPC 30 +#endif + +#ifndef PF_TIPC +#define PF_TIPC AF_TIPC +#endif + +#ifndef SOL_TIPC +#define SOL_TIPC 271 +#endif + +#define TIPC_ADDR_NAMESEQ 1 +#define TIPC_ADDR_MCAST 1 +#define TIPC_ADDR_NAME 2 +#define TIPC_ADDR_ID 3 + +struct sockaddr_tipc { + unsigned short family; + unsigned char addrtype; + signed char scope; + union { + struct tipc_portid id; + struct tipc_name_seq nameseq; + struct { + struct tipc_name name; + __u32 domain; /* 0: own zone */ + } name; + } addr; +}; + +/* + * Ancillary data objects supported by recvmsg() + */ + +#define TIPC_ERRINFO 1 /* error info */ +#define TIPC_RETDATA 2 /* returned data */ +#define TIPC_DESTNAME 3 /* destination name */ + +/* + * TIPC-specific socket option values + */ + +#define TIPC_IMPORTANCE 127 /* Default: TIPC_LOW_IMPORTANCE */ +#define TIPC_SRC_DROPPABLE 128 /* Default: 0 (resend congested msg) */ +#define TIPC_DEST_DROPPABLE 129 /* Default: based on socket type */ +#define TIPC_CONN_TIMEOUT 130 /* Default: 8000 (ms) */ + +/* + * Bearer + */ + +/* Identifiers of supported TIPC media types */ + +#define TIPC_MEDIA_TYPE_ETH 1 + +/* Maximum sizes of TIPC bearer-related names (including terminating NUL) */ + +#define TIPC_MAX_MEDIA_NAME 16 /* format = media */ +#define TIPC_MAX_IF_NAME 16 /* format = interface */ +#define TIPC_MAX_BEARER_NAME 32 /* format = media:interface */ +#define TIPC_MAX_LINK_NAME 60 /* format = Z.C.N:interface-Z.C.N:interface */ + +struct tipc_media_addr { + __u32 type; + union { + __u8 eth_addr[6]; /* Ethernet bearer */ +#if 0 + /* Prototypes for other possible bearer types */ + + struct { + __u16 sin_family; + __u16 sin_port; + struct { + __u32 s_addr; + } sin_addr; + char pad[4]; + } addr_in; /* IP-based bearer */ + __u16 sock_descr; /* generic socket bearer */ +#endif + } dev_addr; +}; + + +/* Link priority limits (range from 0 to # priorities - 1) */ + +#define TIPC_NUM_LINK_PRI 32 + +/* Link tolerance limits (min, default, max), in ms */ + +#define TIPC_MIN_LINK_TOL 50 +#define TIPC_DEF_LINK_TOL 1500 +#define TIPC_MAX_LINK_TOL 30000 + +/* Link window limits (min, default, max), in packets */ + +#define TIPC_MIN_LINK_WIN 16 +#define TIPC_DEF_LINK_WIN 50 +#define TIPC_MAX_LINK_WIN 150 + +/* + * Configuration + * + * All configuration management messaging involves sending a request message + * to the TIPC configuration service on a node, which sends a reply message + * back. (In the future multi-message replies may be supported.) + * + * Both request and reply messages consist of a transport header and payload. + * The transport header contains info about the desired operation; + * the payload consists of zero or more type/length/value (TLV) items + * which specify parameters or results for the operation. + * + * For many operations, the request and reply messages have a fixed number + * of TLVs (usually zero or one); however, some reply messages may return + * a variable number of TLVs. A failed request is denoted by the presence + * of an "error string" TLV in the reply message instead of the TLV(s) the + * reply should contain if the request succeeds. + */ + +#define TIPC_CFG_SRV 0 /* configuration service name type */ + +/* + * Public commands: + * May be issued by any process. + * Accepted by own node, or by remote node only if remote management enabled. + */ + +#define TIPC_CMD_NOOP 0x0000 /* tx none, rx none */ +#define TIPC_CMD_GET_NODES 0x0001 /* tx net_addr, rx node_info(s) */ +#define TIPC_CMD_GET_MEDIA_NAMES 0x0002 /* tx none, rx media_name(s) */ +#define TIPC_CMD_GET_BEARER_NAMES 0x0003 /* tx none, rx bearer_name(s) */ +#define TIPC_CMD_GET_LINKS 0x0004 /* tx net_addr, rx link_info(s) */ +#define TIPC_CMD_SHOW_NAME_TABLE 0x0005 /* tx name_tbl_query, rx ultra_string */ +#define TIPC_CMD_SHOW_PORTS 0x0006 /* tx none, rx ultra_string */ +#define TIPC_CMD_SHOW_LINK_STATS 0x000B /* tx link_name, rx ultra_string */ + +#if 0 +#define TIPC_CMD_SHOW_PORT_STATS 0x0008 /* tx port_ref, rx ultra_string */ +#define TIPC_CMD_RESET_PORT_STATS 0x0009 /* tx port_ref, rx none */ +#define TIPC_CMD_GET_ROUTES 0x000A /* tx ?, rx ? */ +#define TIPC_CMD_GET_LINK_PEER 0x000D /* tx link_name, rx ? */ +#endif + +/* + * Protected commands: + * May only be issued by "network administration capable" process. + * Accepted by own node, or by remote node only if remote management enabled + * and this node is zone manager. + */ + +#define TIPC_CMD_GET_REMOTE_MNG 0x4003 /* tx none, rx unsigned */ +#define TIPC_CMD_GET_MAX_PORTS 0x4004 /* tx none, rx unsigned */ +#define TIPC_CMD_GET_MAX_PUBL 0x4005 /* tx none, rx unsigned */ +#define TIPC_CMD_GET_MAX_SUBSCR 0x4006 /* tx none, rx unsigned */ +#define TIPC_CMD_GET_MAX_ZONES 0x4007 /* tx none, rx unsigned */ +#define TIPC_CMD_GET_MAX_CLUSTERS 0x4008 /* tx none, rx unsigned */ +#define TIPC_CMD_GET_MAX_NODES 0x4009 /* tx none, rx unsigned */ +#define TIPC_CMD_GET_MAX_SLAVES 0x400A /* tx none, rx unsigned */ +#define TIPC_CMD_GET_NETID 0x400B /* tx none, rx unsigned */ + +#define TIPC_CMD_ENABLE_BEARER 0x4101 /* tx bearer_config, rx none */ +#define TIPC_CMD_DISABLE_BEARER 0x4102 /* tx bearer_name, rx none */ +#define TIPC_CMD_SET_LINK_TOL 0x4107 /* tx link_config, rx none */ +#define TIPC_CMD_SET_LINK_PRI 0x4108 /* tx link_config, rx none */ +#define TIPC_CMD_SET_LINK_WINDOW 0x4109 /* tx link_config, rx none */ +#define TIPC_CMD_SET_LOG_SIZE 0x410A /* tx unsigned, rx none */ +#define TIPC_CMD_DUMP_LOG 0x410B /* tx none, rx ultra_string */ +#define TIPC_CMD_RESET_LINK_STATS 0x410C /* tx link_name, rx none */ + +#if 0 +#define TIPC_CMD_CREATE_LINK 0x4103 /* tx link_create, rx none */ +#define TIPC_CMD_REMOVE_LINK 0x4104 /* tx link_name, rx none */ +#define TIPC_CMD_BLOCK_LINK 0x4105 /* tx link_name, rx none */ +#define TIPC_CMD_UNBLOCK_LINK 0x4106 /* tx link_name, rx none */ +#endif + +/* + * Private commands: + * May only be issued by "network administration capable" process. + * Accepted by own node only; cannot be used on a remote node. + */ + +#define TIPC_CMD_SET_NODE_ADDR 0x8001 /* tx net_addr, rx none */ +#if 0 +#define TIPC_CMD_SET_ZONE_MASTER 0x8002 /* tx none, rx none */ +#endif +#define TIPC_CMD_SET_REMOTE_MNG 0x8003 /* tx unsigned, rx none */ +#define TIPC_CMD_SET_MAX_PORTS 0x8004 /* tx unsigned, rx none */ +#define TIPC_CMD_SET_MAX_PUBL 0x8005 /* tx unsigned, rx none */ +#define TIPC_CMD_SET_MAX_SUBSCR 0x8006 /* tx unsigned, rx none */ +#define TIPC_CMD_SET_MAX_ZONES 0x8007 /* tx unsigned, rx none */ +#define TIPC_CMD_SET_MAX_CLUSTERS 0x8008 /* tx unsigned, rx none */ +#define TIPC_CMD_SET_MAX_NODES 0x8009 /* tx unsigned, rx none */ +#define TIPC_CMD_SET_MAX_SLAVES 0x800A /* tx unsigned, rx none */ +#define TIPC_CMD_SET_NETID 0x800B /* tx unsigned, rx none */ + +/* + * TLV types defined for TIPC + */ + +#define TIPC_TLV_NONE 0 /* no TLV present */ +#define TIPC_TLV_VOID 1 /* empty TLV (0 data bytes)*/ +#define TIPC_TLV_UNSIGNED 2 /* 32-bit integer */ +#define TIPC_TLV_STRING 3 /* char[128] (max) */ +#define TIPC_TLV_LARGE_STRING 4 /* char[2048] (max) */ +#define TIPC_TLV_ULTRA_STRING 5 /* char[32768] (max) */ + +#define TIPC_TLV_ERROR_STRING 16 /* char[128] containing "error code" */ +#define TIPC_TLV_NET_ADDR 17 /* 32-bit integer denoting */ +#define TIPC_TLV_MEDIA_NAME 18 /* char[MAX_MEDIA_NAME] */ +#define TIPC_TLV_BEARER_NAME 19 /* char[MAX_BEARER_NAME] */ +#define TIPC_TLV_LINK_NAME 20 /* char[MAX_LINK_NAME] */ +#define TIPC_TLV_NODE_INFO 21 /* struct tipc_node_info */ +#define TIPC_TLV_LINK_INFO 22 /* struct tipc_link_info */ +#define TIPC_TLV_BEARER_CONFIG 23 /* struct tipc_bearer_config */ +#define TIPC_TLV_LINK_CONFIG 24 /* struct tipc_link_config */ +#define TIPC_TLV_NAME_TBL_QUERY 25 /* struct tipc_name_table_query */ +#define TIPC_TLV_PORT_REF 26 /* 32-bit port reference */ + +struct tipc_node_info { + __u32 addr; /* network address of node */ + __u32 up; /* 0=down, 1= up */ +}; + +struct tipc_link_info { + __u32 dest; /* network address of peer node */ + __u32 up; /* 0=down, 1=up */ + char str[TIPC_MAX_LINK_NAME]; /* link name */ +}; + +struct tipc_bearer_config { + __u32 priority; /* Range [1,31]. Override per link */ + __u32 detect_scope; + char name[TIPC_MAX_BEARER_NAME]; +}; + +struct tipc_link_config { + __u32 value; + char name[TIPC_MAX_LINK_NAME]; +}; + +#define TIPC_NTQ_ALLTYPES 0x80000000 + +struct tipc_name_table_query { + __u32 depth; /* 1:type, 2:+name info, 3:+port info, 4+:+debug info */ + __u32 type; /* {t,l,u} info ignored if high bit of "depth" is set */ + __u32 lowbound; /* (i.e. displays all entries of name table) */ + __u32 upbound; +}; + +/* + * The error string TLV is a null-terminated string describing the cause + * of the request failure. To simplify error processing (and to save space) + * the first character of the string can be a special error code character + * (lying by the range 0x80 to 0xFF) which represents a pre-defined reason. + */ + +#define TIPC_CFG_TLV_ERROR "\x80" /* request contains incorrect TLV(s) */ +#define TIPC_CFG_NOT_NET_ADMIN "\x81" /* must be network administrator */ +#define TIPC_CFG_NOT_ZONE_MSTR "\x82" /* must be zone master */ +#define TIPC_CFG_NO_REMOTE "\x83" /* remote management not enabled */ +#define TIPC_CFG_NOT_SUPPORTED "\x84" /* request is not supported by TIPC */ +#define TIPC_CFG_INVALID_VALUE "\x85" /* request has invalid argument value */ + +#if 0 +/* prototypes TLV structures for proposed commands */ +struct tipc_link_create { + __u32 domain; + struct tipc_media_addr peer_addr; + char bearer_name[MAX_BEARER_NAME]; +}; + +struct tipc_route_info { + __u32 dest; + __u32 router; +}; +#endif + +/* + * A TLV consists of a descriptor, followed by the TLV value. + * TLV descriptor fields are stored in network byte order; + * TLV values must also be stored in network byte order (where applicable). + * TLV descriptors must be aligned to addresses which are multiple of 4, + * so up to 3 bytes of padding may exist at the end of the TLV value area. + * There must not be any padding between the TLV descriptor and its value. + */ + +struct tlv_desc { + __u16 tlv_len; /* TLV length (descriptor + value) */ + __u16 tlv_type; /* TLV identifier */ +}; + +#define TLV_ALIGNTO 4 + +#define TLV_ALIGN(datalen) (((datalen)+(TLV_ALIGNTO-1)) & ~(TLV_ALIGNTO-1)) +#define TLV_LENGTH(datalen) (sizeof(struct tlv_desc) + (datalen)) +#define TLV_SPACE(datalen) (TLV_ALIGN(TLV_LENGTH(datalen))) +#define TLV_DATA(tlv) ((void *)((char *)(tlv) + TLV_LENGTH(0))) + +static inline int TLV_OK(const void *tlv, __u16 space) +{ + /* + * Would also like to check that "tlv" is a multiple of 4, + * but don't know how to do this in a portable way. + * - Tried doing (!(tlv & (TLV_ALIGNTO-1))), but GCC compiler + * won't allow binary "&" with a pointer. + * - Tried casting "tlv" to integer type, but causes warning about size + * mismatch when pointer is bigger than chosen type (int, long, ...). + */ + + return (space >= TLV_SPACE(0)) && + (ntohs(((struct tlv_desc *)tlv)->tlv_len) <= space); +} + +static inline int TLV_CHECK(const void *tlv, __u16 space, __u16 exp_type) +{ + return TLV_OK(tlv, space) && + (ntohs(((struct tlv_desc *)tlv)->tlv_type) == exp_type); +} + +static inline int TLV_SET(void *tlv, __u16 type, void *data, __u16 len) +{ + struct tlv_desc *tlv_ptr; + int tlv_len; + + tlv_len = TLV_LENGTH(len); + tlv_ptr = (struct tlv_desc *)tlv; + tlv_ptr->tlv_type = htons(type); + tlv_ptr->tlv_len = htons(tlv_len); + if (len && data) + memcpy(TLV_DATA(tlv_ptr), data, tlv_len); + return TLV_SPACE(len); +} + +/* + * A TLV list descriptor simplifies processing of messages + * containing multiple TLVs. + */ + +struct tlv_list_desc { + struct tlv_desc *tlv_ptr; /* ptr to current TLV */ + __u32 tlv_space; /* # bytes from curr TLV to list end */ +}; + +static inline void TLV_LIST_INIT(struct tlv_list_desc *list, + void *data, __u32 space) +{ + list->tlv_ptr = (struct tlv_desc *)data; + list->tlv_space = space; +} + +static inline int TLV_LIST_EMPTY(struct tlv_list_desc *list) +{ + return (list->tlv_space == 0); +} + +static inline int TLV_LIST_CHECK(struct tlv_list_desc *list, __u16 exp_type) +{ + return TLV_CHECK(list->tlv_ptr, list->tlv_space, exp_type); +} + +static inline void *TLV_LIST_DATA(struct tlv_list_desc *list) +{ + return TLV_DATA(list->tlv_ptr); +} + +static inline void TLV_LIST_STEP(struct tlv_list_desc *list) +{ + __u16 tlv_space = TLV_ALIGN(ntohs(list->tlv_ptr->tlv_len)); + + list->tlv_ptr = (struct tlv_desc *)((char *)list->tlv_ptr + tlv_space); + list->tlv_space -= tlv_space; +} + +/* + * Configuration messages exchanged via NETLINK_GENERIC use the following + * family id, name, version and command. + */ +#define TIPC_GENL_FAMILY 0x222 +#define TIPC_GENL_NAME "TIPC" +#define TIPC_GENL_VERSION 0x1 +#define TIPC_GENL_CMD 0x1 + +/* + * TIPC specific header used in NETLINK_GENERIC requests. + */ +struct tipc_genlmsghdr { + __u32 dest; /* Destination address */ + __u16 cmd; /* Command */ + __u16 reserved; /* Unused */ +}; + +#define TIPC_GENL_HDRLEN NLMSG_ALIGN(sizeof(struct tipc_genlmsghdr)) + +/* + * Configuration messages exchanged via TIPC sockets use the TIPC configuration + * message header, which is defined below. This structure is analogous + * to the Netlink message header, but fields are stored in network byte order + * and no padding is permitted between the header and the message data + * that follows. + */ + +struct tipc_cfg_msg_hdr +{ + __u32 tcm_len; /* Message length (including header) */ + __u16 tcm_type; /* Command type */ + __u16 tcm_flags; /* Additional flags */ + char tcm_reserved[8]; /* Unused */ +}; + +#define TCM_F_REQUEST 0x1 /* Flag: Request message */ +#define TCM_F_MORE 0x2 /* Flag: Message to be continued */ + +#define TCM_ALIGN(datalen) (((datalen)+3) & ~3) +#define TCM_LENGTH(datalen) (sizeof(struct tipc_cfg_msg_hdr) + datalen) +#define TCM_SPACE(datalen) (TCM_ALIGN(TCM_LENGTH(datalen))) +#define TCM_DATA(tcm_hdr) ((void *)((char *)(tcm_hdr) + TCM_LENGTH(0))) + +static inline int TCM_SET(void *msg, __u16 cmd, __u16 flags, + void *data, __u16 data_len) +{ + struct tipc_cfg_msg_hdr *tcm_hdr; + int msg_len; + + msg_len = TCM_LENGTH(data_len); + tcm_hdr = (struct tipc_cfg_msg_hdr *)msg; + tcm_hdr->tcm_len = htonl(msg_len); + tcm_hdr->tcm_type = htons(cmd); + tcm_hdr->tcm_flags = htons(flags); + if (data_len && data) + memcpy(TCM_DATA(msg), data, data_len); + return TCM_SPACE(data_len); +} + +#endif diff --git a/include/net/tipc/tipc.h b/include/net/tipc/tipc.h new file mode 100644 index 00000000000..1d4d8d0701e --- /dev/null +++ b/include/net/tipc/tipc.h @@ -0,0 +1,255 @@ +/* + * include/net/tipc/tipc.h: Main include file for TIPC users + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _NET_TIPC_H_ +#define _NET_TIPC_H_ + +#ifdef __KERNEL__ + +#include +#include + +/* + * Native API + * ---------- + */ + +/* + * TIPC operating mode routines + */ + +u32 tipc_get_addr(void); + +#define TIPC_NOT_RUNNING 0 +#define TIPC_NODE_MODE 1 +#define TIPC_NET_MODE 2 + +typedef void (*tipc_mode_event)(void *usr_handle, int mode, u32 addr); + +int tipc_attach(unsigned int *userref, tipc_mode_event, void *usr_handle); + +void tipc_detach(unsigned int userref); + +int tipc_get_mode(void); + +/* + * TIPC port manipulation routines + */ + +typedef void (*tipc_msg_err_event) (void *usr_handle, + u32 portref, + struct sk_buff **buf, + unsigned char const *data, + unsigned int size, + int reason, + struct tipc_portid const *attmpt_destid); + +typedef void (*tipc_named_msg_err_event) (void *usr_handle, + u32 portref, + struct sk_buff **buf, + unsigned char const *data, + unsigned int size, + int reason, + struct tipc_name_seq const *attmpt_dest); + +typedef void (*tipc_conn_shutdown_event) (void *usr_handle, + u32 portref, + struct sk_buff **buf, + unsigned char const *data, + unsigned int size, + int reason); + +typedef void (*tipc_msg_event) (void *usr_handle, + u32 portref, + struct sk_buff **buf, + unsigned char const *data, + unsigned int size, + unsigned int importance, + struct tipc_portid const *origin); + +typedef void (*tipc_named_msg_event) (void *usr_handle, + u32 portref, + struct sk_buff **buf, + unsigned char const *data, + unsigned int size, + unsigned int importance, + struct tipc_portid const *orig, + struct tipc_name_seq const *dest); + +typedef void (*tipc_conn_msg_event) (void *usr_handle, + u32 portref, + struct sk_buff **buf, + unsigned char const *data, + unsigned int size); + +typedef void (*tipc_continue_event) (void *usr_handle, + u32 portref); + +int tipc_createport(unsigned int tipc_user, + void *usr_handle, + unsigned int importance, + tipc_msg_err_event error_cb, + tipc_named_msg_err_event named_error_cb, + tipc_conn_shutdown_event conn_error_cb, + tipc_msg_event message_cb, + tipc_named_msg_event named_message_cb, + tipc_conn_msg_event conn_message_cb, + tipc_continue_event continue_event_cb,/* May be zero */ + u32 *portref); + +int tipc_deleteport(u32 portref); + +int tipc_ownidentity(u32 portref, struct tipc_portid *port); + +int tipc_portimportance(u32 portref, unsigned int *importance); +int tipc_set_portimportance(u32 portref, unsigned int importance); + +int tipc_portunreliable(u32 portref, unsigned int *isunreliable); +int tipc_set_portunreliable(u32 portref, unsigned int isunreliable); + +int tipc_portunreturnable(u32 portref, unsigned int *isunreturnable); +int tipc_set_portunreturnable(u32 portref, unsigned int isunreturnable); + +int tipc_publish(u32 portref, unsigned int scope, + struct tipc_name_seq const *name_seq); +int tipc_withdraw(u32 portref, unsigned int scope, + struct tipc_name_seq const *name_seq); /* 0: all */ + +int tipc_connect2port(u32 portref, struct tipc_portid const *port); + +int tipc_disconnect(u32 portref); + +int tipc_shutdown(u32 ref); /* Sends SHUTDOWN msg */ + +int tipc_isconnected(u32 portref, int *isconnected); + +int tipc_peer(u32 portref, struct tipc_portid *peer); + +int tipc_ref_valid(u32 portref); + +/* + * TIPC messaging routines + */ + +#define TIPC_PORT_IMPORTANCE 100 /* send using current port setting */ + + +int tipc_send(u32 portref, + unsigned int num_sect, + struct iovec const *msg_sect); + +int tipc_send_buf(u32 portref, + struct sk_buff *buf, + unsigned int dsz); + +int tipc_send2name(u32 portref, + struct tipc_name const *name, + u32 domain, /* 0:own zone */ + unsigned int num_sect, + struct iovec const *msg_sect); + +int tipc_send_buf2name(u32 portref, + struct tipc_name const *name, + u32 domain, + struct sk_buff *buf, + unsigned int dsz); + +int tipc_forward2name(u32 portref, + struct tipc_name const *name, + u32 domain, /*0: own zone */ + unsigned int section_count, + struct iovec const *msg_sect, + struct tipc_portid const *origin, + unsigned int importance); + +int tipc_forward_buf2name(u32 portref, + struct tipc_name const *name, + u32 domain, + struct sk_buff *buf, + unsigned int dsz, + struct tipc_portid const *orig, + unsigned int importance); + +int tipc_send2port(u32 portref, + struct tipc_portid const *dest, + unsigned int num_sect, + struct iovec const *msg_sect); + +int tipc_send_buf2port(u32 portref, + struct tipc_portid const *dest, + struct sk_buff *buf, + unsigned int dsz); + +int tipc_forward2port(u32 portref, + struct tipc_portid const *dest, + unsigned int num_sect, + struct iovec const *msg_sect, + struct tipc_portid const *origin, + unsigned int importance); + +int tipc_forward_buf2port(u32 portref, + struct tipc_portid const *dest, + struct sk_buff *buf, + unsigned int dsz, + struct tipc_portid const *orig, + unsigned int importance); + +int tipc_multicast(u32 portref, + struct tipc_name_seq const *seq, + u32 domain, /* 0:own zone */ + unsigned int section_count, + struct iovec const *msg); + +#if 0 +int tipc_multicast_buf(u32 portref, + struct tipc_name_seq const *seq, + u32 domain, /* 0:own zone */ + void *buf, + unsigned int size); +#endif + +/* + * TIPC subscription routines + */ + +int tipc_ispublished(struct tipc_name const *name); + +/* + * Get number of available nodes within specified domain (excluding own node) + */ + +unsigned int tipc_available_nodes(const u32 domain); + +#endif + +#endif diff --git a/include/net/tipc/tipc_bearer.h b/include/net/tipc/tipc_bearer.h new file mode 100644 index 00000000000..a3daf697b6b --- /dev/null +++ b/include/net/tipc/tipc_bearer.h @@ -0,0 +1,92 @@ +/* + * include/net/tipc/tipc_bearer.h: Include file for privileged access to TIPC bearers + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _NET_TIPC_BEARER_H_ +#define _NET_TIPC_BEARER_H_ + +#ifdef __KERNEL__ + +#include +#include +#include + +/** + * struct tipc_bearer - TIPC bearer info available to privileged users + * @usr_handle: pointer to additional user-defined information about bearer + * @mtu: max packet size bearer can support + * @blocked: non-zero if bearer is blocked + * @lock: spinlock for controlling access to bearer + * @addr: media-specific address associated with bearer + * @name: bearer name (format = media:interface) + * + * Note: TIPC initializes "name" and "lock" fields; user is responsible for + * initialization all other fields when a bearer is enabled. + */ + +struct tipc_bearer { + void *usr_handle; + u32 mtu; + int blocked; + spinlock_t lock; + struct tipc_media_addr addr; + char name[TIPC_MAX_BEARER_NAME]; +}; + + +int tipc_register_media(u32 media_type, + char *media_name, + int (*enable)(struct tipc_bearer *), + void (*disable)(struct tipc_bearer *), + int (*send_msg)(struct sk_buff *, + struct tipc_bearer *, + struct tipc_media_addr *), + char *(*addr2str)(struct tipc_media_addr *a, + char *str_buf, + int str_size), + struct tipc_media_addr *bcast_addr, + const u32 bearer_priority, + const u32 link_tolerance, /* [ms] */ + const u32 send_window_limit); + +void tipc_recv_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr); + +int tipc_block_bearer(const char *name); +void tipc_continue(struct tipc_bearer *tb_ptr); + +int tipc_enable_bearer(const char *bearer_name, u32 bcast_scope, u32 priority); +int tipc_disable_bearer(const char *name); + + +#endif + +#endif diff --git a/include/net/tipc/tipc_msg.h b/include/net/tipc/tipc_msg.h new file mode 100644 index 00000000000..78513f5236b --- /dev/null +++ b/include/net/tipc/tipc_msg.h @@ -0,0 +1,220 @@ +/* + * include/net/tipc/tipc_msg.h: Include file for privileged access to TIPC message headers + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _NET_TIPC_MSG_H_ +#define _NET_TIPC_MSG_H_ + +#ifdef __KERNEL__ + +struct tipc_msg { + u32 hdr[15]; +}; + + +/* + TIPC user data message header format, version 2: + + + 1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + w0:|vers | user |hdr sz |n|d|s|-| message size | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + w1:|mstyp| error |rer cnt|lsc|opt p| broadcast ack no | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + w2:| link level ack no | broadcast/link level seq no | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + w3:| previous node | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + w4:| originating port | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + w5:| destination port | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + w6:| originating node | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + w7:| destination node | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + w8:| name type / transport sequence number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + w9:| name instance/multicast lower bound | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + wA:| multicast upper bound | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + / / + \ options \ + / / + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +*/ + +#define TIPC_CONN_MSG 0 +#define TIPC_MCAST_MSG 1 +#define TIPC_NAMED_MSG 2 +#define TIPC_DIRECT_MSG 3 + + +static inline u32 msg_word(struct tipc_msg *m, u32 pos) +{ + return ntohl(m->hdr[pos]); +} + +static inline u32 msg_bits(struct tipc_msg *m, u32 w, u32 pos, u32 mask) +{ + return (msg_word(m, w) >> pos) & mask; +} + +static inline u32 msg_importance(struct tipc_msg *m) +{ + return msg_bits(m, 0, 25, 0xf); +} + +static inline u32 msg_hdr_sz(struct tipc_msg *m) +{ + return msg_bits(m, 0, 21, 0xf) << 2; +} + +static inline int msg_short(struct tipc_msg *m) +{ + return (msg_hdr_sz(m) == 24); +} + +static inline u32 msg_size(struct tipc_msg *m) +{ + return msg_bits(m, 0, 0, 0x1ffff); +} + +static inline u32 msg_data_sz(struct tipc_msg *m) +{ + return (msg_size(m) - msg_hdr_sz(m)); +} + +static inline unchar *msg_data(struct tipc_msg *m) +{ + return ((unchar *)m) + msg_hdr_sz(m); +} + +static inline u32 msg_type(struct tipc_msg *m) +{ + return msg_bits(m, 1, 29, 0x7); +} + +static inline u32 msg_direct(struct tipc_msg *m) +{ + return (msg_type(m) == TIPC_DIRECT_MSG); +} + +static inline u32 msg_named(struct tipc_msg *m) +{ + return (msg_type(m) == TIPC_NAMED_MSG); +} + +static inline u32 msg_mcast(struct tipc_msg *m) +{ + return (msg_type(m) == TIPC_MCAST_MSG); +} + +static inline u32 msg_connected(struct tipc_msg *m) +{ + return (msg_type(m) == TIPC_CONN_MSG); +} + +static inline u32 msg_errcode(struct tipc_msg *m) +{ + return msg_bits(m, 1, 25, 0xf); +} + +static inline u32 msg_prevnode(struct tipc_msg *m) +{ + return msg_word(m, 3); +} + +static inline u32 msg_origport(struct tipc_msg *m) +{ + return msg_word(m, 4); +} + +static inline u32 msg_destport(struct tipc_msg *m) +{ + return msg_word(m, 5); +} + +static inline u32 msg_mc_netid(struct tipc_msg *m) +{ + return msg_word(m, 5); +} + +static inline u32 msg_orignode(struct tipc_msg *m) +{ + if (likely(msg_short(m))) + return msg_prevnode(m); + return msg_word(m, 6); +} + +static inline u32 msg_destnode(struct tipc_msg *m) +{ + return msg_word(m, 7); +} + +static inline u32 msg_nametype(struct tipc_msg *m) +{ + return msg_word(m, 8); +} + +static inline u32 msg_nameinst(struct tipc_msg *m) +{ + return msg_word(m, 9); +} + +static inline u32 msg_namelower(struct tipc_msg *m) +{ + return msg_nameinst(m); +} + +static inline u32 msg_nameupper(struct tipc_msg *m) +{ + return msg_word(m, 10); +} + +static inline char *msg_options(struct tipc_msg *m, u32 *len) +{ + u32 pos = msg_bits(m, 1, 16, 0x7); + + if (!pos) + return 0; + pos = (pos * 4) + 28; + *len = msg_hdr_sz(m) - pos; + return (char *)&m->hdr[pos/4]; +} + +#endif + +#endif diff --git a/include/net/tipc/tipc_port.h b/include/net/tipc/tipc_port.h new file mode 100644 index 00000000000..ec0f0de7f0e --- /dev/null +++ b/include/net/tipc/tipc_port.h @@ -0,0 +1,105 @@ +/* + * include/net/tipc/tipc_port.h: Include file for privileged access to TIPC ports + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _NET_TIPC_PORT_H_ +#define _NET_TIPC_PORT_H_ + +#ifdef __KERNEL__ + +#include +#include +#include + +#define TIPC_FLOW_CONTROL_WIN 512 + +/** + * struct tipc_port - native TIPC port info available to privileged users + * @usr_handle: pointer to additional user-defined information about port + * @lock: pointer to spinlock for controlling access to port + * @connected: non-zero if port is currently connected to a peer port + * @conn_type: TIPC type used when connection was established + * @conn_instance: TIPC instance used when connection was established + * @conn_unacked: number of unacknowledged messages received from peer port + * @published: non-zero if port has one or more associated names + * @congested: non-zero if cannot send because of link or port congestion + * @ref: unique reference to port in TIPC object registry + * @phdr: preformatted message header used when sending messages + */ + +struct tipc_port { + void *usr_handle; + spinlock_t *lock; + int connected; + u32 conn_type; + u32 conn_instance; + u32 conn_unacked; + int published; + u32 congested; + u32 ref; + struct tipc_msg phdr; +}; + + +/** + * tipc_createport_raw - create a native TIPC port and return it's reference + * + * Note: 'dispatcher' and 'wakeup' deliver a locked port. + */ + +u32 tipc_createport_raw(void *usr_handle, + u32 (*dispatcher)(struct tipc_port *, struct sk_buff *), + void (*wakeup)(struct tipc_port *), + const u32 importance); + +/* + * tipc_set_msg_option(): port must be locked. + */ +int tipc_set_msg_option(struct tipc_port *tp_ptr, + const char *opt, + const u32 len); + +int tipc_reject_msg(struct sk_buff *buf, u32 err); + +int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode); + +void tipc_acknowledge(u32 port_ref,u32 ack); + +struct tipc_port *tipc_get_port(const u32 ref); + +void *tipc_get_handle(const u32 ref); + + +#endif + +#endif + diff --git a/net/Kconfig b/net/Kconfig index 60f6f321bd7..9296b269d67 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -159,6 +159,7 @@ source "net/ipx/Kconfig" source "drivers/net/appletalk/Kconfig" source "net/x25/Kconfig" source "net/lapb/Kconfig" +source "net/tipc/Kconfig" config NET_DIVERT bool "Frame Diverter (EXPERIMENTAL)" diff --git a/net/Makefile b/net/Makefile index f5141b9d4f3..065796f5fb1 100644 --- a/net/Makefile +++ b/net/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_VLAN_8021Q) += 8021q/ obj-$(CONFIG_IP_DCCP) += dccp/ obj-$(CONFIG_IP_SCTP) += sctp/ obj-$(CONFIG_IEEE80211) += ieee80211/ +obj-$(CONFIG_TIPC) += tipc/ ifeq ($(CONFIG_NET),y) obj-$(CONFIG_SYSCTL) += sysctl_net.o diff --git a/net/tipc/Kconfig b/net/tipc/Kconfig new file mode 100644 index 00000000000..05ab18e62de --- /dev/null +++ b/net/tipc/Kconfig @@ -0,0 +1,112 @@ +# +# TIPC configuration +# + +menu "TIPC Configuration (EXPERIMENTAL)" + depends on INET && EXPERIMENTAL + +config TIPC + tristate "The TIPC Protocol (EXPERIMENTAL)" + ---help--- + TBD. + + This protocol support is also available as a module ( = code which + can be inserted in and removed from the running kernel whenever you + want). The module will be called tipc. If you want to compile it + as a module, say M here and read . + + If in doubt, say N. + +config TIPC_ADVANCED + bool "TIPC: Advanced configuration" + depends on TIPC + default n + help + Saying Y here will open some advanced configuration + for TIPC. Most users do not need to bother, so if + unsure, just say N. + +config TIPC_ZONES + int "Maximum number of zones in network" + depends on TIPC && TIPC_ADVANCED + default "3" + help + Max number of zones inside TIPC network. Max supported value + is 255 zones, minimum is 1 + + Default is 3 zones in a network; setting this to higher + allows more zones but might use more memory. + +config TIPC_CLUSTERS + int "Maximum number of clusters in a zone" + depends on TIPC && TIPC_ADVANCED + default "1" + help + ***Only 1 (one cluster in a zone) is supported by current code. + Any value set here will be overridden.*** + + (Max number of clusters inside TIPC zone. Max supported + value is 4095 clusters, minimum is 1. + + Default is 1; setting this to smaller value might save + some memory, setting it to higher + allows more clusters and might consume more memory.) + +config TIPC_NODES + int "Maximum number of nodes in cluster" + depends on TIPC && TIPC_ADVANCED + default "255" + help + Maximum number of nodes inside a TIPC cluster. Maximum + supported value is 2047 nodes, minimum is 8. + + Setting this to a smaller value saves some memory, + setting it to higher allows more nodes. + +config TIPC_SLAVE_NODES + int "Maximum number of slave nodes in cluster" + depends on TIPC && TIPC_ADVANCED + default "0" + help + ***This capability is not supported by current code.*** + + Maximum number of slave nodes inside a TIPC cluster. Maximum + supported value is 2047 nodes, minimum is 0. + + Setting this to a smaller value saves some memory, + setting it to higher allows more nodes. + +config TIPC_PORTS + int "Maximum number of ports in a node" + depends on TIPC && TIPC_ADVANCED + default "8191" + help + Maximum number of ports within a node. Maximum + supported value is 64535 nodes, minimum is 127. + + Setting this to a smaller value saves some memory, + setting it to higher allows more ports. + +config TIPC_LOG + int "Size of log buffer" + depends on TIPC && TIPC_ADVANCED + default 0 + help + Size (in bytes) of TIPC's internal log buffer, which records the + occurrence of significant events. Maximum supported value + is 32768 bytes, minimum is 0. + + There is no need to enable the log buffer unless the node will be + managed remotely via TIPC. + +config TIPC_DEBUG + bool "Enable debugging support" + depends on TIPC + default n + help + This will enable debugging of TIPC. + + Only say Y here if you are having trouble with TIPC. It will + enable the display of detailed information about what is going on. + +endmenu diff --git a/net/tipc/Makefile b/net/tipc/Makefile new file mode 100644 index 00000000000..dceb7027946 --- /dev/null +++ b/net/tipc/Makefile @@ -0,0 +1,13 @@ +# +# Makefile for the Linux TIPC layer +# + +obj-$(CONFIG_TIPC) := tipc.o + +tipc-y += addr.o bcast.o bearer.o config.o cluster.o \ + core.o handler.o link.o discover.o msg.o \ + name_distr.o subscr.o name_table.o net.o \ + netlink.o node.o node_subscr.o port.o ref.o \ + socket.o user_reg.o zone.o dbg.o eth_media.o + +# End of file diff --git a/net/tipc/addr.c b/net/tipc/addr.c new file mode 100644 index 00000000000..bc353639562 --- /dev/null +++ b/net/tipc/addr.c @@ -0,0 +1,91 @@ +/* + * net/tipc/addr.c: TIPC address utility routines + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2004-2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "core.h" +#include "dbg.h" +#include "addr.h" +#include "zone.h" +#include "cluster.h" +#include "net.h" + +u32 tipc_get_addr(void) +{ + return tipc_own_addr; +} + +/** + * addr_domain_valid - validates a network domain address + * + * Accepts , , , and <0.0.0>, + * where Z, C, and N are non-zero and do not exceed the configured limits. + * + * Returns 1 if domain address is valid, otherwise 0 + */ + +int addr_domain_valid(u32 addr) +{ + u32 n = tipc_node(addr); + u32 c = tipc_cluster(addr); + u32 z = tipc_zone(addr); + u32 max_nodes = tipc_max_nodes; + + if (is_slave(addr)) + max_nodes = LOWEST_SLAVE + tipc_max_slaves; + if (n > max_nodes) + return 0; + if (c > tipc_max_clusters) + return 0; + if (z > tipc_max_zones) + return 0; + + if (n && (!z || !c)) + return 0; + if (c && !z) + return 0; + return 1; +} + +/** + * addr_node_valid - validates a proposed network address for this node + * + * Accepts , where Z, C, and N are non-zero and do not exceed + * the configured limits. + * + * Returns 1 if address can be used, otherwise 0 + */ + +int addr_node_valid(u32 addr) +{ + return (addr_domain_valid(addr) && tipc_node(addr)); +} + diff --git a/net/tipc/addr.h b/net/tipc/addr.h new file mode 100644 index 00000000000..9dabebcba6d --- /dev/null +++ b/net/tipc/addr.h @@ -0,0 +1,125 @@ +/* + * net/tipc/addr.h: Include file for TIPC address utility routines + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2004-2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _TIPC_ADDR_H +#define _TIPC_ADDR_H + +static inline u32 own_node(void) +{ + return tipc_node(tipc_own_addr); +} + +static inline u32 own_cluster(void) +{ + return tipc_cluster(tipc_own_addr); +} + +static inline u32 own_zone(void) +{ + return tipc_zone(tipc_own_addr); +} + +static inline int in_own_cluster(u32 addr) +{ + return !((addr ^ tipc_own_addr) >> 12); +} + +static inline int in_own_zone(u32 addr) +{ + return !((addr ^ tipc_own_addr) >> 24); +} + +static inline int is_slave(u32 addr) +{ + return addr & 0x800; +} + +static inline int may_route(u32 addr) +{ + return(addr ^ tipc_own_addr) >> 11; +} + +static inline int in_scope(u32 domain, u32 addr) +{ + if (!domain || (domain == addr)) + return 1; + if (domain == (addr & 0xfffff000u)) /* domain */ + return 1; + if (domain == (addr & 0xff000000u)) /* domain */ + return 1; + return 0; +} + +/** + * addr_scope - convert message lookup domain to equivalent 2-bit scope value + */ + +static inline int addr_scope(u32 domain) +{ + if (likely(!domain)) + return TIPC_ZONE_SCOPE; + if (tipc_node(domain)) + return TIPC_NODE_SCOPE; + if (tipc_cluster(domain)) + return TIPC_CLUSTER_SCOPE; + return TIPC_ZONE_SCOPE; +} + +/** + * addr_domain - convert 2-bit scope value to equivalent message lookup domain + * + * Needed when address of a named message must be looked up a second time + * after a network hop. + */ + +static inline int addr_domain(int sc) +{ + if (likely(sc == TIPC_NODE_SCOPE)) + return tipc_own_addr; + if (sc == TIPC_CLUSTER_SCOPE) + return tipc_addr(tipc_zone(tipc_own_addr), + tipc_cluster(tipc_own_addr), 0); + return tipc_addr(tipc_zone(tipc_own_addr), 0, 0); +} + +static inline char *addr_string_fill(char *string, u32 addr) +{ + snprintf(string, 16, "<%u.%u.%u>", + tipc_zone(addr), tipc_cluster(addr), tipc_node(addr)); + return string; +} + +int addr_domain_valid(u32); +int addr_node_valid(u32 addr); + +#endif diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c new file mode 100644 index 00000000000..35ca90667a5 --- /dev/null +++ b/net/tipc/bcast.c @@ -0,0 +1,803 @@ +/* + * net/tipc/bcast.c: TIPC broadcast code + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2004, Intel Corporation. + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "core.h" +#include "msg.h" +#include "dbg.h" +#include "link.h" +#include "net.h" +#include "node.h" +#include "port.h" +#include "addr.h" +#include "node_subscr.h" +#include "name_distr.h" +#include "bearer.h" +#include "name_table.h" +#include "bcast.h" + + +#define MAX_PKT_DEFAULT_MCAST 1500 /* bcast link max packet size (fixed) */ + +#define BCLINK_WIN_DEFAULT 20 /* bcast link window size (default) */ + +#define BCLINK_LOG_BUF_SIZE 0 + +/** + * struct bcbearer_pair - a pair of bearers used by broadcast link + * @primary: pointer to primary bearer + * @secondary: pointer to secondary bearer + * + * Bearers must have same priority and same set of reachable destinations + * to be paired. + */ + +struct bcbearer_pair { + struct bearer *primary; + struct bearer *secondary; +}; + +/** + * struct bcbearer - bearer used by broadcast link + * @bearer: (non-standard) broadcast bearer structure + * @media: (non-standard) broadcast media structure + * @bpairs: array of bearer pairs + * @bpairs_temp: array of bearer pairs used during creation of "bpairs" + */ + +struct bcbearer { + struct bearer bearer; + struct media media; + struct bcbearer_pair bpairs[MAX_BEARERS]; + struct bcbearer_pair bpairs_temp[TIPC_NUM_LINK_PRI]; +}; + +/** + * struct bclink - link used for broadcast messages + * @link: (non-standard) broadcast link structure + * @node: (non-standard) node structure representing b'cast link's peer node + * + * Handles sequence numbering, fragmentation, bundling, etc. + */ + +struct bclink { + struct link link; + struct node node; +}; + + +static struct bcbearer *bcbearer = NULL; +static struct bclink *bclink = NULL; +static struct link *bcl = NULL; +static spinlock_t bc_lock = SPIN_LOCK_UNLOCKED; + +char bc_link_name[] = "multicast-link"; + + +static inline u32 buf_seqno(struct sk_buff *buf) +{ + return msg_seqno(buf_msg(buf)); +} + +static inline u32 bcbuf_acks(struct sk_buff *buf) +{ + return (u32)TIPC_SKB_CB(buf)->handle; +} + +static inline void bcbuf_set_acks(struct sk_buff *buf, u32 acks) +{ + TIPC_SKB_CB(buf)->handle = (void *)acks; +} + +static inline void bcbuf_decr_acks(struct sk_buff *buf) +{ + bcbuf_set_acks(buf, bcbuf_acks(buf) - 1); +} + + +/** + * bclink_set_gap - set gap according to contents of current deferred pkt queue + * + * Called with 'node' locked, bc_lock unlocked + */ + +static inline void bclink_set_gap(struct node *n_ptr) +{ + struct sk_buff *buf = n_ptr->bclink.deferred_head; + + n_ptr->bclink.gap_after = n_ptr->bclink.gap_to = + mod(n_ptr->bclink.last_in); + if (unlikely(buf != NULL)) + n_ptr->bclink.gap_to = mod(buf_seqno(buf) - 1); +} + +/** + * bclink_ack_allowed - test if ACK or NACK message can be sent at this moment + * + * This mechanism endeavours to prevent all nodes in network from trying + * to ACK or NACK at the same time. + * + * Note: TIPC uses a different trigger to distribute ACKs than it does to + * distribute NACKs, but tries to use the same spacing (divide by 16). + */ + +static inline int bclink_ack_allowed(u32 n) +{ + return((n % TIPC_MIN_LINK_WIN) == tipc_own_tag); +} + + +/** + * bclink_retransmit_pkt - retransmit broadcast packets + * @after: sequence number of last packet to *not* retransmit + * @to: sequence number of last packet to retransmit + * + * Called with 'node' locked, bc_lock unlocked + */ + +static void bclink_retransmit_pkt(u32 after, u32 to) +{ + struct sk_buff *buf; + + spin_lock_bh(&bc_lock); + buf = bcl->first_out; + while (buf && less_eq(buf_seqno(buf), after)) { + buf = buf->next; + } + if (buf != NULL) + link_retransmit(bcl, buf, mod(to - after)); + spin_unlock_bh(&bc_lock); +} + +/** + * bclink_acknowledge - handle acknowledgement of broadcast packets + * @n_ptr: node that sent acknowledgement info + * @acked: broadcast sequence # that has been acknowledged + * + * Node is locked, bc_lock unlocked. + */ + +void bclink_acknowledge(struct node *n_ptr, u32 acked) +{ + struct sk_buff *crs; + struct sk_buff *next; + unsigned int released = 0; + + if (less_eq(acked, n_ptr->bclink.acked)) + return; + + spin_lock_bh(&bc_lock); + + /* Skip over packets that node has previously acknowledged */ + + crs = bcl->first_out; + while (crs && less_eq(buf_seqno(crs), n_ptr->bclink.acked)) { + crs = crs->next; + } + + /* Update packets that node is now acknowledging */ + + while (crs && less_eq(buf_seqno(crs), acked)) { + next = crs->next; + bcbuf_decr_acks(crs); + if (bcbuf_acks(crs) == 0) { + bcl->first_out = next; + bcl->out_queue_size--; + buf_discard(crs); + released = 1; + } + crs = next; + } + n_ptr->bclink.acked = acked; + + /* Try resolving broadcast link congestion, if necessary */ + + if (unlikely(bcl->next_out)) + link_push_queue(bcl); + if (unlikely(released && !list_empty(&bcl->waiting_ports))) + link_wakeup_ports(bcl, 0); + spin_unlock_bh(&bc_lock); +} + +/** + * bclink_send_ack - unicast an ACK msg + * + * net_lock and node lock set + */ + +static void bclink_send_ack(struct node *n_ptr) +{ + struct link *l_ptr = n_ptr->active_links[n_ptr->addr & 1]; + + if (l_ptr != NULL) + link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); +} + +/** + * bclink_send_nack- broadcast a NACK msg + * + * net_lock and node lock set + */ + +static void bclink_send_nack(struct node *n_ptr) +{ + struct sk_buff *buf; + struct tipc_msg *msg; + + if (!less(n_ptr->bclink.gap_after, n_ptr->bclink.gap_to)) + return; + + buf = buf_acquire(INT_H_SIZE); + if (buf) { + msg = buf_msg(buf); + msg_init(msg, BCAST_PROTOCOL, STATE_MSG, + TIPC_OK, INT_H_SIZE, n_ptr->addr); + msg_set_mc_netid(msg, tipc_net_id); + msg_set_bcast_ack(msg, mod(n_ptr->bclink.last_in)); + msg_set_bcgap_after(msg, n_ptr->bclink.gap_after); + msg_set_bcgap_to(msg, n_ptr->bclink.gap_to); + msg_set_bcast_tag(msg, tipc_own_tag); + + if (bearer_send(&bcbearer->bearer, buf, 0)) { + bcl->stats.sent_nacks++; + buf_discard(buf); + } else { + bearer_schedule(bcl->b_ptr, bcl); + bcl->proto_msg_queue = buf; + bcl->stats.bearer_congs++; + } + + /* + * Ensure we doesn't send another NACK msg to the node + * until 16 more deferred messages arrive from it + * (i.e. helps prevent all nodes from NACK'ing at same time) + */ + + n_ptr->bclink.nack_sync = tipc_own_tag; + } +} + +/** + * bclink_check_gap - send a NACK if a sequence gap exists + * + * net_lock and node lock set + */ + +void bclink_check_gap(struct node *n_ptr, u32 last_sent) +{ + if (!n_ptr->bclink.supported || + less_eq(last_sent, mod(n_ptr->bclink.last_in))) + return; + + bclink_set_gap(n_ptr); + if (n_ptr->bclink.gap_after == n_ptr->bclink.gap_to) + n_ptr->bclink.gap_to = last_sent; + bclink_send_nack(n_ptr); +} + +/** + * bclink_peek_nack - process a NACK msg meant for another node + * + * Only net_lock set. + */ + +void bclink_peek_nack(u32 dest, u32 sender_tag, u32 gap_after, u32 gap_to) +{ + struct node *n_ptr = node_find(dest); + u32 my_after, my_to; + + if (unlikely(!n_ptr || !node_is_up(n_ptr))) + return; + node_lock(n_ptr); + /* + * Modify gap to suppress unnecessary NACKs from this node + */ + my_after = n_ptr->bclink.gap_after; + my_to = n_ptr->bclink.gap_to; + + if (less_eq(gap_after, my_after)) { + if (less(my_after, gap_to) && less(gap_to, my_to)) + n_ptr->bclink.gap_after = gap_to; + else if (less_eq(my_to, gap_to)) + n_ptr->bclink.gap_to = n_ptr->bclink.gap_after; + } else if (less_eq(gap_after, my_to)) { + if (less_eq(my_to, gap_to)) + n_ptr->bclink.gap_to = gap_after; + } else { + /* + * Expand gap if missing bufs not in deferred queue: + */ + struct sk_buff *buf = n_ptr->bclink.deferred_head; + u32 prev = n_ptr->bclink.gap_to; + + for (; buf; buf = buf->next) { + u32 seqno = buf_seqno(buf); + + if (mod(seqno - prev) != 1) + buf = NULL; + if (seqno == gap_after) + break; + prev = seqno; + } + if (buf == NULL) + n_ptr->bclink.gap_to = gap_after; + } + /* + * Some nodes may send a complementary NACK now: + */ + if (bclink_ack_allowed(sender_tag + 1)) { + if (n_ptr->bclink.gap_to != n_ptr->bclink.gap_after) { + bclink_send_nack(n_ptr); + bclink_set_gap(n_ptr); + } + } + node_unlock(n_ptr); +} + +/** + * bclink_send_msg - broadcast a packet to all nodes in cluster + */ + +int bclink_send_msg(struct sk_buff *buf) +{ + int res; + + spin_lock_bh(&bc_lock); + + res = link_send_buf(bcl, buf); + if (unlikely(res == -ELINKCONG)) + buf_discard(buf); + else + bcl->stats.sent_info++; + + if (bcl->out_queue_size > bcl->stats.max_queue_sz) + bcl->stats.max_queue_sz = bcl->out_queue_size; + bcl->stats.queue_sz_counts++; + bcl->stats.accu_queue_sz += bcl->out_queue_size; + + spin_unlock_bh(&bc_lock); + return res; +} + +/** + * bclink_recv_pkt - receive a broadcast packet, and deliver upwards + * + * net_lock is read_locked, no other locks set + */ + +void bclink_recv_pkt(struct sk_buff *buf) +{ + struct tipc_msg *msg = buf_msg(buf); + struct node* node = node_find(msg_prevnode(msg)); + u32 next_in; + u32 seqno; + struct sk_buff *deferred; + + msg_dbg(msg, "bclink.supported || + (msg_mc_netid(msg) != tipc_net_id))) { + buf_discard(buf); + return; + } + + if (unlikely(msg_user(msg) == BCAST_PROTOCOL)) { + msg_dbg(msg, "stats.recv_nacks++; + bclink_retransmit_pkt(msg_bcgap_after(msg), + msg_bcgap_to(msg)); + } else { + bclink_peek_nack(msg_destnode(msg), + msg_bcast_tag(msg), + msg_bcgap_after(msg), + msg_bcgap_to(msg)); + } + buf_discard(buf); + return; + } + + node_lock(node); +receive: + deferred = node->bclink.deferred_head; + next_in = mod(node->bclink.last_in + 1); + seqno = msg_seqno(msg); + + if (likely(seqno == next_in)) { + bcl->stats.recv_info++; + node->bclink.last_in++; + bclink_set_gap(node); + if (unlikely(bclink_ack_allowed(seqno))) { + bclink_send_ack(node); + bcl->stats.sent_acks++; + } + if (likely(msg_isdata(msg))) { + node_unlock(node); + port_recv_mcast(buf, NULL); + } else if (msg_user(msg) == MSG_BUNDLER) { + bcl->stats.recv_bundles++; + bcl->stats.recv_bundled += msg_msgcnt(msg); + node_unlock(node); + link_recv_bundle(buf); + } else if (msg_user(msg) == MSG_FRAGMENTER) { + bcl->stats.recv_fragments++; + if (link_recv_fragment(&node->bclink.defragm, + &buf, &msg)) + bcl->stats.recv_fragmented++; + node_unlock(node); + net_route_msg(buf); + } else { + node_unlock(node); + net_route_msg(buf); + } + if (deferred && (buf_seqno(deferred) == mod(next_in + 1))) { + node_lock(node); + buf = deferred; + msg = buf_msg(buf); + node->bclink.deferred_head = deferred->next; + goto receive; + } + return; + } else if (less(next_in, seqno)) { + u32 gap_after = node->bclink.gap_after; + u32 gap_to = node->bclink.gap_to; + + if (link_defer_pkt(&node->bclink.deferred_head, + &node->bclink.deferred_tail, + buf)) { + node->bclink.nack_sync++; + bcl->stats.deferred_recv++; + if (seqno == mod(gap_after + 1)) + node->bclink.gap_after = seqno; + else if (less(gap_after, seqno) && less(seqno, gap_to)) + node->bclink.gap_to = seqno; + } + if (bclink_ack_allowed(node->bclink.nack_sync)) { + if (gap_to != gap_after) + bclink_send_nack(node); + bclink_set_gap(node); + } + } else { + bcl->stats.duplicates++; + buf_discard(buf); + } + node_unlock(node); +} + +u32 bclink_get_last_sent(void) +{ + u32 last_sent = mod(bcl->next_out_no - 1); + + if (bcl->next_out) + last_sent = mod(buf_seqno(bcl->next_out) - 1); + return last_sent; +} + +u32 bclink_acks_missing(struct node *n_ptr) +{ + return (n_ptr->bclink.supported && + (bclink_get_last_sent() != n_ptr->bclink.acked)); +} + + +/** + * bcbearer_send - send a packet through the broadcast pseudo-bearer + * + * Send through as many bearers as necessary to reach all nodes + * that support TIPC multicasting. + * + * Returns 0 if packet sent successfully, non-zero if not + */ + +int bcbearer_send(struct sk_buff *buf, + struct tipc_bearer *unused1, + struct tipc_media_addr *unused2) +{ + static int send_count = 0; + + struct node_map remains; + struct node_map remains_new; + int bp_index; + int swap_time; + + /* Prepare buffer for broadcasting (if first time trying to send it) */ + + if (likely(!msg_non_seq(buf_msg(buf)))) { + struct tipc_msg *msg; + + assert(cluster_bcast_nodes.count != 0); + bcbuf_set_acks(buf, cluster_bcast_nodes.count); + msg = buf_msg(buf); + msg_set_non_seq(msg); + msg_set_mc_netid(msg, tipc_net_id); + } + + /* Determine if bearer pairs should be swapped following this attempt */ + + if ((swap_time = (++send_count >= 10))) + send_count = 0; + + /* Send buffer over bearers until all targets reached */ + + remains = cluster_bcast_nodes; + + for (bp_index = 0; bp_index < MAX_BEARERS; bp_index++) { + struct bearer *p = bcbearer->bpairs[bp_index].primary; + struct bearer *s = bcbearer->bpairs[bp_index].secondary; + + if (!p) + break; /* no more bearers to try */ + + nmap_diff(&remains, &p->nodes, &remains_new); + if (remains_new.count == remains.count) + continue; /* bearer pair doesn't add anything */ + + if (!p->publ.blocked && + !p->media->send_msg(buf, &p->publ, &p->media->bcast_addr)) { + if (swap_time && s && !s->publ.blocked) + goto swap; + else + goto update; + } + + if (!s || s->publ.blocked || + s->media->send_msg(buf, &s->publ, &s->media->bcast_addr)) + continue; /* unable to send using bearer pair */ +swap: + bcbearer->bpairs[bp_index].primary = s; + bcbearer->bpairs[bp_index].secondary = p; +update: + if (remains_new.count == 0) + return TIPC_OK; + + remains = remains_new; + } + + /* Unable to reach all targets */ + + bcbearer->bearer.publ.blocked = 1; + bcl->stats.bearer_congs++; + return ~TIPC_OK; +} + +/** + * bcbearer_sort - create sets of bearer pairs used by broadcast bearer + */ + +void bcbearer_sort(void) +{ + struct bcbearer_pair *bp_temp = bcbearer->bpairs_temp; + struct bcbearer_pair *bp_curr; + int b_index; + int pri; + + spin_lock_bh(&bc_lock); + + /* Group bearers by priority (can assume max of two per priority) */ + + memset(bp_temp, 0, sizeof(bcbearer->bpairs_temp)); + + for (b_index = 0; b_index < MAX_BEARERS; b_index++) { + struct bearer *b = &bearers[b_index]; + + if (!b->active || !b->nodes.count) + continue; + + if (!bp_temp[b->priority].primary) + bp_temp[b->priority].primary = b; + else + bp_temp[b->priority].secondary = b; + } + + /* Create array of bearer pairs for broadcasting */ + + bp_curr = bcbearer->bpairs; + memset(bcbearer->bpairs, 0, sizeof(bcbearer->bpairs)); + + for (pri = (TIPC_NUM_LINK_PRI - 1); pri >= 0; pri--) { + + if (!bp_temp[pri].primary) + continue; + + bp_curr->primary = bp_temp[pri].primary; + + if (bp_temp[pri].secondary) { + if (nmap_equal(&bp_temp[pri].primary->nodes, + &bp_temp[pri].secondary->nodes)) { + bp_curr->secondary = bp_temp[pri].secondary; + } else { + bp_curr++; + bp_curr->primary = bp_temp[pri].secondary; + } + } + + bp_curr++; + } + + spin_unlock_bh(&bc_lock); +} + +/** + * bcbearer_push - resolve bearer congestion + * + * Forces bclink to push out any unsent packets, until all packets are gone + * or congestion reoccurs. + * No locks set when function called + */ + +void bcbearer_push(void) +{ + struct bearer *b_ptr; + + spin_lock_bh(&bc_lock); + b_ptr = &bcbearer->bearer; + if (b_ptr->publ.blocked) { + b_ptr->publ.blocked = 0; + bearer_lock_push(b_ptr); + } + spin_unlock_bh(&bc_lock); +} + + +int bclink_stats(char *buf, const u32 buf_size) +{ + struct print_buf pb; + + if (!bcl) + return 0; + + printbuf_init(&pb, buf, buf_size); + + spin_lock_bh(&bc_lock); + + tipc_printf(&pb, "Link <%s>\n" + " Window:%u packets\n", + bcl->name, bcl->queue_limit[0]); + tipc_printf(&pb, " RX packets:%u fragments:%u/%u bundles:%u/%u\n", + bcl->stats.recv_info, + bcl->stats.recv_fragments, + bcl->stats.recv_fragmented, + bcl->stats.recv_bundles, + bcl->stats.recv_bundled); + tipc_printf(&pb, " TX packets:%u fragments:%u/%u bundles:%u/%u\n", + bcl->stats.sent_info, + bcl->stats.sent_fragments, + bcl->stats.sent_fragmented, + bcl->stats.sent_bundles, + bcl->stats.sent_bundled); + tipc_printf(&pb, " RX naks:%u defs:%u dups:%u\n", + bcl->stats.recv_nacks, + bcl->stats.deferred_recv, + bcl->stats.duplicates); + tipc_printf(&pb, " TX naks:%u acks:%u dups:%u\n", + bcl->stats.sent_nacks, + bcl->stats.sent_acks, + bcl->stats.retransmitted); + tipc_printf(&pb, " Congestion bearer:%u link:%u Send queue max:%u avg:%u\n", + bcl->stats.bearer_congs, + bcl->stats.link_congs, + bcl->stats.max_queue_sz, + bcl->stats.queue_sz_counts + ? (bcl->stats.accu_queue_sz / bcl->stats.queue_sz_counts) + : 0); + + spin_unlock_bh(&bc_lock); + return printbuf_validate(&pb); +} + +int bclink_reset_stats(void) +{ + if (!bcl) + return -ENOPROTOOPT; + + spin_lock_bh(&bc_lock); + memset(&bcl->stats, 0, sizeof(bcl->stats)); + spin_unlock_bh(&bc_lock); + return TIPC_OK; +} + +int bclink_set_queue_limits(u32 limit) +{ + if (!bcl) + return -ENOPROTOOPT; + if ((limit < TIPC_MIN_LINK_WIN) || (limit > TIPC_MAX_LINK_WIN)) + return -EINVAL; + + spin_lock_bh(&bc_lock); + link_set_queue_limits(bcl, limit); + spin_unlock_bh(&bc_lock); + return TIPC_OK; +} + +int bclink_init(void) +{ + bcbearer = kmalloc(sizeof(*bcbearer), GFP_ATOMIC); + bclink = kmalloc(sizeof(*bclink), GFP_ATOMIC); + if (!bcbearer || !bclink) { + nomem: + warn("Memory squeeze; Failed to create multicast link\n"); + kfree(bcbearer); + bcbearer = NULL; + kfree(bclink); + bclink = NULL; + return -ENOMEM; + } + + memset(bcbearer, 0, sizeof(struct bcbearer)); + INIT_LIST_HEAD(&bcbearer->bearer.cong_links); + bcbearer->bearer.media = &bcbearer->media; + bcbearer->media.send_msg = bcbearer_send; + sprintf(bcbearer->media.name, "tipc-multicast"); + + bcl = &bclink->link; + memset(bclink, 0, sizeof(struct bclink)); + INIT_LIST_HEAD(&bcl->waiting_ports); + bcl->next_out_no = 1; + bclink->node.lock = SPIN_LOCK_UNLOCKED; + bcl->owner = &bclink->node; + bcl->max_pkt = MAX_PKT_DEFAULT_MCAST; + link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT); + bcl->b_ptr = &bcbearer->bearer; + bcl->state = WORKING_WORKING; + sprintf(bcl->name, bc_link_name); + + if (BCLINK_LOG_BUF_SIZE) { + char *pb = kmalloc(BCLINK_LOG_BUF_SIZE, GFP_ATOMIC); + + if (!pb) + goto nomem; + printbuf_init(&bcl->print_buf, pb, BCLINK_LOG_BUF_SIZE); + } + + return TIPC_OK; +} + +void bclink_stop(void) +{ + spin_lock_bh(&bc_lock); + if (bcbearer) { + link_stop(bcl); + if (BCLINK_LOG_BUF_SIZE) + kfree(bcl->print_buf.buf); + bcl = NULL; + kfree(bclink); + bclink = NULL; + kfree(bcbearer); + bcbearer = NULL; + } + spin_unlock_bh(&bc_lock); +} + diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h new file mode 100644 index 00000000000..cc2ede15c4f --- /dev/null +++ b/net/tipc/bcast.h @@ -0,0 +1,220 @@ +/* + * net/tipc/bcast.h: Include file for TIPC broadcast code + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _TIPC_BCAST_H +#define _TIPC_BCAST_H + +#define MAX_NODES 4096 +#define WSIZE 32 + +/** + * struct node_map - set of node identifiers + * @count: # of nodes in set + * @map: bitmap of node identifiers that are in the set + */ + +struct node_map { + u32 count; + u32 map[MAX_NODES / WSIZE]; +}; + + +#define PLSIZE 32 + +/** + * struct port_list - set of node local destination ports + * @count: # of ports in set (only valid for first entry in list) + * @next: pointer to next entry in list + * @ports: array of port references + */ + +struct port_list { + int count; + struct port_list *next; + u32 ports[PLSIZE]; +}; + + +struct node; + +extern char bc_link_name[]; + + +/** + * nmap_get - determine if node exists in a node map + */ + +static inline int nmap_get(struct node_map *nm_ptr, u32 node) +{ + int n = tipc_node(node); + int w = n / WSIZE; + int b = n % WSIZE; + + return nm_ptr->map[w] & (1 << b); +} + +/** + * nmap_add - add a node to a node map + */ + +static inline void nmap_add(struct node_map *nm_ptr, u32 node) +{ + int n = tipc_node(node); + int w = n / WSIZE; + u32 mask = (1 << (n % WSIZE)); + + if ((nm_ptr->map[w] & mask) == 0) { + nm_ptr->count++; + nm_ptr->map[w] |= mask; + } +} + +/** + * nmap_remove - remove a node from a node map + */ + +static inline void nmap_remove(struct node_map *nm_ptr, u32 node) +{ + int n = tipc_node(node); + int w = n / WSIZE; + u32 mask = (1 << (n % WSIZE)); + + if ((nm_ptr->map[w] & mask) != 0) { + nm_ptr->map[w] &= ~mask; + nm_ptr->count--; + } +} + +/** + * nmap_equal - test for equality of node maps + */ + +static inline int nmap_equal(struct node_map *nm_a, struct node_map *nm_b) +{ + return !memcmp(nm_a, nm_b, sizeof(*nm_a)); +} + +/** + * nmap_diff - find differences between node maps + * @nm_a: input node map A + * @nm_b: input node map B + * @nm_diff: output node map A-B (i.e. nodes of A that are not in B) + */ + +static inline void nmap_diff(struct node_map *nm_a, struct node_map *nm_b, + struct node_map *nm_diff) +{ + int stop = sizeof(nm_a->map) / sizeof(u32); + int w; + int b; + u32 map; + + memset(nm_diff, 0, sizeof(*nm_diff)); + for (w = 0; w < stop; w++) { + map = nm_a->map[w] ^ (nm_a->map[w] & nm_b->map[w]); + nm_diff->map[w] = map; + if (map != 0) { + for (b = 0 ; b < WSIZE; b++) { + if (map & (1 << b)) + nm_diff->count++; + } + } + } +} + +/** + * port_list_add - add a port to a port list, ensuring no duplicates + */ + +static inline void port_list_add(struct port_list *pl_ptr, u32 port) +{ + struct port_list *item = pl_ptr; + int i; + int item_sz = PLSIZE; + int cnt = pl_ptr->count; + + for (; ; cnt -= item_sz, item = item->next) { + if (cnt < PLSIZE) + item_sz = cnt; + for (i = 0; i < item_sz; i++) + if (item->ports[i] == port) + return; + if (i < PLSIZE) { + item->ports[i] = port; + pl_ptr->count++; + return; + } + if (!item->next) { + item->next = kmalloc(sizeof(*item), GFP_ATOMIC); + if (!item->next) { + warn("Memory squeeze: multicast destination port list is incomplete\n"); + return; + } + item->next->next = NULL; + } + } +} + +/** + * port_list_free - free dynamically created entries in port_list chain + * + * Note: First item is on stack, so it doesn't need to be released + */ + +static inline void port_list_free(struct port_list *pl_ptr) +{ + struct port_list *item; + struct port_list *next; + + for (item = pl_ptr->next; item; item = next) { + next = item->next; + kfree(item); + } +} + + +int bclink_init(void); +void bclink_stop(void); +void bclink_acknowledge(struct node *n_ptr, u32 acked); +int bclink_send_msg(struct sk_buff *buf); +void bclink_recv_pkt(struct sk_buff *buf); +u32 bclink_get_last_sent(void); +u32 bclink_acks_missing(struct node *n_ptr); +void bclink_check_gap(struct node *n_ptr, u32 seqno); +int bclink_stats(char *stats_buf, const u32 buf_size); +int bclink_reset_stats(void); +int bclink_set_queue_limits(u32 limit); +void bcbearer_sort(void); +void bcbearer_push(void); + +#endif diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c new file mode 100644 index 00000000000..c19465c5f03 --- /dev/null +++ b/net/tipc/bearer.c @@ -0,0 +1,689 @@ +/* + * net/tipc/bearer.c: TIPC bearer code + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2004-2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "core.h" +#include "config.h" +#include "dbg.h" +#include "bearer.h" +#include "link.h" +#include "port.h" +#include "discover.h" +#include "bcast.h" + +#define MAX_ADDR_STR 32 + +static struct media *media_list = 0; +static u32 media_count = 0; + +struct bearer *bearers = 0; + +/** + * media_name_valid - validate media name + * + * Returns 1 if media name is valid, otherwise 0. + */ + +static int media_name_valid(const char *name) +{ + u32 len; + + len = strlen(name); + if ((len + 1) > TIPC_MAX_MEDIA_NAME) + return 0; + return (strspn(name, tipc_alphabet) == len); +} + +/** + * media_find - locates specified media object by name + */ + +static struct media *media_find(const char *name) +{ + struct media *m_ptr; + u32 i; + + for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) { + if (!strcmp(m_ptr->name, name)) + return m_ptr; + } + return 0; +} + +/** + * tipc_register_media - register a media type + * + * Bearers for this media type must be activated separately at a later stage. + */ + +int tipc_register_media(u32 media_type, + char *name, + int (*enable)(struct tipc_bearer *), + void (*disable)(struct tipc_bearer *), + int (*send_msg)(struct sk_buff *, + struct tipc_bearer *, + struct tipc_media_addr *), + char *(*addr2str)(struct tipc_media_addr *a, + char *str_buf, int str_size), + struct tipc_media_addr *bcast_addr, + const u32 bearer_priority, + const u32 link_tolerance, /* [ms] */ + const u32 send_window_limit) +{ + struct media *m_ptr; + u32 media_id; + u32 i; + int res = -EINVAL; + + write_lock_bh(&net_lock); + if (!media_list) + goto exit; + + if (!media_name_valid(name)) { + warn("Media registration error: illegal name <%s>\n", name); + goto exit; + } + if (!bcast_addr) { + warn("Media registration error: no broadcast address supplied\n"); + goto exit; + } + if (bearer_priority >= TIPC_NUM_LINK_PRI) { + warn("Media registration error: priority %u\n", bearer_priority); + goto exit; + } + if ((link_tolerance < TIPC_MIN_LINK_TOL) || + (link_tolerance > TIPC_MAX_LINK_TOL)) { + warn("Media registration error: tolerance %u\n", link_tolerance); + goto exit; + } + + media_id = media_count++; + if (media_id >= MAX_MEDIA) { + warn("Attempt to register more than %u media\n", MAX_MEDIA); + media_count--; + goto exit; + } + for (i = 0; i < media_id; i++) { + if (media_list[i].type_id == media_type) { + warn("Attempt to register second media with type %u\n", + media_type); + media_count--; + goto exit; + } + if (!strcmp(name, media_list[i].name)) { + warn("Attempt to re-register media name <%s>\n", name); + media_count--; + goto exit; + } + } + + m_ptr = &media_list[media_id]; + m_ptr->type_id = media_type; + m_ptr->send_msg = send_msg; + m_ptr->enable_bearer = enable; + m_ptr->disable_bearer = disable; + m_ptr->addr2str = addr2str; + memcpy(&m_ptr->bcast_addr, bcast_addr, sizeof(*bcast_addr)); + m_ptr->bcast = 1; + strcpy(m_ptr->name, name); + m_ptr->priority = bearer_priority; + m_ptr->tolerance = link_tolerance; + m_ptr->window = send_window_limit; + dbg("Media <%s> registered\n", name); + res = 0; +exit: + write_unlock_bh(&net_lock); + return res; +} + +/** + * media_addr_printf - record media address in print buffer + */ + +void media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a) +{ + struct media *m_ptr; + u32 media_type; + u32 i; + + media_type = ntohl(a->type); + for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) { + if (m_ptr->type_id == media_type) + break; + } + + if ((i < media_count) && (m_ptr->addr2str != NULL)) { + char addr_str[MAX_ADDR_STR]; + + tipc_printf(pb, "%s(%s) ", m_ptr->name, + m_ptr->addr2str(a, addr_str, sizeof(addr_str))); + } else { + unchar *addr = (unchar *)&a->dev_addr; + + tipc_printf(pb, "UNKNOWN(%u):", media_type); + for (i = 0; i < (sizeof(*a) - sizeof(a->type)); i++) { + tipc_printf(pb, "%02x ", addr[i]); + } + } +} + +/** + * media_get_names - record names of registered media in buffer + */ + +struct sk_buff *media_get_names(void) +{ + struct sk_buff *buf; + struct media *m_ptr; + int i; + + buf = cfg_reply_alloc(MAX_MEDIA * TLV_SPACE(TIPC_MAX_MEDIA_NAME)); + if (!buf) + return NULL; + + read_lock_bh(&net_lock); + for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) { + cfg_append_tlv(buf, TIPC_TLV_MEDIA_NAME, m_ptr->name, + strlen(m_ptr->name) + 1); + } + read_unlock_bh(&net_lock); + return buf; +} + +/** + * bearer_name_validate - validate & (optionally) deconstruct bearer name + * @name - ptr to bearer name string + * @name_parts - ptr to area for bearer name components (or NULL if not needed) + * + * Returns 1 if bearer name is valid, otherwise 0. + */ + +static int bearer_name_validate(const char *name, + struct bearer_name *name_parts) +{ + char name_copy[TIPC_MAX_BEARER_NAME]; + char *media_name; + char *if_name; + u32 media_len; + u32 if_len; + + /* copy bearer name & ensure length is OK */ + + name_copy[TIPC_MAX_BEARER_NAME - 1] = 0; + /* need above in case non-Posix strncpy() doesn't pad with nulls */ + strncpy(name_copy, name, TIPC_MAX_BEARER_NAME); + if (name_copy[TIPC_MAX_BEARER_NAME - 1] != 0) + return 0; + + /* ensure all component parts of bearer name are present */ + + media_name = name_copy; + if ((if_name = strchr(media_name, ':')) == NULL) + return 0; + *(if_name++) = 0; + media_len = if_name - media_name; + if_len = strlen(if_name) + 1; + + /* validate component parts of bearer name */ + + if ((media_len <= 1) || (media_len > TIPC_MAX_MEDIA_NAME) || + (if_len <= 1) || (if_len > TIPC_MAX_IF_NAME) || + (strspn(media_name, tipc_alphabet) != (media_len - 1)) || + (strspn(if_name, tipc_alphabet) != (if_len - 1))) + return 0; + + /* return bearer name components, if necessary */ + + if (name_parts) { + strcpy(name_parts->media_name, media_name); + strcpy(name_parts->if_name, if_name); + } + return 1; +} + +/** + * bearer_find - locates bearer object with matching bearer name + */ + +static struct bearer *bearer_find(const char *name) +{ + struct bearer *b_ptr; + u32 i; + + for (i = 0, b_ptr = bearers; i < MAX_BEARERS; i++, b_ptr++) { + if (b_ptr->active && (!strcmp(b_ptr->publ.name, name))) + return b_ptr; + } + return 0; +} + +/** + * bearer_find - locates bearer object with matching interface name + */ + +struct bearer *bearer_find_interface(const char *if_name) +{ + struct bearer *b_ptr; + char *b_if_name; + u32 i; + + for (i = 0, b_ptr = bearers; i < MAX_BEARERS; i++, b_ptr++) { + if (!b_ptr->active) + continue; + b_if_name = strchr(b_ptr->publ.name, ':') + 1; + if (!strcmp(b_if_name, if_name)) + return b_ptr; + } + return 0; +} + +/** + * bearer_get_names - record names of bearers in buffer + */ + +struct sk_buff *bearer_get_names(void) +{ + struct sk_buff *buf; + struct media *m_ptr; + struct bearer *b_ptr; + int i, j; + + buf = cfg_reply_alloc(MAX_BEARERS * TLV_SPACE(TIPC_MAX_BEARER_NAME)); + if (!buf) + return NULL; + + read_lock_bh(&net_lock); + for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) { + for (j = 0; j < MAX_BEARERS; j++) { + b_ptr = &bearers[j]; + if (b_ptr->active && (b_ptr->media == m_ptr)) { + cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME, + b_ptr->publ.name, + strlen(b_ptr->publ.name) + 1); + } + } + } + read_unlock_bh(&net_lock); + return buf; +} + +void bearer_add_dest(struct bearer *b_ptr, u32 dest) +{ + nmap_add(&b_ptr->nodes, dest); + disc_update_link_req(b_ptr->link_req); + bcbearer_sort(); +} + +void bearer_remove_dest(struct bearer *b_ptr, u32 dest) +{ + nmap_remove(&b_ptr->nodes, dest); + disc_update_link_req(b_ptr->link_req); + bcbearer_sort(); +} + +/* + * bearer_push(): Resolve bearer congestion. Force the waiting + * links to push out their unsent packets, one packet per link + * per iteration, until all packets are gone or congestion reoccurs. + * 'net_lock' is read_locked when this function is called + * bearer.lock must be taken before calling + * Returns binary true(1) ore false(0) + */ +static int bearer_push(struct bearer *b_ptr) +{ + u32 res = TIPC_OK; + struct link *ln, *tln; + + if (b_ptr->publ.blocked) + return 0; + + while (!list_empty(&b_ptr->cong_links) && (res != PUSH_FAILED)) { + list_for_each_entry_safe(ln, tln, &b_ptr->cong_links, link_list) { + res = link_push_packet(ln); + if (res == PUSH_FAILED) + break; + if (res == PUSH_FINISHED) + list_move_tail(&ln->link_list, &b_ptr->links); + } + } + return list_empty(&b_ptr->cong_links); +} + +void bearer_lock_push(struct bearer *b_ptr) +{ + int res; + + spin_lock_bh(&b_ptr->publ.lock); + res = bearer_push(b_ptr); + spin_unlock_bh(&b_ptr->publ.lock); + if (res) + bcbearer_push(); +} + + +/* + * Interrupt enabling new requests after bearer congestion or blocking: + * See bearer_send(). + */ +void tipc_continue(struct tipc_bearer *tb_ptr) +{ + struct bearer *b_ptr = (struct bearer *)tb_ptr; + + spin_lock_bh(&b_ptr->publ.lock); + b_ptr->continue_count++; + if (!list_empty(&b_ptr->cong_links)) + k_signal((Handler)bearer_lock_push, (unsigned long)b_ptr); + b_ptr->publ.blocked = 0; + spin_unlock_bh(&b_ptr->publ.lock); +} + +/* + * Schedule link for sending of messages after the bearer + * has been deblocked by 'continue()'. This method is called + * when somebody tries to send a message via this link while + * the bearer is congested. 'net_lock' is in read_lock here + * bearer.lock is busy + */ + +static void bearer_schedule_unlocked(struct bearer *b_ptr, struct link *l_ptr) +{ + list_move_tail(&l_ptr->link_list, &b_ptr->cong_links); +} + +/* + * Schedule link for sending of messages after the bearer + * has been deblocked by 'continue()'. This method is called + * when somebody tries to send a message via this link while + * the bearer is congested. 'net_lock' is in read_lock here, + * bearer.lock is free + */ + +void bearer_schedule(struct bearer *b_ptr, struct link *l_ptr) +{ + spin_lock_bh(&b_ptr->publ.lock); + bearer_schedule_unlocked(b_ptr, l_ptr); + spin_unlock_bh(&b_ptr->publ.lock); +} + + +/* + * bearer_resolve_congestion(): Check if there is bearer congestion, + * and if there is, try to resolve it before returning. + * 'net_lock' is read_locked when this function is called + */ +int bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr) +{ + int res = 1; + + if (list_empty(&b_ptr->cong_links)) + return 1; + spin_lock_bh(&b_ptr->publ.lock); + if (!bearer_push(b_ptr)) { + bearer_schedule_unlocked(b_ptr, l_ptr); + res = 0; + } + spin_unlock_bh(&b_ptr->publ.lock); + return res; +} + + +/** + * tipc_enable_bearer - enable bearer with the given name + */ + +int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority) +{ + struct bearer *b_ptr; + struct media *m_ptr; + struct bearer_name b_name; + char addr_string[16]; + u32 bearer_id; + u32 with_this_prio; + u32 i; + int res = -EINVAL; + + if (tipc_mode != TIPC_NET_MODE) + return -ENOPROTOOPT; + if (!bearer_name_validate(name, &b_name) || + !addr_domain_valid(bcast_scope) || + !in_scope(bcast_scope, tipc_own_addr) || + (priority > TIPC_NUM_LINK_PRI)) + return -EINVAL; + + write_lock_bh(&net_lock); + if (!bearers) + goto failed; + + m_ptr = media_find(b_name.media_name); + if (!m_ptr) { + warn("No media <%s>\n", b_name.media_name); + goto failed; + } + if (priority == TIPC_NUM_LINK_PRI) + priority = m_ptr->priority; + +restart: + bearer_id = MAX_BEARERS; + with_this_prio = 1; + for (i = MAX_BEARERS; i-- != 0; ) { + if (!bearers[i].active) { + bearer_id = i; + continue; + } + if (!strcmp(name, bearers[i].publ.name)) { + warn("Bearer <%s> already enabled\n", name); + goto failed; + } + if ((bearers[i].priority == priority) && + (++with_this_prio > 2)) { + if (priority-- == 0) { + warn("Third bearer <%s> with priority %u, unable to lower to %u\n", + name, priority + 1, priority); + goto failed; + } + warn("Third bearer <%s> with priority %u, lowering to %u\n", + name, priority + 1, priority); + goto restart; + } + } + if (bearer_id >= MAX_BEARERS) { + warn("Attempt to enable more than %d bearers\n", MAX_BEARERS); + goto failed; + } + + b_ptr = &bearers[bearer_id]; + memset(b_ptr, 0, sizeof(struct bearer)); + + strcpy(b_ptr->publ.name, name); + res = m_ptr->enable_bearer(&b_ptr->publ); + if (res) { + warn("Failed to enable bearer <%s>\n", name); + goto failed; + } + + b_ptr->identity = bearer_id; + b_ptr->media = m_ptr; + b_ptr->net_plane = bearer_id + 'A'; + b_ptr->active = 1; + b_ptr->detect_scope = bcast_scope; + b_ptr->priority = priority; + INIT_LIST_HEAD(&b_ptr->cong_links); + INIT_LIST_HEAD(&b_ptr->links); + if (m_ptr->bcast) { + b_ptr->link_req = disc_init_link_req(b_ptr, &m_ptr->bcast_addr, + bcast_scope, 2); + } + b_ptr->publ.lock = SPIN_LOCK_UNLOCKED; + write_unlock_bh(&net_lock); + info("Enabled bearer <%s>, discovery domain %s\n", + name, addr_string_fill(addr_string, bcast_scope)); + return 0; +failed: + write_unlock_bh(&net_lock); + return res; +} + +/** + * tipc_block_bearer(): Block the bearer with the given name, + * and reset all its links + */ + +int tipc_block_bearer(const char *name) +{ + struct bearer *b_ptr = 0; + struct link *l_ptr; + struct link *temp_l_ptr; + + if (tipc_mode != TIPC_NET_MODE) + return -ENOPROTOOPT; + + read_lock_bh(&net_lock); + b_ptr = bearer_find(name); + if (!b_ptr) { + warn("Attempt to block unknown bearer <%s>\n", name); + read_unlock_bh(&net_lock); + return -EINVAL; + } + + spin_lock_bh(&b_ptr->publ.lock); + b_ptr->publ.blocked = 1; + list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { + struct node *n_ptr = l_ptr->owner; + + spin_lock_bh(&n_ptr->lock); + link_reset(l_ptr); + spin_unlock_bh(&n_ptr->lock); + } + spin_unlock_bh(&b_ptr->publ.lock); + read_unlock_bh(&net_lock); + info("Blocked bearer <%s>\n", name); + return TIPC_OK; +} + +/** + * bearer_disable - + * + * Note: This routine assumes caller holds net_lock. + */ + +static int bearer_disable(const char *name) +{ + struct bearer *b_ptr; + struct link *l_ptr; + struct link *temp_l_ptr; + + if (tipc_mode != TIPC_NET_MODE) + return -ENOPROTOOPT; + + b_ptr = bearer_find(name); + if (!b_ptr) { + warn("Attempt to disable unknown bearer <%s>\n", name); + return -EINVAL; + } + + disc_stop_link_req(b_ptr->link_req); + spin_lock_bh(&b_ptr->publ.lock); + b_ptr->link_req = NULL; + b_ptr->publ.blocked = 1; + if (b_ptr->media->disable_bearer) { + spin_unlock_bh(&b_ptr->publ.lock); + write_unlock_bh(&net_lock); + b_ptr->media->disable_bearer(&b_ptr->publ); + write_lock_bh(&net_lock); + spin_lock_bh(&b_ptr->publ.lock); + } + list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { + link_delete(l_ptr); + } + spin_unlock_bh(&b_ptr->publ.lock); + info("Disabled bearer <%s>\n", name); + memset(b_ptr, 0, sizeof(struct bearer)); + return TIPC_OK; +} + +int tipc_disable_bearer(const char *name) +{ + int res; + + write_lock_bh(&net_lock); + res = bearer_disable(name); + write_unlock_bh(&net_lock); + return res; +} + + + +int bearer_init(void) +{ + int res; + + write_lock_bh(&net_lock); + bearers = kmalloc(MAX_BEARERS * sizeof(struct bearer), GFP_ATOMIC); + media_list = kmalloc(MAX_MEDIA * sizeof(struct media), GFP_ATOMIC); + if (bearers && media_list) { + memset(bearers, 0, MAX_BEARERS * sizeof(struct bearer)); + memset(media_list, 0, MAX_MEDIA * sizeof(struct media)); + res = TIPC_OK; + } else { + kfree(bearers); + kfree(media_list); + bearers = 0; + media_list = 0; + res = -ENOMEM; + } + write_unlock_bh(&net_lock); + return res; +} + +void bearer_stop(void) +{ + u32 i; + + if (!bearers) + return; + + for (i = 0; i < MAX_BEARERS; i++) { + if (bearers[i].active) + bearers[i].publ.blocked = 1; + } + for (i = 0; i < MAX_BEARERS; i++) { + if (bearers[i].active) + bearer_disable(bearers[i].publ.name); + } + kfree(bearers); + kfree(media_list); + bearers = 0; + media_list = 0; + media_count = 0; +} + + diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h new file mode 100644 index 00000000000..02a16f86def --- /dev/null +++ b/net/tipc/bearer.h @@ -0,0 +1,169 @@ +/* + * net/tipc/bearer.h: Include file for TIPC bearer code + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _TIPC_BEARER_H +#define _TIPC_BEARER_H + +#include +#include "bcast.h" + +#define MAX_BEARERS 8 +#define MAX_MEDIA 4 + + +/** + * struct media - TIPC media information available to internal users + * @send_msg: routine which handles buffer transmission + * @enable_bearer: routine which enables a bearer + * @disable_bearer: routine which disables a bearer + * @addr2str: routine which converts bearer's address to string form + * @bcast_addr: media address used in broadcasting + * @bcast: non-zero if media supports broadcasting [currently mandatory] + * @priority: default link (and bearer) priority + * @tolerance: default time (in ms) before declaring link failure + * @window: default window (in packets) before declaring link congestion + * @type_id: TIPC media identifier [defined in tipc_bearer.h] + * @name: media name + */ + +struct media { + int (*send_msg)(struct sk_buff *buf, + struct tipc_bearer *b_ptr, + struct tipc_media_addr *dest); + int (*enable_bearer)(struct tipc_bearer *b_ptr); + void (*disable_bearer)(struct tipc_bearer *b_ptr); + char *(*addr2str)(struct tipc_media_addr *a, + char *str_buf, int str_size); + struct tipc_media_addr bcast_addr; + int bcast; + u32 priority; + u32 tolerance; + u32 window; + u32 type_id; + char name[TIPC_MAX_MEDIA_NAME]; +}; + +/** + * struct bearer - TIPC bearer information available to internal users + * @publ: bearer information available to privileged users + * @media: ptr to media structure associated with bearer + * @priority: default link priority for bearer + * @detect_scope: network address mask used during automatic link creation + * @identity: array index of this bearer within TIPC bearer array + * @link_req: ptr to (optional) structure making periodic link setup requests + * @links: list of non-congested links associated with bearer + * @cong_links: list of congested links associated with bearer + * @continue_count: # of times bearer has resumed after congestion or blocking + * @active: non-zero if bearer structure is represents a bearer + * @net_plane: network plane ('A' through 'H') currently associated with bearer + * @nodes: indicates which nodes in cluster can be reached through bearer + */ + +struct bearer { + struct tipc_bearer publ; + struct media *media; + u32 priority; + u32 detect_scope; + u32 identity; + struct link_req *link_req; + struct list_head links; + struct list_head cong_links; + u32 continue_count; + int active; + char net_plane; + struct node_map nodes; +}; + +struct bearer_name { + char media_name[TIPC_MAX_MEDIA_NAME]; + char if_name[TIPC_MAX_IF_NAME]; +}; + +struct link; + +extern struct bearer *bearers; + +void media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a); +struct sk_buff *media_get_names(void); + +struct sk_buff *bearer_get_names(void); +void bearer_add_dest(struct bearer *b_ptr, u32 dest); +void bearer_remove_dest(struct bearer *b_ptr, u32 dest); +void bearer_schedule(struct bearer *b_ptr, struct link *l_ptr); +struct bearer *bearer_find_interface(const char *if_name); +int bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr); +int bearer_init(void); +void bearer_stop(void); +int bearer_broadcast(struct sk_buff *buf, struct tipc_bearer *b_ptr, + struct tipc_media_addr *dest); +void bearer_lock_push(struct bearer *b_ptr); + + +/** + * bearer_send- sends buffer to destination over bearer + * + * Returns true (1) if successful, or false (0) if unable to send + * + * IMPORTANT: + * The media send routine must not alter the buffer being passed in + * as it may be needed for later retransmission! + * + * If the media send routine returns a non-zero value (indicating that + * it was unable to send the buffer), it must: + * 1) mark the bearer as blocked, + * 2) call tipc_continue() once the bearer is able to send again. + * Media types that are unable to meet these two critera must ensure their + * send routine always returns success -- even if the buffer was not sent -- + * and let TIPC's link code deal with the undelivered message. + */ + +static inline int bearer_send(struct bearer *b_ptr, struct sk_buff *buf, + struct tipc_media_addr *dest) +{ + return !b_ptr->media->send_msg(buf, &b_ptr->publ, dest); +} + +/** + * bearer_congested - determines if bearer is currently congested + */ + +static inline int bearer_congested(struct bearer *b_ptr, struct link *l_ptr) +{ + if (unlikely(b_ptr->publ.blocked)) + return 1; + if (likely(list_empty(&b_ptr->cong_links))) + return 0; + return !bearer_resolve_congestion(b_ptr, l_ptr); +} + +#endif diff --git a/net/tipc/cluster.c b/net/tipc/cluster.c new file mode 100644 index 00000000000..d7d0f5f17e0 --- /dev/null +++ b/net/tipc/cluster.c @@ -0,0 +1,573 @@ +/* + * net/tipc/cluster.c: TIPC cluster management routines + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "core.h" +#include "cluster.h" +#include "addr.h" +#include "node_subscr.h" +#include "link.h" +#include "node.h" +#include "net.h" +#include "msg.h" +#include "bearer.h" + +void cluster_multicast(struct cluster *c_ptr, struct sk_buff *buf, + u32 lower, u32 upper); +struct sk_buff *cluster_prepare_routing_msg(u32 data_size, u32 dest); + +struct node **local_nodes = 0; +struct node_map cluster_bcast_nodes = {0,{0,}}; +u32 highest_allowed_slave = 0; + +struct cluster *cluster_create(u32 addr) +{ + struct _zone *z_ptr; + struct cluster *c_ptr; + int max_nodes; + int alloc; + + c_ptr = (struct cluster *)kmalloc(sizeof(*c_ptr), GFP_ATOMIC); + if (c_ptr == NULL) + return 0; + memset(c_ptr, 0, sizeof(*c_ptr)); + + c_ptr->addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0); + if (in_own_cluster(addr)) + max_nodes = LOWEST_SLAVE + tipc_max_slaves; + else + max_nodes = tipc_max_nodes + 1; + alloc = sizeof(void *) * (max_nodes + 1); + c_ptr->nodes = (struct node **)kmalloc(alloc, GFP_ATOMIC); + if (c_ptr->nodes == NULL) { + kfree(c_ptr); + return 0; + } + memset(c_ptr->nodes, 0, alloc); + if (in_own_cluster(addr)) + local_nodes = c_ptr->nodes; + c_ptr->highest_slave = LOWEST_SLAVE - 1; + c_ptr->highest_node = 0; + + z_ptr = zone_find(tipc_zone(addr)); + if (z_ptr == NULL) { + z_ptr = zone_create(addr); + } + if (z_ptr != NULL) { + zone_attach_cluster(z_ptr, c_ptr); + c_ptr->owner = z_ptr; + } + else { + kfree(c_ptr); + c_ptr = 0; + } + + return c_ptr; +} + +void cluster_delete(struct cluster *c_ptr) +{ + u32 n_num; + + if (!c_ptr) + return; + for (n_num = 1; n_num <= c_ptr->highest_node; n_num++) { + node_delete(c_ptr->nodes[n_num]); + } + for (n_num = LOWEST_SLAVE; n_num <= c_ptr->highest_slave; n_num++) { + node_delete(c_ptr->nodes[n_num]); + } + kfree(c_ptr->nodes); + kfree(c_ptr); +} + +u32 cluster_next_node(struct cluster *c_ptr, u32 addr) +{ + struct node *n_ptr; + u32 n_num = tipc_node(addr) + 1; + + if (!c_ptr) + return addr; + for (; n_num <= c_ptr->highest_node; n_num++) { + n_ptr = c_ptr->nodes[n_num]; + if (n_ptr && node_has_active_links(n_ptr)) + return n_ptr->addr; + } + for (n_num = 1; n_num < tipc_node(addr); n_num++) { + n_ptr = c_ptr->nodes[n_num]; + if (n_ptr && node_has_active_links(n_ptr)) + return n_ptr->addr; + } + return 0; +} + +void cluster_attach_node(struct cluster *c_ptr, struct node *n_ptr) +{ + u32 n_num = tipc_node(n_ptr->addr); + u32 max_n_num = tipc_max_nodes; + + if (in_own_cluster(n_ptr->addr)) + max_n_num = highest_allowed_slave; + assert(n_num > 0); + assert(n_num <= max_n_num); + assert(c_ptr->nodes[n_num] == 0); + c_ptr->nodes[n_num] = n_ptr; + if (n_num > c_ptr->highest_node) + c_ptr->highest_node = n_num; +} + +/** + * cluster_select_router - select router to a cluster + * + * Uses deterministic and fair algorithm. + */ + +u32 cluster_select_router(struct cluster *c_ptr, u32 ref) +{ + u32 n_num; + u32 ulim = c_ptr->highest_node; + u32 mask; + u32 tstart; + + assert(!in_own_cluster(c_ptr->addr)); + if (!ulim) + return 0; + + /* Start entry must be random */ + mask = tipc_max_nodes; + while (mask > ulim) + mask >>= 1; + tstart = ref & mask; + n_num = tstart; + + /* Lookup upwards with wrap-around */ + do { + if (node_is_up(c_ptr->nodes[n_num])) + break; + } while (++n_num <= ulim); + if (n_num > ulim) { + n_num = 1; + do { + if (node_is_up(c_ptr->nodes[n_num])) + break; + } while (++n_num < tstart); + if (n_num == tstart) + return 0; + } + assert(n_num <= ulim); + return node_select_router(c_ptr->nodes[n_num], ref); +} + +/** + * cluster_select_node - select destination node within a remote cluster + * + * Uses deterministic and fair algorithm. + */ + +struct node *cluster_select_node(struct cluster *c_ptr, u32 selector) +{ + u32 n_num; + u32 mask = tipc_max_nodes; + u32 start_entry; + + assert(!in_own_cluster(c_ptr->addr)); + if (!c_ptr->highest_node) + return 0; + + /* Start entry must be random */ + while (mask > c_ptr->highest_node) { + mask >>= 1; + } + start_entry = (selector & mask) ? selector & mask : 1u; + assert(start_entry <= c_ptr->highest_node); + + /* Lookup upwards with wrap-around */ + for (n_num = start_entry; n_num <= c_ptr->highest_node; n_num++) { + if (node_has_active_links(c_ptr->nodes[n_num])) + return c_ptr->nodes[n_num]; + } + for (n_num = 1; n_num < start_entry; n_num++) { + if (node_has_active_links(c_ptr->nodes[n_num])) + return c_ptr->nodes[n_num]; + } + return 0; +} + +/* + * Routing table management: See description in node.c + */ + +struct sk_buff *cluster_prepare_routing_msg(u32 data_size, u32 dest) +{ + u32 size = INT_H_SIZE + data_size; + struct sk_buff *buf = buf_acquire(size); + struct tipc_msg *msg; + + if (buf) { + msg = buf_msg(buf); + memset((char *)msg, 0, size); + msg_init(msg, ROUTE_DISTRIBUTOR, 0, TIPC_OK, INT_H_SIZE, dest); + } + return buf; +} + +void cluster_bcast_new_route(struct cluster *c_ptr, u32 dest, + u32 lower, u32 upper) +{ + struct sk_buff *buf = cluster_prepare_routing_msg(0, c_ptr->addr); + struct tipc_msg *msg; + + if (buf) { + msg = buf_msg(buf); + msg_set_remote_node(msg, dest); + msg_set_type(msg, ROUTE_ADDITION); + cluster_multicast(c_ptr, buf, lower, upper); + } else { + warn("Memory squeeze: broadcast of new route failed\n"); + } +} + +void cluster_bcast_lost_route(struct cluster *c_ptr, u32 dest, + u32 lower, u32 upper) +{ + struct sk_buff *buf = cluster_prepare_routing_msg(0, c_ptr->addr); + struct tipc_msg *msg; + + if (buf) { + msg = buf_msg(buf); + msg_set_remote_node(msg, dest); + msg_set_type(msg, ROUTE_REMOVAL); + cluster_multicast(c_ptr, buf, lower, upper); + } else { + warn("Memory squeeze: broadcast of lost route failed\n"); + } +} + +void cluster_send_slave_routes(struct cluster *c_ptr, u32 dest) +{ + struct sk_buff *buf; + struct tipc_msg *msg; + u32 highest = c_ptr->highest_slave; + u32 n_num; + int send = 0; + + assert(!is_slave(dest)); + assert(in_own_cluster(dest)); + assert(in_own_cluster(c_ptr->addr)); + if (highest <= LOWEST_SLAVE) + return; + buf = cluster_prepare_routing_msg(highest - LOWEST_SLAVE + 1, + c_ptr->addr); + if (buf) { + msg = buf_msg(buf); + msg_set_remote_node(msg, c_ptr->addr); + msg_set_type(msg, SLAVE_ROUTING_TABLE); + for (n_num = LOWEST_SLAVE; n_num <= highest; n_num++) { + if (c_ptr->nodes[n_num] && + node_has_active_links(c_ptr->nodes[n_num])) { + send = 1; + msg_set_dataoctet(msg, n_num); + } + } + if (send) + link_send(buf, dest, dest); + else + buf_discard(buf); + } else { + warn("Memory squeeze: broadcast of lost route failed\n"); + } +} + +void cluster_send_ext_routes(struct cluster *c_ptr, u32 dest) +{ + struct sk_buff *buf; + struct tipc_msg *msg; + u32 highest = c_ptr->highest_node; + u32 n_num; + int send = 0; + + if (in_own_cluster(c_ptr->addr)) + return; + assert(!is_slave(dest)); + assert(in_own_cluster(dest)); + highest = c_ptr->highest_node; + buf = cluster_prepare_routing_msg(highest + 1, c_ptr->addr); + if (buf) { + msg = buf_msg(buf); + msg_set_remote_node(msg, c_ptr->addr); + msg_set_type(msg, EXT_ROUTING_TABLE); + for (n_num = 1; n_num <= highest; n_num++) { + if (c_ptr->nodes[n_num] && + node_has_active_links(c_ptr->nodes[n_num])) { + send = 1; + msg_set_dataoctet(msg, n_num); + } + } + if (send) + link_send(buf, dest, dest); + else + buf_discard(buf); + } else { + warn("Memory squeeze: broadcast of external route failed\n"); + } +} + +void cluster_send_local_routes(struct cluster *c_ptr, u32 dest) +{ + struct sk_buff *buf; + struct tipc_msg *msg; + u32 highest = c_ptr->highest_node; + u32 n_num; + int send = 0; + + assert(is_slave(dest)); + assert(in_own_cluster(c_ptr->addr)); + buf = cluster_prepare_routing_msg(highest, c_ptr->addr); + if (buf) { + msg = buf_msg(buf); + msg_set_remote_node(msg, c_ptr->addr); + msg_set_type(msg, LOCAL_ROUTING_TABLE); + for (n_num = 1; n_num <= highest; n_num++) { + if (c_ptr->nodes[n_num] && + node_has_active_links(c_ptr->nodes[n_num])) { + send = 1; + msg_set_dataoctet(msg, n_num); + } + } + if (send) + link_send(buf, dest, dest); + else + buf_discard(buf); + } else { + warn("Memory squeeze: broadcast of local route failed\n"); + } +} + +void cluster_recv_routing_table(struct sk_buff *buf) +{ + struct tipc_msg *msg = buf_msg(buf); + struct cluster *c_ptr; + struct node *n_ptr; + unchar *node_table; + u32 table_size; + u32 router; + u32 rem_node = msg_remote_node(msg); + u32 z_num; + u32 c_num; + u32 n_num; + + c_ptr = cluster_find(rem_node); + if (!c_ptr) { + c_ptr = cluster_create(rem_node); + if (!c_ptr) { + buf_discard(buf); + return; + } + } + + node_table = buf->data + msg_hdr_sz(msg); + table_size = msg_size(msg) - msg_hdr_sz(msg); + router = msg_prevnode(msg); + z_num = tipc_zone(rem_node); + c_num = tipc_cluster(rem_node); + + switch (msg_type(msg)) { + case LOCAL_ROUTING_TABLE: + assert(is_slave(tipc_own_addr)); + case EXT_ROUTING_TABLE: + for (n_num = 1; n_num < table_size; n_num++) { + if (node_table[n_num]) { + u32 addr = tipc_addr(z_num, c_num, n_num); + n_ptr = c_ptr->nodes[n_num]; + if (!n_ptr) { + n_ptr = node_create(addr); + } + if (n_ptr) + node_add_router(n_ptr, router); + } + } + break; + case SLAVE_ROUTING_TABLE: + assert(!is_slave(tipc_own_addr)); + assert(in_own_cluster(c_ptr->addr)); + for (n_num = 1; n_num < table_size; n_num++) { + if (node_table[n_num]) { + u32 slave_num = n_num + LOWEST_SLAVE; + u32 addr = tipc_addr(z_num, c_num, slave_num); + n_ptr = c_ptr->nodes[slave_num]; + if (!n_ptr) { + n_ptr = node_create(addr); + } + if (n_ptr) + node_add_router(n_ptr, router); + } + } + break; + case ROUTE_ADDITION: + if (!is_slave(tipc_own_addr)) { + assert(!in_own_cluster(c_ptr->addr) + || is_slave(rem_node)); + } else { + assert(in_own_cluster(c_ptr->addr) + && !is_slave(rem_node)); + } + n_ptr = c_ptr->nodes[tipc_node(rem_node)]; + if (!n_ptr) + n_ptr = node_create(rem_node); + if (n_ptr) + node_add_router(n_ptr, router); + break; + case ROUTE_REMOVAL: + if (!is_slave(tipc_own_addr)) { + assert(!in_own_cluster(c_ptr->addr) + || is_slave(rem_node)); + } else { + assert(in_own_cluster(c_ptr->addr) + && !is_slave(rem_node)); + } + n_ptr = c_ptr->nodes[tipc_node(rem_node)]; + if (n_ptr) + node_remove_router(n_ptr, router); + break; + default: + assert(!"Illegal routing manager message received\n"); + } + buf_discard(buf); +} + +void cluster_remove_as_router(struct cluster *c_ptr, u32 router) +{ + u32 start_entry; + u32 tstop; + u32 n_num; + + if (is_slave(router)) + return; /* Slave nodes can not be routers */ + + if (in_own_cluster(c_ptr->addr)) { + start_entry = LOWEST_SLAVE; + tstop = c_ptr->highest_slave; + } else { + start_entry = 1; + tstop = c_ptr->highest_node; + } + + for (n_num = start_entry; n_num <= tstop; n_num++) { + if (c_ptr->nodes[n_num]) { + node_remove_router(c_ptr->nodes[n_num], router); + } + } +} + +/** + * cluster_multicast - multicast message to local nodes + */ + +void cluster_multicast(struct cluster *c_ptr, struct sk_buff *buf, + u32 lower, u32 upper) +{ + struct sk_buff *buf_copy; + struct node *n_ptr; + u32 n_num; + u32 tstop; + + assert(lower <= upper); + assert(((lower >= 1) && (lower <= tipc_max_nodes)) || + ((lower >= LOWEST_SLAVE) && (lower <= highest_allowed_slave))); + assert(((upper >= 1) && (upper <= tipc_max_nodes)) || + ((upper >= LOWEST_SLAVE) && (upper <= highest_allowed_slave))); + assert(in_own_cluster(c_ptr->addr)); + + tstop = is_slave(upper) ? c_ptr->highest_slave : c_ptr->highest_node; + if (tstop > upper) + tstop = upper; + for (n_num = lower; n_num <= tstop; n_num++) { + n_ptr = c_ptr->nodes[n_num]; + if (n_ptr && node_has_active_links(n_ptr)) { + buf_copy = skb_copy(buf, GFP_ATOMIC); + if (buf_copy == NULL) + break; + msg_set_destnode(buf_msg(buf_copy), n_ptr->addr); + link_send(buf_copy, n_ptr->addr, n_ptr->addr); + } + } + buf_discard(buf); +} + +/** + * cluster_broadcast - broadcast message to all nodes within cluster + */ + +void cluster_broadcast(struct sk_buff *buf) +{ + struct sk_buff *buf_copy; + struct cluster *c_ptr; + struct node *n_ptr; + u32 n_num; + u32 tstart; + u32 tstop; + u32 node_type; + + if (tipc_mode == TIPC_NET_MODE) { + c_ptr = cluster_find(tipc_own_addr); + assert(in_own_cluster(c_ptr->addr)); /* For now */ + + /* Send to standard nodes, then repeat loop sending to slaves */ + tstart = 1; + tstop = c_ptr->highest_node; + for (node_type = 1; node_type <= 2; node_type++) { + for (n_num = tstart; n_num <= tstop; n_num++) { + n_ptr = c_ptr->nodes[n_num]; + if (n_ptr && node_has_active_links(n_ptr)) { + buf_copy = skb_copy(buf, GFP_ATOMIC); + if (buf_copy == NULL) + goto exit; + msg_set_destnode(buf_msg(buf_copy), + n_ptr->addr); + link_send(buf_copy, n_ptr->addr, + n_ptr->addr); + } + } + tstart = LOWEST_SLAVE; + tstop = c_ptr->highest_slave; + } + } +exit: + buf_discard(buf); +} + +int cluster_init(void) +{ + highest_allowed_slave = LOWEST_SLAVE + tipc_max_slaves; + return cluster_create(tipc_own_addr) ? TIPC_OK : -ENOMEM; +} + diff --git a/net/tipc/cluster.h b/net/tipc/cluster.h new file mode 100644 index 00000000000..c12875ab46b --- /dev/null +++ b/net/tipc/cluster.h @@ -0,0 +1,89 @@ +/* + * net/tipc/cluster.h: Include file for TIPC cluster management routines + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _TIPC_CLUSTER_H +#define _TIPC_CLUSTER_H + +#include "addr.h" +#include "zone.h" + +#define LOWEST_SLAVE 2048u + +/** + * struct cluster - TIPC cluster structure + * @addr: network address of cluster + * @owner: pointer to zone that cluster belongs to + * @nodes: array of pointers to all nodes within cluster + * @highest_node: id of highest numbered node within cluster + * @highest_slave: (used for secondary node support) + */ + +struct cluster { + u32 addr; + struct _zone *owner; + struct node **nodes; + u32 highest_node; + u32 highest_slave; +}; + + +extern struct node **local_nodes; +extern u32 highest_allowed_slave; +extern struct node_map cluster_bcast_nodes; + +void cluster_remove_as_router(struct cluster *c_ptr, u32 router); +void cluster_send_ext_routes(struct cluster *c_ptr, u32 dest); +struct node *cluster_select_node(struct cluster *c_ptr, u32 selector); +u32 cluster_select_router(struct cluster *c_ptr, u32 ref); +void cluster_recv_routing_table(struct sk_buff *buf); +struct cluster *cluster_create(u32 addr); +void cluster_delete(struct cluster *c_ptr); +void cluster_attach_node(struct cluster *c_ptr, struct node *n_ptr); +void cluster_send_slave_routes(struct cluster *c_ptr, u32 dest); +void cluster_broadcast(struct sk_buff *buf); +int cluster_init(void); +u32 cluster_next_node(struct cluster *c_ptr, u32 addr); +void cluster_bcast_new_route(struct cluster *c_ptr, u32 dest, u32 lo, u32 hi); +void cluster_send_local_routes(struct cluster *c_ptr, u32 dest); +void cluster_bcast_lost_route(struct cluster *c_ptr, u32 dest, u32 lo, u32 hi); + +static inline struct cluster *cluster_find(u32 addr) +{ + struct _zone *z_ptr = zone_find(addr); + + if (z_ptr) + return z_ptr->clusters[1]; + return 0; +} + +#endif diff --git a/net/tipc/config.c b/net/tipc/config.c new file mode 100644 index 00000000000..0f31c342d11 --- /dev/null +++ b/net/tipc/config.c @@ -0,0 +1,715 @@ +/* + * net/tipc/config.c: TIPC configuration management code + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2004-2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "core.h" +#include "dbg.h" +#include "bearer.h" +#include "port.h" +#include "link.h" +#include "zone.h" +#include "addr.h" +#include "name_table.h" +#include "node.h" +#include "config.h" +#include "discover.h" + +struct subscr_data { + char usr_handle[8]; + u32 domain; + u32 port_ref; + struct list_head subd_list; +}; + +struct manager { + u32 user_ref; + u32 port_ref; + u32 subscr_ref; + u32 link_subscriptions; + struct list_head link_subscribers; +}; + +static struct manager mng = { 0}; + +static spinlock_t config_lock = SPIN_LOCK_UNLOCKED; + +static const void *req_tlv_area; /* request message TLV area */ +static int req_tlv_space; /* request message TLV area size */ +static int rep_headroom; /* reply message headroom to use */ + + +void cfg_link_event(u32 addr, char *name, int up) +{ + /* TIPC DOESN'T HANDLE LINK EVENT SUBSCRIPTIONS AT THE MOMENT */ +} + + +struct sk_buff *cfg_reply_alloc(int payload_size) +{ + struct sk_buff *buf; + + buf = alloc_skb(rep_headroom + payload_size, GFP_ATOMIC); + if (buf) + skb_reserve(buf, rep_headroom); + return buf; +} + +int cfg_append_tlv(struct sk_buff *buf, int tlv_type, + void *tlv_data, int tlv_data_size) +{ + struct tlv_desc *tlv = (struct tlv_desc *)buf->tail; + int new_tlv_space = TLV_SPACE(tlv_data_size); + + if (skb_tailroom(buf) < new_tlv_space) { + dbg("cfg_append_tlv unable to append TLV\n"); + return 0; + } + skb_put(buf, new_tlv_space); + tlv->tlv_type = htons(tlv_type); + tlv->tlv_len = htons(TLV_LENGTH(tlv_data_size)); + if (tlv_data_size && tlv_data) + memcpy(TLV_DATA(tlv), tlv_data, tlv_data_size); + return 1; +} + +struct sk_buff *cfg_reply_unsigned_type(u16 tlv_type, u32 value) +{ + struct sk_buff *buf; + u32 value_net; + + buf = cfg_reply_alloc(TLV_SPACE(sizeof(value))); + if (buf) { + value_net = htonl(value); + cfg_append_tlv(buf, tlv_type, &value_net, + sizeof(value_net)); + } + return buf; +} + +struct sk_buff *cfg_reply_string_type(u16 tlv_type, char *string) +{ + struct sk_buff *buf; + int string_len = strlen(string) + 1; + + buf = cfg_reply_alloc(TLV_SPACE(string_len)); + if (buf) + cfg_append_tlv(buf, tlv_type, string, string_len); + return buf; +} + + + + +#if 0 + +/* Now obsolete code for handling commands not yet implemented the new way */ + +int tipc_cfg_cmd(const struct tipc_cmd_msg * msg, + char *data, + u32 sz, + u32 *ret_size, + struct tipc_portid *orig) +{ + int rv = -EINVAL; + u32 cmd = msg->cmd; + + *ret_size = 0; + switch (cmd) { + case TIPC_REMOVE_LINK: + case TIPC_CMD_BLOCK_LINK: + case TIPC_CMD_UNBLOCK_LINK: + if (!cfg_check_connection(orig)) + rv = link_control(msg->argv.link_name, msg->cmd, 0); + break; + case TIPC_ESTABLISH: + { + int connected; + + tipc_isconnected(mng.conn_port_ref, &connected); + if (connected || !orig) { + rv = TIPC_FAILURE; + break; + } + rv = tipc_connect2port(mng.conn_port_ref, orig); + if (rv == TIPC_OK) + orig = 0; + break; + } + case TIPC_GET_PEER_ADDRESS: + *ret_size = link_peer_addr(msg->argv.link_name, data, sz); + break; + case TIPC_GET_ROUTES: + rv = TIPC_OK; + break; + default: {} + } + if (*ret_size) + rv = TIPC_OK; + return rv; +} + +static void cfg_cmd_event(struct tipc_cmd_msg *msg, + char *data, + u32 sz, + struct tipc_portid const *orig) +{ + int rv = -EINVAL; + struct tipc_cmd_result_msg rmsg; + struct iovec msg_sect[2]; + int *arg; + + msg->cmd = ntohl(msg->cmd); + + cfg_prepare_res_msg(msg->cmd, msg->usr_handle, rv, &rmsg, msg_sect, + data, 0); + if (ntohl(msg->magic) != TIPC_MAGIC) + goto exit; + + switch (msg->cmd) { + case TIPC_CREATE_LINK: + if (!cfg_check_connection(orig)) + rv = disc_create_link(&msg->argv.create_link); + break; + case TIPC_LINK_SUBSCRIBE: + { + struct subscr_data *sub; + + if (mng.link_subscriptions > 64) + break; + sub = (struct subscr_data *)kmalloc(sizeof(*sub), + GFP_ATOMIC); + if (sub == NULL) { + warn("Memory squeeze; dropped remote link subscription\n"); + break; + } + INIT_LIST_HEAD(&sub->subd_list); + tipc_createport(mng.user_ref, + (void *)sub, + TIPC_HIGH_IMPORTANCE, + 0, + 0, + (tipc_conn_shutdown_event)cfg_linksubscr_cancel, + 0, + 0, + (tipc_conn_msg_event)cfg_linksubscr_cancel, + 0, + &sub->port_ref); + if (!sub->port_ref) { + kfree(sub); + break; + } + memcpy(sub->usr_handle,msg->usr_handle, + sizeof(sub->usr_handle)); + sub->domain = msg->argv.domain; + list_add_tail(&sub->subd_list, &mng.link_subscribers); + tipc_connect2port(sub->port_ref, orig); + rmsg.retval = TIPC_OK; + tipc_send(sub->port_ref, 2u, msg_sect); + mng.link_subscriptions++; + return; + } + default: + rv = tipc_cfg_cmd(msg, data, sz, (u32 *)&msg_sect[1].iov_len, orig); + } + exit: + rmsg.result_len = htonl(msg_sect[1].iov_len); + rmsg.retval = htonl(rv); + cfg_respond(msg_sect, 2u, orig); +} +#endif + +static struct sk_buff *cfg_enable_bearer(void) +{ + struct tipc_bearer_config *args; + + if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_CONFIG)) + return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + + args = (struct tipc_bearer_config *)TLV_DATA(req_tlv_area); + if (tipc_enable_bearer(args->name, + ntohl(args->detect_scope), + ntohl(args->priority))) + return cfg_reply_error_string("unable to enable bearer"); + + return cfg_reply_none(); +} + +static struct sk_buff *cfg_disable_bearer(void) +{ + if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_NAME)) + return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + + if (tipc_disable_bearer((char *)TLV_DATA(req_tlv_area))) + return cfg_reply_error_string("unable to disable bearer"); + + return cfg_reply_none(); +} + +static struct sk_buff *cfg_set_own_addr(void) +{ + u32 addr; + + if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) + return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + + addr = *(u32 *)TLV_DATA(req_tlv_area); + addr = ntohl(addr); + if (addr == tipc_own_addr) + return cfg_reply_none(); + if (!addr_node_valid(addr)) + return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE + " (node address)"); + if (tipc_own_addr) + return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED + " (cannot change node address once assigned)"); + + spin_unlock_bh(&config_lock); + stop_net(); + tipc_own_addr = addr; + start_net(); + spin_lock_bh(&config_lock); + return cfg_reply_none(); +} + +static struct sk_buff *cfg_set_remote_mng(void) +{ + u32 value; + + if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) + return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + + value = *(u32 *)TLV_DATA(req_tlv_area); + value = ntohl(value); + tipc_remote_management = (value != 0); + return cfg_reply_none(); +} + +static struct sk_buff *cfg_set_max_publications(void) +{ + u32 value; + + if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) + return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + + value = *(u32 *)TLV_DATA(req_tlv_area); + value = ntohl(value); + if (value != delimit(value, 1, 65535)) + return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE + " (max publications must be 1-65535)"); + tipc_max_publications = value; + return cfg_reply_none(); +} + +static struct sk_buff *cfg_set_max_subscriptions(void) +{ + u32 value; + + if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) + return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + + value = *(u32 *)TLV_DATA(req_tlv_area); + value = ntohl(value); + if (value != delimit(value, 1, 65535)) + return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE + " (max subscriptions must be 1-65535"); + tipc_max_subscriptions = value; + return cfg_reply_none(); +} + +static struct sk_buff *cfg_set_max_ports(void) +{ + int orig_mode; + u32 value; + + if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) + return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + value = *(u32 *)TLV_DATA(req_tlv_area); + value = ntohl(value); + if (value != delimit(value, 127, 65535)) + return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE + " (max ports must be 127-65535)"); + + if (value == tipc_max_ports) + return cfg_reply_none(); + + if (atomic_read(&tipc_user_count) > 2) + return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED + " (cannot change max ports while TIPC users exist)"); + + spin_unlock_bh(&config_lock); + orig_mode = tipc_get_mode(); + if (orig_mode == TIPC_NET_MODE) + stop_net(); + stop_core(); + tipc_max_ports = value; + start_core(); + if (orig_mode == TIPC_NET_MODE) + start_net(); + spin_lock_bh(&config_lock); + return cfg_reply_none(); +} + +static struct sk_buff *set_net_max(int value, int *parameter) +{ + int orig_mode; + + if (value != *parameter) { + orig_mode = tipc_get_mode(); + if (orig_mode == TIPC_NET_MODE) + stop_net(); + *parameter = value; + if (orig_mode == TIPC_NET_MODE) + start_net(); + } + + return cfg_reply_none(); +} + +static struct sk_buff *cfg_set_max_zones(void) +{ + u32 value; + + if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) + return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + value = *(u32 *)TLV_DATA(req_tlv_area); + value = ntohl(value); + if (value != delimit(value, 1, 255)) + return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE + " (max zones must be 1-255)"); + return set_net_max(value, &tipc_max_zones); +} + +static struct sk_buff *cfg_set_max_clusters(void) +{ + u32 value; + + if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) + return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + value = *(u32 *)TLV_DATA(req_tlv_area); + value = ntohl(value); + if (value != 1) + return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED + " (max clusters fixed at 1)"); + return cfg_reply_none(); +} + +static struct sk_buff *cfg_set_max_nodes(void) +{ + u32 value; + + if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) + return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + value = *(u32 *)TLV_DATA(req_tlv_area); + value = ntohl(value); + if (value != delimit(value, 8, 2047)) + return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE + " (max nodes must be 8-2047)"); + return set_net_max(value, &tipc_max_nodes); +} + +static struct sk_buff *cfg_set_max_slaves(void) +{ + u32 value; + + if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) + return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + value = *(u32 *)TLV_DATA(req_tlv_area); + value = ntohl(value); + if (value != 0) + return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED + " (max secondary nodes fixed at 0)"); + return cfg_reply_none(); +} + +static struct sk_buff *cfg_set_netid(void) +{ + u32 value; + + if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) + return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + value = *(u32 *)TLV_DATA(req_tlv_area); + value = ntohl(value); + if (value != delimit(value, 1, 9999)) + return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE + " (network id must be 1-9999)"); + + if (tipc_own_addr) + return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED + " (cannot change network id once part of network)"); + + return set_net_max(value, &tipc_net_id); +} + +struct sk_buff *cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area, + int request_space, int reply_headroom) +{ + struct sk_buff *rep_tlv_buf; + + spin_lock_bh(&config_lock); + + /* Save request and reply details in a well-known location */ + + req_tlv_area = request_area; + req_tlv_space = request_space; + rep_headroom = reply_headroom; + + /* Check command authorization */ + + if (likely(orig_node == tipc_own_addr)) { + /* command is permitted */ + } else if (cmd >= 0x8000) { + rep_tlv_buf = cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED + " (cannot be done remotely)"); + goto exit; + } else if (!tipc_remote_management) { + rep_tlv_buf = cfg_reply_error_string(TIPC_CFG_NO_REMOTE); + goto exit; + } + else if (cmd >= 0x4000) { + u32 domain = 0; + + if ((nametbl_translate(TIPC_ZM_SRV, 0, &domain) == 0) || + (domain != orig_node)) { + rep_tlv_buf = cfg_reply_error_string(TIPC_CFG_NOT_ZONE_MSTR); + goto exit; + } + } + + /* Call appropriate processing routine */ + + switch (cmd) { + case TIPC_CMD_NOOP: + rep_tlv_buf = cfg_reply_none(); + break; + case TIPC_CMD_GET_NODES: + rep_tlv_buf = node_get_nodes(req_tlv_area, req_tlv_space); + break; + case TIPC_CMD_GET_LINKS: + rep_tlv_buf = node_get_links(req_tlv_area, req_tlv_space); + break; + case TIPC_CMD_SHOW_LINK_STATS: + rep_tlv_buf = link_cmd_show_stats(req_tlv_area, req_tlv_space); + break; + case TIPC_CMD_RESET_LINK_STATS: + rep_tlv_buf = link_cmd_reset_stats(req_tlv_area, req_tlv_space); + break; + case TIPC_CMD_SHOW_NAME_TABLE: + rep_tlv_buf = nametbl_get(req_tlv_area, req_tlv_space); + break; + case TIPC_CMD_GET_BEARER_NAMES: + rep_tlv_buf = bearer_get_names(); + break; + case TIPC_CMD_GET_MEDIA_NAMES: + rep_tlv_buf = media_get_names(); + break; + case TIPC_CMD_SHOW_PORTS: + rep_tlv_buf = port_get_ports(); + break; +#if 0 + case TIPC_CMD_SHOW_PORT_STATS: + rep_tlv_buf = port_show_stats(req_tlv_area, req_tlv_space); + break; + case TIPC_CMD_RESET_PORT_STATS: + rep_tlv_buf = cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED); + break; +#endif + case TIPC_CMD_SET_LOG_SIZE: + rep_tlv_buf = log_resize(req_tlv_area, req_tlv_space); + break; + case TIPC_CMD_DUMP_LOG: + rep_tlv_buf = log_dump(); + break; + case TIPC_CMD_SET_LINK_TOL: + case TIPC_CMD_SET_LINK_PRI: + case TIPC_CMD_SET_LINK_WINDOW: + rep_tlv_buf = link_cmd_config(req_tlv_area, req_tlv_space, cmd); + break; + case TIPC_CMD_ENABLE_BEARER: + rep_tlv_buf = cfg_enable_bearer(); + break; + case TIPC_CMD_DISABLE_BEARER: + rep_tlv_buf = cfg_disable_bearer(); + break; + case TIPC_CMD_SET_NODE_ADDR: + rep_tlv_buf = cfg_set_own_addr(); + break; + case TIPC_CMD_SET_REMOTE_MNG: + rep_tlv_buf = cfg_set_remote_mng(); + break; + case TIPC_CMD_SET_MAX_PORTS: + rep_tlv_buf = cfg_set_max_ports(); + break; + case TIPC_CMD_SET_MAX_PUBL: + rep_tlv_buf = cfg_set_max_publications(); + break; + case TIPC_CMD_SET_MAX_SUBSCR: + rep_tlv_buf = cfg_set_max_subscriptions(); + break; + case TIPC_CMD_SET_MAX_ZONES: + rep_tlv_buf = cfg_set_max_zones(); + break; + case TIPC_CMD_SET_MAX_CLUSTERS: + rep_tlv_buf = cfg_set_max_clusters(); + break; + case TIPC_CMD_SET_MAX_NODES: + rep_tlv_buf = cfg_set_max_nodes(); + break; + case TIPC_CMD_SET_MAX_SLAVES: + rep_tlv_buf = cfg_set_max_slaves(); + break; + case TIPC_CMD_SET_NETID: + rep_tlv_buf = cfg_set_netid(); + break; + case TIPC_CMD_GET_REMOTE_MNG: + rep_tlv_buf = cfg_reply_unsigned(tipc_remote_management); + break; + case TIPC_CMD_GET_MAX_PORTS: + rep_tlv_buf = cfg_reply_unsigned(tipc_max_ports); + break; + case TIPC_CMD_GET_MAX_PUBL: + rep_tlv_buf = cfg_reply_unsigned(tipc_max_publications); + break; + case TIPC_CMD_GET_MAX_SUBSCR: + rep_tlv_buf = cfg_reply_unsigned(tipc_max_subscriptions); + break; + case TIPC_CMD_GET_MAX_ZONES: + rep_tlv_buf = cfg_reply_unsigned(tipc_max_zones); + break; + case TIPC_CMD_GET_MAX_CLUSTERS: + rep_tlv_buf = cfg_reply_unsigned(tipc_max_clusters); + break; + case TIPC_CMD_GET_MAX_NODES: + rep_tlv_buf = cfg_reply_unsigned(tipc_max_nodes); + break; + case TIPC_CMD_GET_MAX_SLAVES: + rep_tlv_buf = cfg_reply_unsigned(tipc_max_slaves); + break; + case TIPC_CMD_GET_NETID: + rep_tlv_buf = cfg_reply_unsigned(tipc_net_id); + break; + default: + rep_tlv_buf = NULL; + break; + } + + /* Return reply buffer */ +exit: + spin_unlock_bh(&config_lock); + return rep_tlv_buf; +} + +static void cfg_named_msg_event(void *userdata, + u32 port_ref, + struct sk_buff **buf, + const unchar *msg, + u32 size, + u32 importance, + struct tipc_portid const *orig, + struct tipc_name_seq const *dest) +{ + struct tipc_cfg_msg_hdr *req_hdr; + struct tipc_cfg_msg_hdr *rep_hdr; + struct sk_buff *rep_buf; + + /* Validate configuration message header (ignore invalid message) */ + + req_hdr = (struct tipc_cfg_msg_hdr *)msg; + if ((size < sizeof(*req_hdr)) || + (size != TCM_ALIGN(ntohl(req_hdr->tcm_len))) || + (ntohs(req_hdr->tcm_flags) != TCM_F_REQUEST)) { + warn("discarded invalid configuration message\n"); + return; + } + + /* Generate reply for request (if can't, return request) */ + + rep_buf = cfg_do_cmd(orig->node, + ntohs(req_hdr->tcm_type), + msg + sizeof(*req_hdr), + size - sizeof(*req_hdr), + BUF_HEADROOM + MAX_H_SIZE + sizeof(*rep_hdr)); + if (rep_buf) { + skb_push(rep_buf, sizeof(*rep_hdr)); + rep_hdr = (struct tipc_cfg_msg_hdr *)rep_buf->data; + memcpy(rep_hdr, req_hdr, sizeof(*rep_hdr)); + rep_hdr->tcm_len = htonl(rep_buf->len); + rep_hdr->tcm_flags &= htons(~TCM_F_REQUEST); + } else { + rep_buf = *buf; + *buf = NULL; + } + + /* NEED TO ADD CODE TO HANDLE FAILED SEND (SUCH AS CONGESTION) */ + tipc_send_buf2port(port_ref, orig, rep_buf, rep_buf->len); +} + +int cfg_init(void) +{ + struct tipc_name_seq seq; + int res; + + memset(&mng, 0, sizeof(mng)); + INIT_LIST_HEAD(&mng.link_subscribers); + + res = tipc_attach(&mng.user_ref, 0, 0); + if (res) + goto failed; + + res = tipc_createport(mng.user_ref, 0, TIPC_CRITICAL_IMPORTANCE, + NULL, NULL, NULL, + NULL, cfg_named_msg_event, NULL, + NULL, &mng.port_ref); + if (res) + goto failed; + + seq.type = TIPC_CFG_SRV; + seq.lower = seq.upper = tipc_own_addr; + res = nametbl_publish_rsv(mng.port_ref, TIPC_ZONE_SCOPE, &seq); + if (res) + goto failed; + + return 0; + +failed: + err("Unable to create configuration service\n"); + tipc_detach(mng.user_ref); + mng.user_ref = 0; + return res; +} + +void cfg_stop(void) +{ + if (mng.user_ref) { + tipc_detach(mng.user_ref); + mng.user_ref = 0; + } +} diff --git a/net/tipc/config.h b/net/tipc/config.h new file mode 100644 index 00000000000..7ac0af57bf5 --- /dev/null +++ b/net/tipc/config.h @@ -0,0 +1,76 @@ +/* + * net/tipc/config.h: Include file for TIPC configuration service code + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _TIPC_CONFIG_H +#define _TIPC_CONFIG_H + +/* ---------------------------------------------------------------------- */ + +#include +#include "link.h" + +struct sk_buff *cfg_reply_alloc(int payload_size); +int cfg_append_tlv(struct sk_buff *buf, int tlv_type, + void *tlv_data, int tlv_data_size); +struct sk_buff *cfg_reply_unsigned_type(u16 tlv_type, u32 value); +struct sk_buff *cfg_reply_string_type(u16 tlv_type, char *string); + +static inline struct sk_buff *cfg_reply_none(void) +{ + return cfg_reply_alloc(0); +} + +static inline struct sk_buff *cfg_reply_unsigned(u32 value) +{ + return cfg_reply_unsigned_type(TIPC_TLV_UNSIGNED, value); +} + +static inline struct sk_buff *cfg_reply_error_string(char *string) +{ + return cfg_reply_string_type(TIPC_TLV_ERROR_STRING, string); +} + +static inline struct sk_buff *cfg_reply_ultra_string(char *string) +{ + return cfg_reply_string_type(TIPC_TLV_ULTRA_STRING, string); +} + +struct sk_buff *cfg_do_cmd(u32 orig_node, u16 cmd, + const void *req_tlv_area, int req_tlv_space, + int headroom); + +void cfg_link_event(u32 addr, char *name, int up); +int cfg_init(void); +void cfg_stop(void); + +#endif diff --git a/net/tipc/core.c b/net/tipc/core.c new file mode 100644 index 00000000000..17c723f4918 --- /dev/null +++ b/net/tipc/core.c @@ -0,0 +1,282 @@ +/* + * net/tipc/core.c: TIPC module code + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +#include "core.h" +#include "dbg.h" +#include "ref.h" +#include "net.h" +#include "user_reg.h" +#include "name_table.h" +#include "subscr.h" +#include "config.h" + +int eth_media_start(void); +void eth_media_stop(void); +int handler_start(void); +void handler_stop(void); +int socket_init(void); +void socket_stop(void); +int netlink_start(void); +void netlink_stop(void); + +#define MOD_NAME "tipc_start: " + +#ifndef CONFIG_TIPC_ZONES +#define CONFIG_TIPC_ZONES 3 +#endif + +#ifndef CONFIG_TIPC_CLUSTERS +#define CONFIG_TIPC_CLUSTERS 1 +#endif + +#ifndef CONFIG_TIPC_NODES +#define CONFIG_TIPC_NODES 255 +#endif + +#ifndef CONFIG_TIPC_SLAVE_NODES +#define CONFIG_TIPC_SLAVE_NODES 0 +#endif + +#ifndef CONFIG_TIPC_PORTS +#define CONFIG_TIPC_PORTS 8191 +#endif + +#ifndef CONFIG_TIPC_LOG +#define CONFIG_TIPC_LOG 0 +#endif + +/* global variables used by multiple sub-systems within TIPC */ + +int tipc_mode = TIPC_NOT_RUNNING; +int tipc_random; +atomic_t tipc_user_count = ATOMIC_INIT(0); + +const char tipc_alphabet[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"; + +/* configurable TIPC parameters */ + +u32 tipc_own_addr; +int tipc_max_zones; +int tipc_max_clusters; +int tipc_max_nodes; +int tipc_max_slaves; +int tipc_max_ports; +int tipc_max_subscriptions; +int tipc_max_publications; +int tipc_net_id; +int tipc_remote_management; + + +int tipc_get_mode(void) +{ + return tipc_mode; +} + +/** + * stop_net - shut down TIPC networking sub-systems + */ + +void stop_net(void) +{ + eth_media_stop(); + tipc_stop_net(); +} + +/** + * start_net - start TIPC networking sub-systems + */ + +int start_net(void) +{ + int res; + + if ((res = tipc_start_net()) || + (res = eth_media_start())) { + stop_net(); + } + return res; +} + +/** + * stop_core - switch TIPC from SINGLE NODE to NOT RUNNING mode + */ + +void stop_core(void) +{ + if (tipc_mode != TIPC_NODE_MODE) + return; + + tipc_mode = TIPC_NOT_RUNNING; + + netlink_stop(); + handler_stop(); + cfg_stop(); + subscr_stop(); + reg_stop(); + nametbl_stop(); + ref_table_stop(); + socket_stop(); +} + +/** + * start_core - switch TIPC from NOT RUNNING to SINGLE NODE mode + */ + +int start_core(void) +{ + int res; + + if (tipc_mode != TIPC_NOT_RUNNING) + return -ENOPROTOOPT; + + get_random_bytes(&tipc_random, sizeof(tipc_random)); + tipc_mode = TIPC_NODE_MODE; + + if ((res = handler_start()) || + (res = ref_table_init(tipc_max_ports + tipc_max_subscriptions, + tipc_random)) || + (res = reg_start()) || + (res = nametbl_init()) || + (res = k_signal((Handler)subscr_start, 0)) || + (res = k_signal((Handler)cfg_init, 0)) || + (res = netlink_start()) || + (res = socket_init())) { + stop_core(); + } + return res; +} + + +static int __init tipc_init(void) +{ + int res; + + log_reinit(CONFIG_TIPC_LOG); + info("Activated (compiled " __DATE__ " " __TIME__ ")\n"); + + tipc_own_addr = 0; + tipc_remote_management = 1; + tipc_max_publications = 10000; + tipc_max_subscriptions = 2000; + tipc_max_ports = delimit(CONFIG_TIPC_PORTS, 127, 65536); + tipc_max_zones = delimit(CONFIG_TIPC_ZONES, 1, 511); + tipc_max_clusters = delimit(CONFIG_TIPC_CLUSTERS, 1, 1); + tipc_max_nodes = delimit(CONFIG_TIPC_NODES, 8, 2047); + tipc_max_slaves = delimit(CONFIG_TIPC_SLAVE_NODES, 0, 2047); + tipc_net_id = 4711; + + if ((res = start_core())) + err("Unable to start in single node mode\n"); + else + info("Started in single node mode\n"); + return res; +} + +static void __exit tipc_exit(void) +{ + stop_net(); + stop_core(); + info("Deactivated\n"); + log_stop(); +} + +module_init(tipc_init); +module_exit(tipc_exit); + +MODULE_DESCRIPTION("TIPC: Transparent Inter Process Communication"); +MODULE_LICENSE("Dual BSD/GPL"); + +/* Native TIPC API for kernel-space applications (see tipc.h) */ + +EXPORT_SYMBOL(tipc_attach); +EXPORT_SYMBOL(tipc_detach); +EXPORT_SYMBOL(tipc_get_addr); +EXPORT_SYMBOL(tipc_get_mode); +EXPORT_SYMBOL(tipc_createport); +EXPORT_SYMBOL(tipc_deleteport); +EXPORT_SYMBOL(tipc_ownidentity); +EXPORT_SYMBOL(tipc_portimportance); +EXPORT_SYMBOL(tipc_set_portimportance); +EXPORT_SYMBOL(tipc_portunreliable); +EXPORT_SYMBOL(tipc_set_portunreliable); +EXPORT_SYMBOL(tipc_portunreturnable); +EXPORT_SYMBOL(tipc_set_portunreturnable); +EXPORT_SYMBOL(tipc_publish); +EXPORT_SYMBOL(tipc_withdraw); +EXPORT_SYMBOL(tipc_connect2port); +EXPORT_SYMBOL(tipc_disconnect); +EXPORT_SYMBOL(tipc_shutdown); +EXPORT_SYMBOL(tipc_isconnected); +EXPORT_SYMBOL(tipc_peer); +EXPORT_SYMBOL(tipc_ref_valid); +EXPORT_SYMBOL(tipc_send); +EXPORT_SYMBOL(tipc_send_buf); +EXPORT_SYMBOL(tipc_send2name); +EXPORT_SYMBOL(tipc_forward2name); +EXPORT_SYMBOL(tipc_send_buf2name); +EXPORT_SYMBOL(tipc_forward_buf2name); +EXPORT_SYMBOL(tipc_send2port); +EXPORT_SYMBOL(tipc_forward2port); +EXPORT_SYMBOL(tipc_send_buf2port); +EXPORT_SYMBOL(tipc_forward_buf2port); +EXPORT_SYMBOL(tipc_multicast); +/* EXPORT_SYMBOL(tipc_multicast_buf); not available yet */ +EXPORT_SYMBOL(tipc_ispublished); +EXPORT_SYMBOL(tipc_available_nodes); + +/* TIPC API for external bearers (see tipc_bearer.h) */ + +EXPORT_SYMBOL(tipc_block_bearer); +EXPORT_SYMBOL(tipc_continue); +EXPORT_SYMBOL(tipc_disable_bearer); +EXPORT_SYMBOL(tipc_enable_bearer); +EXPORT_SYMBOL(tipc_recv_msg); +EXPORT_SYMBOL(tipc_register_media); + +/* TIPC API for external APIs (see tipc_port.h) */ + +EXPORT_SYMBOL(tipc_createport_raw); +EXPORT_SYMBOL(tipc_set_msg_option); +EXPORT_SYMBOL(tipc_reject_msg); +EXPORT_SYMBOL(tipc_send_buf_fast); +EXPORT_SYMBOL(tipc_acknowledge); +EXPORT_SYMBOL(tipc_get_port); +EXPORT_SYMBOL(tipc_get_handle); + diff --git a/net/tipc/core.h b/net/tipc/core.h new file mode 100644 index 00000000000..d92898d6c09 --- /dev/null +++ b/net/tipc/core.h @@ -0,0 +1,313 @@ +/* + * net/tipc/core.h: Include file for TIPC global declarations + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _TIPC_CORE_H +#define _TIPC_CORE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * TIPC debugging code + */ + +#define assert(i) BUG_ON(!(i)) + +struct tipc_msg; +extern struct print_buf *CONS, *LOG; +extern struct print_buf *TEE(struct print_buf *, struct print_buf *); +void msg_print(struct print_buf*,struct tipc_msg *,const char*); +void tipc_printf(struct print_buf *, const char *fmt, ...); +void tipc_dump(struct print_buf*,const char *fmt, ...); + +#ifdef CONFIG_TIPC_DEBUG + +/* + * TIPC debug support included: + * - system messages are printed to TIPC_OUTPUT print buffer + * - debug messages are printed to DBG_OUTPUT print buffer + */ + +#define err(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_ERR "TIPC: " fmt, ## arg) +#define warn(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_WARNING "TIPC: " fmt, ## arg) +#define info(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_NOTICE "TIPC: " fmt, ## arg) + +#define dbg(fmt, arg...) do {if (DBG_OUTPUT) tipc_printf(DBG_OUTPUT, fmt, ## arg);} while(0) +#define msg_dbg(msg, txt) do {if (DBG_OUTPUT) msg_print(DBG_OUTPUT, msg, txt);} while(0) +#define dump(fmt, arg...) do {if (DBG_OUTPUT) tipc_dump(DBG_OUTPUT, fmt, ##arg);} while(0) + + +/* + * By default, TIPC_OUTPUT is defined to be system console and TIPC log buffer, + * while DBG_OUTPUT is the null print buffer. These defaults can be changed + * here, or on a per .c file basis, by redefining these symbols. The following + * print buffer options are available: + * + * NULL : Output to null print buffer (i.e. print nowhere) + * CONS : Output to system console + * LOG : Output to TIPC log buffer + * &buf : Output to user-defined buffer (struct print_buf *) + * TEE(&buf_a,&buf_b) : Output to two print buffers (eg. TEE(CONS,LOG) ) + */ + +#ifndef TIPC_OUTPUT +#define TIPC_OUTPUT TEE(CONS,LOG) +#endif + +#ifndef DBG_OUTPUT +#define DBG_OUTPUT NULL +#endif + +#else + +#ifndef DBG_OUTPUT +#define DBG_OUTPUT NULL +#endif + +/* + * TIPC debug support not included: + * - system messages are printed to system console + * - debug messages are not printed + */ + +#define err(fmt, arg...) printk(KERN_ERR "%s: " fmt "\n" , __FILE__ , ## arg) +#define info(fmt, arg...) printk(KERN_INFO "%s: " fmt "\n" , __FILE__ , ## arg) +#define warn(fmt, arg...) printk(KERN_WARNING "%s: " fmt "\n" , __FILE__ , ## arg) + +#define dbg(fmt, arg...) do {} while (0) +#define msg_dbg(msg,txt) do {} while (0) +#define dump(fmt,arg...) do {} while (0) + +#endif + + +/* + * TIPC-specific error codes + */ + +#define ELINKCONG EAGAIN /* link congestion <=> resource unavailable */ + +/* + * Global configuration variables + */ + +extern u32 tipc_own_addr; +extern int tipc_max_zones; +extern int tipc_max_clusters; +extern int tipc_max_nodes; +extern int tipc_max_slaves; +extern int tipc_max_ports; +extern int tipc_max_subscriptions; +extern int tipc_max_publications; +extern int tipc_net_id; +extern int tipc_remote_management; + +/* + * Other global variables + */ + +extern int tipc_mode; +extern int tipc_random; +extern const char tipc_alphabet[]; +extern atomic_t tipc_user_count; + + +/* + * Routines available to privileged subsystems + */ + +extern int start_core(void); +extern void stop_core(void); +extern int start_net(void); +extern void stop_net(void); + +static inline int delimit(int val, int min, int max) +{ + if (val > max) + return max; + if (val < min) + return min; + return val; +} + + +/* + * TIPC timer and signal code + */ + +typedef void (*Handler) (unsigned long); + +u32 k_signal(Handler routine, unsigned long argument); + +/** + * k_init_timer - initialize a timer + * @timer: pointer to timer structure + * @routine: pointer to routine to invoke when timer expires + * @argument: value to pass to routine when timer expires + * + * Timer must be initialized before use (and terminated when no longer needed). + */ + +static inline void k_init_timer(struct timer_list *timer, Handler routine, + unsigned long argument) +{ + dbg("initializing timer %p\n", timer); + init_timer(timer); + timer->function = routine; + timer->data = argument; +} + +/** + * k_start_timer - start a timer + * @timer: pointer to timer structure + * @msec: time to delay (in ms) + * + * Schedules a previously initialized timer for later execution. + * If timer is already running, the new timeout overrides the previous request. + * + * To ensure the timer doesn't expire before the specified delay elapses, + * the amount of delay is rounded up when converting to the jiffies + * then an additional jiffy is added to account for the fact that + * the starting time may be in the middle of the current jiffy. + */ + +static inline void k_start_timer(struct timer_list *timer, unsigned long msec) +{ + dbg("starting timer %p for %u\n", timer, msec); + mod_timer(timer, jiffies + msecs_to_jiffies(msec) + 1); +} + +/** + * k_cancel_timer - cancel a timer + * @timer: pointer to timer structure + * + * Cancels a previously initialized timer. + * Can be called safely even if the timer is already inactive. + * + * WARNING: Must not be called when holding locks required by the timer's + * timeout routine, otherwise deadlock can occur on SMP systems! + */ + +static inline void k_cancel_timer(struct timer_list *timer) +{ + dbg("cancelling timer %p\n", timer); + del_timer_sync(timer); +} + +/** + * k_term_timer - terminate a timer + * @timer: pointer to timer structure + * + * Prevents further use of a previously initialized timer. + * + * WARNING: Caller must ensure timer isn't currently running. + * + * (Do not "enhance" this routine to automatically cancel an active timer, + * otherwise deadlock can arise when a timeout routine calls k_term_timer.) + */ + +static inline void k_term_timer(struct timer_list *timer) +{ + dbg("terminating timer %p\n", timer); +} + + +/* + * TIPC message buffer code + * + * TIPC message buffer headroom leaves room for 14 byte Ethernet header, + * while ensuring TIPC header is word aligned for quicker access + */ + +#define BUF_HEADROOM 16u + +struct tipc_skb_cb { + void *handle; +}; + +#define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0])) + + +static inline struct tipc_msg *buf_msg(struct sk_buff *skb) +{ + return (struct tipc_msg *)skb->data; +} + +/** + * buf_acquire - creates a TIPC message buffer + * @size: message size (including TIPC header) + * + * Returns a new buffer. Space is reserved for a data link header. + */ + +static inline struct sk_buff *buf_acquire(u32 size) +{ + struct sk_buff *skb; + unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u; + + skb = alloc_skb(buf_size, GFP_ATOMIC); + if (skb) { + skb_reserve(skb, BUF_HEADROOM); + skb_put(skb, size); + skb->next = NULL; + } + return skb; +} + +/** + * buf_discard - frees a TIPC message buffer + * @skb: message buffer + * + * Frees a new buffer. If passed NULL, just returns. + */ + +static inline void buf_discard(struct sk_buff *skb) +{ + if (likely(skb != NULL)) + kfree_skb(skb); +} + +#endif diff --git a/net/tipc/dbg.c b/net/tipc/dbg.c new file mode 100644 index 00000000000..efd6d652d05 --- /dev/null +++ b/net/tipc/dbg.c @@ -0,0 +1,392 @@ +/* + * net/tipc/dbg.c: TIPC print buffer routines for debuggign + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "core.h" +#include "config.h" +#include "dbg.h" + +#define MAX_STRING 512 + +static char print_string[MAX_STRING]; +static spinlock_t print_lock = SPIN_LOCK_UNLOCKED; + +static struct print_buf cons_buf = { NULL, 0, NULL, NULL }; +struct print_buf *CONS = &cons_buf; + +static struct print_buf log_buf = { NULL, 0, NULL, NULL }; +struct print_buf *LOG = &log_buf; + + +#define FORMAT(PTR,LEN,FMT) \ +{\ + va_list args;\ + va_start(args, FMT);\ + LEN = vsprintf(PTR, FMT, args);\ + va_end(args);\ + *(PTR + LEN) = '\0';\ +} + +/* + * Locking policy when using print buffers. + * + * 1) Routines of the form printbuf_XXX() rely on the caller to prevent + * simultaneous use of the print buffer(s) being manipulated. + * 2) tipc_printf() uses 'print_lock' to prevent simultaneous use of + * 'print_string' and to protect its print buffer(s). + * 3) TEE() uses 'print_lock' to protect its print buffer(s). + * 4) Routines of the form log_XXX() uses 'print_lock' to protect LOG. + */ + +/** + * printbuf_init - initialize print buffer to empty + */ + +void printbuf_init(struct print_buf *pb, char *raw, u32 sz) +{ + if (!pb || !raw || (sz < (MAX_STRING + 1))) + return; + + pb->crs = pb->buf = raw; + pb->size = sz; + pb->next = 0; + pb->buf[0] = 0; + pb->buf[sz-1] = ~0; +} + +/** + * printbuf_reset - reinitialize print buffer to empty state + */ + +void printbuf_reset(struct print_buf *pb) +{ + if (pb && pb->buf) + printbuf_init(pb, pb->buf, pb->size); +} + +/** + * printbuf_empty - test if print buffer is in empty state + */ + +int printbuf_empty(struct print_buf *pb) +{ + return (!pb || !pb->buf || (pb->crs == pb->buf)); +} + +/** + * printbuf_validate - check for print buffer overflow + * + * Verifies that a print buffer has captured all data written to it. + * If data has been lost, linearize buffer and prepend an error message + * + * Returns length of print buffer data string (including trailing NULL) + */ + +int printbuf_validate(struct print_buf *pb) +{ + char *err = " *** PRINT BUFFER WRAPPED AROUND ***\n"; + char *cp_buf; + struct print_buf cb; + + if (!pb || !pb->buf) + return 0; + + if (pb->buf[pb->size - 1] == '\0') { + cp_buf = kmalloc(pb->size, GFP_ATOMIC); + if (cp_buf != NULL){ + printbuf_init(&cb, cp_buf, pb->size); + printbuf_move(&cb, pb); + printbuf_move(pb, &cb); + kfree(cp_buf); + memcpy(pb->buf, err, strlen(err)); + } else { + printbuf_reset(pb); + tipc_printf(pb, err); + } + } + return (pb->crs - pb->buf + 1); +} + +/** + * printbuf_move - move print buffer contents to another print buffer + * + * Current contents of destination print buffer (if any) are discarded. + * Source print buffer becomes empty if a successful move occurs. + */ + +void printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from) +{ + int len; + + /* Handle the cases where contents can't be moved */ + + if (!pb_to || !pb_to->buf) + return; + + if (!pb_from || !pb_from->buf) { + printbuf_reset(pb_to); + return; + } + + if (pb_to->size < pb_from->size) { + printbuf_reset(pb_to); + tipc_printf(pb_to, "*** PRINT BUFFER OVERFLOW ***"); + return; + } + + /* Copy data from char after cursor to end (if used) */ + len = pb_from->buf + pb_from->size - pb_from->crs - 2; + if ((pb_from->buf[pb_from->size-1] == 0) && (len > 0)) { + strcpy(pb_to->buf, pb_from->crs + 1); + pb_to->crs = pb_to->buf + len; + } else + pb_to->crs = pb_to->buf; + + /* Copy data from start to cursor (always) */ + len = pb_from->crs - pb_from->buf; + strcpy(pb_to->crs, pb_from->buf); + pb_to->crs += len; + + printbuf_reset(pb_from); +} + +/** + * tipc_printf - append formatted output to print buffer chain + */ + +void tipc_printf(struct print_buf *pb, const char *fmt, ...) +{ + int chars_to_add; + int chars_left; + char save_char; + struct print_buf *pb_next; + + spin_lock_bh(&print_lock); + FORMAT(print_string, chars_to_add, fmt); + if (chars_to_add >= MAX_STRING) + strcpy(print_string, "*** STRING TOO LONG ***"); + + while (pb) { + if (pb == CONS) + printk(print_string); + else if (pb->buf) { + chars_left = pb->buf + pb->size - pb->crs - 1; + if (chars_to_add <= chars_left) { + strcpy(pb->crs, print_string); + pb->crs += chars_to_add; + } else { + strcpy(pb->buf, print_string + chars_left); + save_char = print_string[chars_left]; + print_string[chars_left] = 0; + strcpy(pb->crs, print_string); + print_string[chars_left] = save_char; + pb->crs = pb->buf + chars_to_add - chars_left; + } + } + pb_next = pb->next; + pb->next = 0; + pb = pb_next; + } + spin_unlock_bh(&print_lock); +} + +/** + * TEE - perform next output operation on both print buffers + */ + +struct print_buf *TEE(struct print_buf *b0, struct print_buf *b1) +{ + struct print_buf *pb = b0; + + if (!b0 || (b0 == b1)) + return b1; + if (!b1) + return b0; + + spin_lock_bh(&print_lock); + while (pb->next) { + if ((pb->next == b1) || (pb->next == b0)) + pb->next = pb->next->next; + else + pb = pb->next; + } + pb->next = b1; + spin_unlock_bh(&print_lock); + return b0; +} + +/** + * print_to_console - write string of bytes to console in multiple chunks + */ + +static void print_to_console(char *crs, int len) +{ + int rest = len; + + while (rest > 0) { + int sz = rest < MAX_STRING ? rest : MAX_STRING; + char c = crs[sz]; + + crs[sz] = 0; + printk((const char *)crs); + crs[sz] = c; + rest -= sz; + crs += sz; + } +} + +/** + * printbuf_dump - write print buffer contents to console + */ + +static void printbuf_dump(struct print_buf *pb) +{ + int len; + + /* Dump print buffer from char after cursor to end (if used) */ + len = pb->buf + pb->size - pb->crs - 2; + if ((pb->buf[pb->size - 1] == 0) && (len > 0)) + print_to_console(pb->crs + 1, len); + + /* Dump print buffer from start to cursor (always) */ + len = pb->crs - pb->buf; + print_to_console(pb->buf, len); +} + +/** + * tipc_dump - dump non-console print buffer(s) to console + */ + +void tipc_dump(struct print_buf *pb, const char *fmt, ...) +{ + int len; + + spin_lock_bh(&print_lock); + FORMAT(CONS->buf, len, fmt); + printk(CONS->buf); + + for (; pb; pb = pb->next) { + if (pb == CONS) + continue; + printk("\n---- Start of dump,%s log ----\n\n", + (pb == LOG) ? "global" : "local"); + printbuf_dump(pb); + printbuf_reset(pb); + printk("\n-------- End of dump --------\n"); + } + spin_unlock_bh(&print_lock); +} + +/** + * log_stop - free up TIPC log print buffer + */ + +void log_stop(void) +{ + spin_lock_bh(&print_lock); + if (LOG->buf) { + kfree(LOG->buf); + LOG->buf = NULL; + } + spin_unlock_bh(&print_lock); +} + +/** + * log_reinit - set TIPC log print buffer to specified size + */ + +void log_reinit(int log_size) +{ + log_stop(); + + if (log_size) { + if (log_size <= MAX_STRING) + log_size = MAX_STRING + 1; + spin_lock_bh(&print_lock); + printbuf_init(LOG, kmalloc(log_size, GFP_ATOMIC), log_size); + spin_unlock_bh(&print_lock); + } +} + +/** + * log_resize - reconfigure size of TIPC log buffer + */ + +struct sk_buff *log_resize(const void *req_tlv_area, int req_tlv_space) +{ + u32 value; + + if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) + return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + + value = *(u32 *)TLV_DATA(req_tlv_area); + value = ntohl(value); + if (value != delimit(value, 0, 32768)) + return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE + " (log size must be 0-32768)"); + log_reinit(value); + return cfg_reply_none(); +} + +/** + * log_dump - capture TIPC log buffer contents in configuration message + */ + +struct sk_buff *log_dump(void) +{ + struct sk_buff *reply; + + spin_lock_bh(&print_lock); + if (!LOG->buf) + reply = cfg_reply_ultra_string("log not activated\n"); + else if (printbuf_empty(LOG)) + reply = cfg_reply_ultra_string("log is empty\n"); + else { + struct tlv_desc *rep_tlv; + struct print_buf pb; + int str_len; + + str_len = min(LOG->size, 32768u); + reply = cfg_reply_alloc(TLV_SPACE(str_len)); + if (reply) { + rep_tlv = (struct tlv_desc *)reply->data; + printbuf_init(&pb, TLV_DATA(rep_tlv), str_len); + printbuf_move(&pb, LOG); + str_len = strlen(TLV_DATA(rep_tlv)) + 1; + skb_put(reply, TLV_SPACE(str_len)); + TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); + } + } + spin_unlock_bh(&print_lock); + return reply; +} + diff --git a/net/tipc/dbg.h b/net/tipc/dbg.h new file mode 100644 index 00000000000..af4217a993c --- /dev/null +++ b/net/tipc/dbg.h @@ -0,0 +1,56 @@ +/* + * net/tipc/dbg.h: Include file for TIPC print buffer routines + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _TIPC_DBG_H +#define _TIPC_DBG_H + +struct print_buf { + char *buf; + u32 size; + char *crs; + struct print_buf *next; +}; + +void printbuf_init(struct print_buf *pb, char *buf, u32 sz); +void printbuf_reset(struct print_buf *pb); +int printbuf_empty(struct print_buf *pb); +int printbuf_validate(struct print_buf *pb); +void printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from); + +void log_reinit(int log_size); +void log_stop(void); + +struct sk_buff *log_resize(const void *req_tlv_area, int req_tlv_space); +struct sk_buff *log_dump(void); + +#endif diff --git a/net/tipc/discover.c b/net/tipc/discover.c new file mode 100644 index 00000000000..c83c1be17f8 --- /dev/null +++ b/net/tipc/discover.c @@ -0,0 +1,339 @@ +/* + * net/tipc/discover.c + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "core.h" +#include "dbg.h" +#include "link.h" +#include "zone.h" +#include "discover.h" +#include "port.h" +#include "name_table.h" + +#define TIPC_LINK_REQ_INIT 125 /* min delay during bearer start up */ +#define TIPC_LINK_REQ_FAST 2000 /* normal delay if bearer has no links */ +#define TIPC_LINK_REQ_SLOW 600000 /* normal delay if bearer has links */ + +#if 0 +#define GET_NODE_INFO 300 +#define GET_NODE_INFO_RESULT 301 +#define FORWARD_LINK_PROBE 302 +#define LINK_REQUEST_REJECTED 303 +#define LINK_REQUEST_ACCEPTED 304 +#define DROP_LINK_REQUEST 305 +#define CHECK_LINK_COUNT 306 +#endif + +/* + * TODO: Most of the inter-cluster setup stuff should be + * rewritten, and be made conformant with specification. + */ + + +/** + * struct link_req - information about an ongoing link setup request + * @bearer: bearer issuing requests + * @dest: destination address for request messages + * @buf: request message to be (repeatedly) sent + * @timer: timer governing period between requests + * @timer_intv: current interval between requests (in ms) + */ +struct link_req { + struct bearer *bearer; + struct tipc_media_addr dest; + struct sk_buff *buf; + struct timer_list timer; + unsigned int timer_intv; +}; + + +#if 0 +int disc_create_link(const struct tipc_link_create *argv) +{ + /* + * Code for inter cluster link setup here + */ + return TIPC_OK; +} +#endif + +/* + * disc_lost_link(): A link has lost contact + */ + +void disc_link_event(u32 addr, char *name, int up) +{ + if (in_own_cluster(addr)) + return; + /* + * Code for inter cluster link setup here + */ +} + +/** + * disc_init_msg - initialize a link setup message + * @type: message type (request or response) + * @req_links: number of links associated with message + * @dest_domain: network domain of node(s) which should respond to message + * @b_ptr: ptr to bearer issuing message + */ + +struct sk_buff *disc_init_msg(u32 type, + u32 req_links, + u32 dest_domain, + struct bearer *b_ptr) +{ + struct sk_buff *buf = buf_acquire(DSC_H_SIZE); + struct tipc_msg *msg; + + if (buf) { + msg = buf_msg(buf); + msg_init(msg, LINK_CONFIG, type, TIPC_OK, DSC_H_SIZE, + dest_domain); + msg_set_non_seq(msg); + msg_set_req_links(msg, req_links); + msg_set_dest_domain(msg, dest_domain); + msg_set_bc_netid(msg, tipc_net_id); + msg_set_media_addr(msg, &b_ptr->publ.addr); + } + return buf; +} + +/** + * disc_recv_msg - handle incoming link setup message (request or response) + * @buf: buffer containing message + */ + +void disc_recv_msg(struct sk_buff *buf) +{ + struct bearer *b_ptr = (struct bearer *)TIPC_SKB_CB(buf)->handle; + struct link *link; + struct tipc_media_addr media_addr; + struct tipc_msg *msg = buf_msg(buf); + u32 dest = msg_dest_domain(msg); + u32 orig = msg_prevnode(msg); + u32 net_id = msg_bc_netid(msg); + u32 type = msg_type(msg); + + msg_get_media_addr(msg,&media_addr); + msg_dbg(msg, "RECV:"); + buf_discard(buf); + + if (net_id != tipc_net_id) + return; + if (!addr_domain_valid(dest)) + return; + if (!addr_node_valid(orig)) + return; + if (orig == tipc_own_addr) + return; + if (!in_scope(dest, tipc_own_addr)) + return; + if (is_slave(tipc_own_addr) && is_slave(orig)) + return; + if (is_slave(orig) && !in_own_cluster(orig)) + return; + if (in_own_cluster(orig)) { + /* Always accept link here */ + struct sk_buff *rbuf; + struct tipc_media_addr *addr; + struct node *n_ptr = node_find(orig); + int link_up; + dbg(" in own cluster\n"); + if (n_ptr == NULL) { + n_ptr = node_create(orig); + } + if (n_ptr == NULL) { + warn("Memory squeeze; Failed to create node\n"); + return; + } + spin_lock_bh(&n_ptr->lock); + link = n_ptr->links[b_ptr->identity]; + if (!link) { + dbg("creating link\n"); + link = link_create(b_ptr, orig, &media_addr); + if (!link) { + spin_unlock_bh(&n_ptr->lock); + return; + } + } + addr = &link->media_addr; + if (memcmp(addr, &media_addr, sizeof(*addr))) { + char addr_string[16]; + + warn("New bearer address for %s\n", + addr_string_fill(addr_string, orig)); + memcpy(addr, &media_addr, sizeof(*addr)); + link_reset(link); + } + link_up = link_is_up(link); + spin_unlock_bh(&n_ptr->lock); + if ((type == DSC_RESP_MSG) || link_up) + return; + rbuf = disc_init_msg(DSC_RESP_MSG, 1, orig, b_ptr); + if (rbuf != NULL) { + msg_dbg(buf_msg(rbuf),"SEND:"); + b_ptr->media->send_msg(rbuf, &b_ptr->publ, &media_addr); + buf_discard(rbuf); + } + } +} + +/** + * disc_stop_link_req - stop sending periodic link setup requests + * @req: ptr to link request structure + */ + +void disc_stop_link_req(struct link_req *req) +{ + if (!req) + return; + + k_cancel_timer(&req->timer); + k_term_timer(&req->timer); + buf_discard(req->buf); + kfree(req); +} + +/** + * disc_update_link_req - update frequency of periodic link setup requests + * @req: ptr to link request structure + */ + +void disc_update_link_req(struct link_req *req) +{ + if (!req) + return; + + if (req->timer_intv == TIPC_LINK_REQ_SLOW) { + if (!req->bearer->nodes.count) { + req->timer_intv = TIPC_LINK_REQ_FAST; + k_start_timer(&req->timer, req->timer_intv); + } + } else if (req->timer_intv == TIPC_LINK_REQ_FAST) { + if (req->bearer->nodes.count) { + req->timer_intv = TIPC_LINK_REQ_SLOW; + k_start_timer(&req->timer, req->timer_intv); + } + } else { + /* leave timer "as is" if haven't yet reached a "normal" rate */ + } +} + +/** + * disc_timeout - send a periodic link setup request + * @req: ptr to link request structure + * + * Called whenever a link setup request timer associated with a bearer expires. + */ + +static void disc_timeout(struct link_req *req) +{ + struct tipc_msg *msg = buf_msg(req->buf); + + spin_lock_bh(&req->bearer->publ.lock); + +#if 0 + /* CURRENTLY DON'T SUPPORT INTER-ZONE LINKS */ + u32 dest_domain = msg_dest_domain(msg); + int stop = 0; + if (!in_scope(dest_domain, tipc_own_addr)) { + struct _zone *z_ptr = zone_find(dest_domain); + + if (z_ptr && (z_ptr->links >= msg_req_links(msg))) + stop = 1; + if (req->timer_intv >= 32000) + stop = 1; + } + if (stop) { + k_cancel_timer(&req->timer); + buf_discard(req->buf); + kfree(req); + spin_unlock_bh(&req->bearer->publ.lock); + return; + } +#endif + + msg_dbg(msg,"SEND:"); + req->bearer->media->send_msg(req->buf, &req->bearer->publ, &req->dest); + + if ((req->timer_intv == TIPC_LINK_REQ_SLOW) || + (req->timer_intv == TIPC_LINK_REQ_FAST)) { + /* leave timer interval "as is" if already at a "normal" rate */ + } else { + req->timer_intv *= 2; + if (req->timer_intv > TIPC_LINK_REQ_FAST) + req->timer_intv = TIPC_LINK_REQ_FAST; + if ((req->timer_intv == TIPC_LINK_REQ_FAST) && + (req->bearer->nodes.count)) + req->timer_intv = TIPC_LINK_REQ_SLOW; + } + k_start_timer(&req->timer, req->timer_intv); + + spin_unlock_bh(&req->bearer->publ.lock); +} + +/** + * disc_init_link_req - start sending periodic link setup requests + * @b_ptr: ptr to bearer issuing requests + * @dest: destination address for request messages + * @dest_domain: network domain of node(s) which should respond to message + * @req_links: max number of desired links + * + * Returns pointer to link request structure, or NULL if unable to create. + */ + +struct link_req *disc_init_link_req(struct bearer *b_ptr, + const struct tipc_media_addr *dest, + u32 dest_domain, + u32 req_links) +{ + struct link_req *req; + + req = (struct link_req *)kmalloc(sizeof(*req), GFP_ATOMIC); + if (!req) + return NULL; + + req->buf = disc_init_msg(DSC_REQ_MSG, req_links, dest_domain, b_ptr); + if (!req->buf) { + kfree(req); + return NULL; + } + + memcpy(&req->dest, dest, sizeof(*dest)); + req->bearer = b_ptr; + req->timer_intv = TIPC_LINK_REQ_INIT; + k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req); + k_start_timer(&req->timer, req->timer_intv); + return req; +} + diff --git a/net/tipc/discover.h b/net/tipc/discover.h new file mode 100644 index 00000000000..90c1de905e7 --- /dev/null +++ b/net/tipc/discover.h @@ -0,0 +1,55 @@ +/* + * net/tipc/discover.h + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _TIPC_DISCOVER_H +#define _TIPC_DISCOVER_H + +#include + +struct link_req; + +struct link_req *disc_init_link_req(struct bearer *b_ptr, + const struct tipc_media_addr *dest, + u32 dest_domain, + u32 req_links); +void disc_update_link_req(struct link_req *req); +void disc_stop_link_req(struct link_req *req); + +void disc_recv_msg(struct sk_buff *buf); + +void disc_link_event(u32 addr, char *name, int up); +#if 0 +int disc_create_link(const struct tipc_link_create *argv); +#endif + +#endif diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c new file mode 100644 index 00000000000..b634d7a5640 --- /dev/null +++ b/net/tipc/eth_media.c @@ -0,0 +1,296 @@ +/* + * net/tipc/eth_media.c: Ethernet bearer support for TIPC + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +#define MAX_ETH_BEARERS 2 +#define TIPC_PROTOCOL 0x88ca +#define ETH_LINK_PRIORITY 10 +#define ETH_LINK_TOLERANCE TIPC_DEF_LINK_TOL + + +/** + * struct eth_bearer - Ethernet bearer data structure + * @bearer: ptr to associated "generic" bearer structure + * @dev: ptr to associated Ethernet network device + * @tipc_packet_type: used in binding TIPC to Ethernet driver + */ + +struct eth_bearer { + struct tipc_bearer *bearer; + struct net_device *dev; + struct packet_type tipc_packet_type; +}; + +static struct eth_bearer eth_bearers[MAX_ETH_BEARERS]; +static int eth_started = 0; +static struct notifier_block notifier; + +/** + * send_msg - send a TIPC message out over an Ethernet interface + */ + +static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr, + struct tipc_media_addr *dest) +{ + struct sk_buff *clone; + struct net_device *dev; + + clone = skb_clone(buf, GFP_ATOMIC); + if (clone) { + clone->nh.raw = clone->data; + dev = ((struct eth_bearer *)(tb_ptr->usr_handle))->dev; + clone->dev = dev; + dev->hard_header(clone, dev, TIPC_PROTOCOL, + &dest->dev_addr.eth_addr, + dev->dev_addr, clone->len); + dev_queue_xmit(clone); + } + return TIPC_OK; +} + +/** + * recv_msg - handle incoming TIPC message from an Ethernet interface + * + * Routine truncates any Ethernet padding/CRC appended to the message, + * and ensures message size matches actual length + */ + +static int recv_msg(struct sk_buff *buf, struct net_device *dev, + struct packet_type *pt, struct net_device *orig_dev) +{ + struct eth_bearer *eb_ptr = (struct eth_bearer *)pt->af_packet_priv; + u32 size; + + if (likely(eb_ptr->bearer)) { + size = msg_size((struct tipc_msg *)buf->data); + skb_trim(buf, size); + if (likely(buf->len == size)) { + buf->next = NULL; + tipc_recv_msg(buf, eb_ptr->bearer); + } else { + kfree_skb(buf); + } + } else { + kfree_skb(buf); + } + return TIPC_OK; +} + +/** + * enable_bearer - attach TIPC bearer to an Ethernet interface + */ + +static int enable_bearer(struct tipc_bearer *tb_ptr) +{ + struct net_device *dev = dev_base; + struct eth_bearer *eb_ptr = ð_bearers[0]; + struct eth_bearer *stop = ð_bearers[MAX_ETH_BEARERS]; + char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1; + + /* Find device with specified name */ + + while (dev && dev->name && + (memcmp(dev->name, driver_name, strlen(dev->name)))) { + dev = dev->next; + } + if (!dev) + return -ENODEV; + + /* Find Ethernet bearer for device (or create one) */ + + for (;(eb_ptr != stop) && eb_ptr->dev && (eb_ptr->dev != dev); eb_ptr++); + if (eb_ptr == stop) + return -EDQUOT; + if (!eb_ptr->dev) { + eb_ptr->dev = dev; + eb_ptr->tipc_packet_type.type = __constant_htons(TIPC_PROTOCOL); + eb_ptr->tipc_packet_type.dev = dev; + eb_ptr->tipc_packet_type.func = recv_msg; + eb_ptr->tipc_packet_type.af_packet_priv = eb_ptr; + INIT_LIST_HEAD(&(eb_ptr->tipc_packet_type.list)); + dev_hold(dev); + dev_add_pack(&eb_ptr->tipc_packet_type); + } + + /* Associate TIPC bearer with Ethernet bearer */ + + eb_ptr->bearer = tb_ptr; + tb_ptr->usr_handle = (void *)eb_ptr; + tb_ptr->mtu = dev->mtu; + tb_ptr->blocked = 0; + tb_ptr->addr.type = htonl(TIPC_MEDIA_TYPE_ETH); + memcpy(&tb_ptr->addr.dev_addr, &dev->dev_addr, ETH_ALEN); + return 0; +} + +/** + * disable_bearer - detach TIPC bearer from an Ethernet interface + * + * We really should do dev_remove_pack() here, but this function can not be + * called at tasklet level. => Use eth_bearer->bearer as a flag to throw away + * incoming buffers, & postpone dev_remove_pack() to eth_media_stop() on exit. + */ + +static void disable_bearer(struct tipc_bearer *tb_ptr) +{ + ((struct eth_bearer *)tb_ptr->usr_handle)->bearer = 0; +} + +/** + * recv_notification - handle device updates from OS + * + * Change the state of the Ethernet bearer (if any) associated with the + * specified device. + */ + +static int recv_notification(struct notifier_block *nb, unsigned long evt, + void *dv) +{ + struct net_device *dev = (struct net_device *)dv; + struct eth_bearer *eb_ptr = ð_bearers[0]; + struct eth_bearer *stop = ð_bearers[MAX_ETH_BEARERS]; + + while ((eb_ptr->dev != dev)) { + if (++eb_ptr == stop) + return NOTIFY_DONE; /* couldn't find device */ + } + if (!eb_ptr->bearer) + return NOTIFY_DONE; /* bearer had been disabled */ + + eb_ptr->bearer->mtu = dev->mtu; + + switch (evt) { + case NETDEV_CHANGE: + if (netif_carrier_ok(dev)) + tipc_continue(eb_ptr->bearer); + else + tipc_block_bearer(eb_ptr->bearer->name); + break; + case NETDEV_UP: + tipc_continue(eb_ptr->bearer); + break; + case NETDEV_DOWN: + tipc_block_bearer(eb_ptr->bearer->name); + break; + case NETDEV_CHANGEMTU: + case NETDEV_CHANGEADDR: + tipc_block_bearer(eb_ptr->bearer->name); + tipc_continue(eb_ptr->bearer); + break; + case NETDEV_UNREGISTER: + case NETDEV_CHANGENAME: + tipc_disable_bearer(eb_ptr->bearer->name); + break; + } + return NOTIFY_OK; +} + +/** + * eth_addr2str - convert Ethernet address to string + */ + +static char *eth_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size) +{ + unchar *addr = (unchar *)&a->dev_addr; + + if (str_size < 18) + *str_buf = '\0'; + else + sprintf(str_buf, "%02x:%02x:%02x:%02x:%02x:%02x", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + return str_buf; +} + +/** + * eth_media_start - activate Ethernet bearer support + * + * Register Ethernet media type with TIPC bearer code. Also register + * with OS for notifications about device state changes. + */ + +int eth_media_start(void) +{ + struct tipc_media_addr bcast_addr; + int res; + + if (eth_started) + return -EINVAL; + + memset(&bcast_addr, 0xff, sizeof(bcast_addr)); + memset(eth_bearers, 0, sizeof(eth_bearers)); + + res = tipc_register_media(TIPC_MEDIA_TYPE_ETH, "eth", + enable_bearer, disable_bearer, send_msg, + eth_addr2str, &bcast_addr, ETH_LINK_PRIORITY, + ETH_LINK_TOLERANCE, TIPC_DEF_LINK_WIN); + if (res) + return res; + + notifier.notifier_call = &recv_notification; + notifier.priority = 0; + res = register_netdevice_notifier(¬ifier); + if (!res) + eth_started = 1; + return res; +} + +/** + * eth_media_stop - deactivate Ethernet bearer support + */ + +void eth_media_stop(void) +{ + int i; + + if (!eth_started) + return; + + unregister_netdevice_notifier(¬ifier); + for (i = 0; i < MAX_ETH_BEARERS ; i++) { + if (eth_bearers[i].bearer) { + eth_bearers[i].bearer->blocked = 1; + eth_bearers[i].bearer = 0; + } + if (eth_bearers[i].dev) { + dev_remove_pack(ð_bearers[i].tipc_packet_type); + dev_put(eth_bearers[i].dev); + } + } + memset(ð_bearers, 0, sizeof(eth_bearers)); + eth_started = 0; +} diff --git a/net/tipc/handler.c b/net/tipc/handler.c new file mode 100644 index 00000000000..c8fbb2071df --- /dev/null +++ b/net/tipc/handler.c @@ -0,0 +1,129 @@ +/* + * net/tipc/handler.c: TIPC signal handling + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "core.h" + +struct queue_item { + struct list_head next_signal; + void (*handler) (unsigned long); + unsigned long data; +}; + +static kmem_cache_t *tipc_queue_item_cache; +static struct list_head signal_queue_head; +static spinlock_t qitem_lock = SPIN_LOCK_UNLOCKED; +static int handler_enabled = 0; + +static void process_signal_queue(unsigned long dummy); + +static DECLARE_TASKLET_DISABLED(tipc_tasklet, process_signal_queue, 0); + + +unsigned int k_signal(Handler routine, unsigned long argument) +{ + struct queue_item *item; + + if (!handler_enabled) { + err("Signal request ignored by handler\n"); + return -ENOPROTOOPT; + } + + spin_lock_bh(&qitem_lock); + item = kmem_cache_alloc(tipc_queue_item_cache, GFP_ATOMIC); + if (!item) { + err("Signal queue out of memory\n"); + spin_unlock_bh(&qitem_lock); + return -ENOMEM; + } + item->handler = routine; + item->data = argument; + list_add_tail(&item->next_signal, &signal_queue_head); + spin_unlock_bh(&qitem_lock); + tasklet_schedule(&tipc_tasklet); + return 0; +} + +static void process_signal_queue(unsigned long dummy) +{ + struct queue_item *__volatile__ item; + struct list_head *l, *n; + + spin_lock_bh(&qitem_lock); + list_for_each_safe(l, n, &signal_queue_head) { + item = list_entry(l, struct queue_item, next_signal); + list_del(&item->next_signal); + spin_unlock_bh(&qitem_lock); + item->handler(item->data); + spin_lock_bh(&qitem_lock); + kmem_cache_free(tipc_queue_item_cache, item); + } + spin_unlock_bh(&qitem_lock); +} + +int handler_start(void) +{ + tipc_queue_item_cache = + kmem_cache_create("tipc_queue_items", sizeof(struct queue_item), + 0, SLAB_HWCACHE_ALIGN, NULL, NULL); + if (!tipc_queue_item_cache) + return -ENOMEM; + + INIT_LIST_HEAD(&signal_queue_head); + tasklet_enable(&tipc_tasklet); + handler_enabled = 1; + return 0; +} + +void handler_stop(void) +{ + struct list_head *l, *n; + struct queue_item *item; + + if (!handler_enabled) + return; + + handler_enabled = 0; + tasklet_disable(&tipc_tasklet); + tasklet_kill(&tipc_tasklet); + + spin_lock_bh(&qitem_lock); + list_for_each_safe(l, n, &signal_queue_head) { + item = list_entry(l, struct queue_item, next_signal); + list_del(&item->next_signal); + kmem_cache_free(tipc_queue_item_cache, item); + } + spin_unlock_bh(&qitem_lock); + + kmem_cache_destroy(tipc_queue_item_cache); +} + diff --git a/net/tipc/link.c b/net/tipc/link.c new file mode 100644 index 00000000000..92acb80bb24 --- /dev/null +++ b/net/tipc/link.c @@ -0,0 +1,3164 @@ +/* + * net/tipc/link.c: TIPC link code + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2004-2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "core.h" +#include "dbg.h" +#include "link.h" +#include "net.h" +#include "node.h" +#include "port.h" +#include "addr.h" +#include "node_subscr.h" +#include "name_distr.h" +#include "bearer.h" +#include "name_table.h" +#include "discover.h" +#include "config.h" +#include "bcast.h" + + +/* + * Limit for deferred reception queue: + */ + +#define DEF_QUEUE_LIMIT 256u + +/* + * Link state events: + */ + +#define STARTING_EVT 856384768 /* link processing trigger */ +#define TRAFFIC_MSG_EVT 560815u /* rx'd ??? */ +#define TIMEOUT_EVT 560817u /* link timer expired */ + +/* + * The following two 'message types' is really just implementation + * data conveniently stored in the message header. + * They must not be considered part of the protocol + */ +#define OPEN_MSG 0 +#define CLOSED_MSG 1 + +/* + * State value stored in 'exp_msg_count' + */ + +#define START_CHANGEOVER 100000u + +/** + * struct link_name - deconstructed link name + * @addr_local: network address of node at this end + * @if_local: name of interface at this end + * @addr_peer: network address of node at far end + * @if_peer: name of interface at far end + */ + +struct link_name { + u32 addr_local; + char if_local[TIPC_MAX_IF_NAME]; + u32 addr_peer; + char if_peer[TIPC_MAX_IF_NAME]; +}; + +#if 0 + +/* LINK EVENT CODE IS NOT SUPPORTED AT PRESENT */ + +/** + * struct link_event - link up/down event notification + */ + +struct link_event { + u32 addr; + int up; + void (*fcn)(u32, char *, int); + char name[TIPC_MAX_LINK_NAME]; +}; + +#endif + +static void link_handle_out_of_seq_msg(struct link *l_ptr, + struct sk_buff *buf); +static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf); +static int link_recv_changeover_msg(struct link **l_ptr, struct sk_buff **buf); +static void link_set_supervision_props(struct link *l_ptr, u32 tolerance); +static int link_send_sections_long(struct port *sender, + struct iovec const *msg_sect, + u32 num_sect, u32 destnode); +static void link_check_defragm_bufs(struct link *l_ptr); +static void link_state_event(struct link *l_ptr, u32 event); +static void link_reset_statistics(struct link *l_ptr); +static void link_print(struct link *l_ptr, struct print_buf *buf, + const char *str); + +/* + * Debugging code used by link routines only + * + * When debugging link problems on a system that has multiple links, + * the standard TIPC debugging routines may not be useful since they + * allow the output from multiple links to be intermixed. For this reason + * routines of the form "dbg_link_XXX()" have been created that will capture + * debug info into a link's personal print buffer, which can then be dumped + * into the TIPC system log (LOG) upon request. + * + * To enable per-link debugging, use LINK_LOG_BUF_SIZE to specify the size + * of the print buffer used by each link. If LINK_LOG_BUF_SIZE is set to 0, + * the dbg_link_XXX() routines simply send their output to the standard + * debug print buffer (DBG_OUTPUT), if it has been defined; this can be useful + * when there is only a single link in the system being debugged. + * + * Notes: + * - When enabled, LINK_LOG_BUF_SIZE should be set to at least 1000 (bytes) + * - "l_ptr" must be valid when using dbg_link_XXX() macros + */ + +#define LINK_LOG_BUF_SIZE 0 + +#define dbg_link(fmt, arg...) do {if (LINK_LOG_BUF_SIZE) tipc_printf(&l_ptr->print_buf, fmt, ## arg); } while(0) +#define dbg_link_msg(msg, txt) do {if (LINK_LOG_BUF_SIZE) msg_print(&l_ptr->print_buf, msg, txt); } while(0) +#define dbg_link_state(txt) do {if (LINK_LOG_BUF_SIZE) link_print(l_ptr, &l_ptr->print_buf, txt); } while(0) +#define dbg_link_dump() do { \ + if (LINK_LOG_BUF_SIZE) { \ + tipc_printf(LOG, "\n\nDumping link <%s>:\n", l_ptr->name); \ + printbuf_move(LOG, &l_ptr->print_buf); \ + } \ +} while (0) + +static inline void dbg_print_link(struct link *l_ptr, const char *str) +{ + if (DBG_OUTPUT) + link_print(l_ptr, DBG_OUTPUT, str); +} + +static inline void dbg_print_buf_chain(struct sk_buff *root_buf) +{ + if (DBG_OUTPUT) { + struct sk_buff *buf = root_buf; + + while (buf) { + msg_dbg(buf_msg(buf), "In chain: "); + buf = buf->next; + } + } +} + +/* + * Simple inlined link routines + */ + +static inline unsigned int align(unsigned int i) +{ + return (i + 3) & ~3u; +} + +static inline int link_working_working(struct link *l_ptr) +{ + return (l_ptr->state == WORKING_WORKING); +} + +static inline int link_working_unknown(struct link *l_ptr) +{ + return (l_ptr->state == WORKING_UNKNOWN); +} + +static inline int link_reset_unknown(struct link *l_ptr) +{ + return (l_ptr->state == RESET_UNKNOWN); +} + +static inline int link_reset_reset(struct link *l_ptr) +{ + return (l_ptr->state == RESET_RESET); +} + +static inline int link_blocked(struct link *l_ptr) +{ + return (l_ptr->exp_msg_count || l_ptr->blocked); +} + +static inline int link_congested(struct link *l_ptr) +{ + return (l_ptr->out_queue_size >= l_ptr->queue_limit[0]); +} + +static inline u32 link_max_pkt(struct link *l_ptr) +{ + return l_ptr->max_pkt; +} + +static inline void link_init_max_pkt(struct link *l_ptr) +{ + u32 max_pkt; + + max_pkt = (l_ptr->b_ptr->publ.mtu & ~3); + if (max_pkt > MAX_MSG_SIZE) + max_pkt = MAX_MSG_SIZE; + + l_ptr->max_pkt_target = max_pkt; + if (l_ptr->max_pkt_target < MAX_PKT_DEFAULT) + l_ptr->max_pkt = l_ptr->max_pkt_target; + else + l_ptr->max_pkt = MAX_PKT_DEFAULT; + + l_ptr->max_pkt_probes = 0; +} + +static inline u32 link_next_sent(struct link *l_ptr) +{ + if (l_ptr->next_out) + return msg_seqno(buf_msg(l_ptr->next_out)); + return mod(l_ptr->next_out_no); +} + +static inline u32 link_last_sent(struct link *l_ptr) +{ + return mod(link_next_sent(l_ptr) - 1); +} + +/* + * Simple non-inlined link routines (i.e. referenced outside this file) + */ + +int link_is_up(struct link *l_ptr) +{ + if (!l_ptr) + return 0; + return (link_working_working(l_ptr) || link_working_unknown(l_ptr)); +} + +int link_is_active(struct link *l_ptr) +{ + return ((l_ptr->owner->active_links[0] == l_ptr) || + (l_ptr->owner->active_links[1] == l_ptr)); +} + +/** + * link_name_validate - validate & (optionally) deconstruct link name + * @name - ptr to link name string + * @name_parts - ptr to area for link name components (or NULL if not needed) + * + * Returns 1 if link name is valid, otherwise 0. + */ + +static int link_name_validate(const char *name, struct link_name *name_parts) +{ + char name_copy[TIPC_MAX_LINK_NAME]; + char *addr_local; + char *if_local; + char *addr_peer; + char *if_peer; + char dummy; + u32 z_local, c_local, n_local; + u32 z_peer, c_peer, n_peer; + u32 if_local_len; + u32 if_peer_len; + + /* copy link name & ensure length is OK */ + + name_copy[TIPC_MAX_LINK_NAME - 1] = 0; + /* need above in case non-Posix strncpy() doesn't pad with nulls */ + strncpy(name_copy, name, TIPC_MAX_LINK_NAME); + if (name_copy[TIPC_MAX_LINK_NAME - 1] != 0) + return 0; + + /* ensure all component parts of link name are present */ + + addr_local = name_copy; + if ((if_local = strchr(addr_local, ':')) == NULL) + return 0; + *(if_local++) = 0; + if ((addr_peer = strchr(if_local, '-')) == NULL) + return 0; + *(addr_peer++) = 0; + if_local_len = addr_peer - if_local; + if ((if_peer = strchr(addr_peer, ':')) == NULL) + return 0; + *(if_peer++) = 0; + if_peer_len = strlen(if_peer) + 1; + + /* validate component parts of link name */ + + if ((sscanf(addr_local, "%u.%u.%u%c", + &z_local, &c_local, &n_local, &dummy) != 3) || + (sscanf(addr_peer, "%u.%u.%u%c", + &z_peer, &c_peer, &n_peer, &dummy) != 3) || + (z_local > 255) || (c_local > 4095) || (n_local > 4095) || + (z_peer > 255) || (c_peer > 4095) || (n_peer > 4095) || + (if_local_len <= 1) || (if_local_len > TIPC_MAX_IF_NAME) || + (if_peer_len <= 1) || (if_peer_len > TIPC_MAX_IF_NAME) || + (strspn(if_local, tipc_alphabet) != (if_local_len - 1)) || + (strspn(if_peer, tipc_alphabet) != (if_peer_len - 1))) + return 0; + + /* return link name components, if necessary */ + + if (name_parts) { + name_parts->addr_local = tipc_addr(z_local, c_local, n_local); + strcpy(name_parts->if_local, if_local); + name_parts->addr_peer = tipc_addr(z_peer, c_peer, n_peer); + strcpy(name_parts->if_peer, if_peer); + } + return 1; +} + +/** + * link_timeout - handle expiration of link timer + * @l_ptr: pointer to link + * + * This routine must not grab "net_lock" to avoid a potential deadlock conflict + * with link_delete(). (There is no risk that the node will be deleted by + * another thread because link_delete() always cancels the link timer before + * node_delete() is called.) + */ + +static void link_timeout(struct link *l_ptr) +{ + node_lock(l_ptr->owner); + + /* update counters used in statistical profiling of send traffic */ + + l_ptr->stats.accu_queue_sz += l_ptr->out_queue_size; + l_ptr->stats.queue_sz_counts++; + + if (l_ptr->out_queue_size > l_ptr->stats.max_queue_sz) + l_ptr->stats.max_queue_sz = l_ptr->out_queue_size; + + if (l_ptr->first_out) { + struct tipc_msg *msg = buf_msg(l_ptr->first_out); + u32 length = msg_size(msg); + + if ((msg_user(msg) == MSG_FRAGMENTER) + && (msg_type(msg) == FIRST_FRAGMENT)) { + length = msg_size(msg_get_wrapped(msg)); + } + if (length) { + l_ptr->stats.msg_lengths_total += length; + l_ptr->stats.msg_length_counts++; + if (length <= 64) + l_ptr->stats.msg_length_profile[0]++; + else if (length <= 256) + l_ptr->stats.msg_length_profile[1]++; + else if (length <= 1024) + l_ptr->stats.msg_length_profile[2]++; + else if (length <= 4096) + l_ptr->stats.msg_length_profile[3]++; + else if (length <= 16384) + l_ptr->stats.msg_length_profile[4]++; + else if (length <= 32768) + l_ptr->stats.msg_length_profile[5]++; + else + l_ptr->stats.msg_length_profile[6]++; + } + } + + /* do all other link processing performed on a periodic basis */ + + link_check_defragm_bufs(l_ptr); + + link_state_event(l_ptr, TIMEOUT_EVT); + + if (l_ptr->next_out) + link_push_queue(l_ptr); + + node_unlock(l_ptr->owner); +} + +static inline void link_set_timer(struct link *l_ptr, u32 time) +{ + k_start_timer(&l_ptr->timer, time); +} + +/** + * link_create - create a new link + * @b_ptr: pointer to associated bearer + * @peer: network address of node at other end of link + * @media_addr: media address to use when sending messages over link + * + * Returns pointer to link. + */ + +struct link *link_create(struct bearer *b_ptr, const u32 peer, + const struct tipc_media_addr *media_addr) +{ + struct link *l_ptr; + struct tipc_msg *msg; + char *if_name; + + l_ptr = (struct link *)kmalloc(sizeof(*l_ptr), GFP_ATOMIC); + if (!l_ptr) { + warn("Memory squeeze; Failed to create link\n"); + return NULL; + } + memset(l_ptr, 0, sizeof(*l_ptr)); + + l_ptr->addr = peer; + if_name = strchr(b_ptr->publ.name, ':') + 1; + sprintf(l_ptr->name, "%u.%u.%u:%s-%u.%u.%u:", + tipc_zone(tipc_own_addr), tipc_cluster(tipc_own_addr), + tipc_node(tipc_own_addr), + if_name, + tipc_zone(peer), tipc_cluster(peer), tipc_node(peer)); + /* note: peer i/f is appended to link name by reset/activate */ + memcpy(&l_ptr->media_addr, media_addr, sizeof(*media_addr)); + k_init_timer(&l_ptr->timer, (Handler)link_timeout, (unsigned long)l_ptr); + list_add_tail(&l_ptr->link_list, &b_ptr->links); + l_ptr->checkpoint = 1; + l_ptr->b_ptr = b_ptr; + link_set_supervision_props(l_ptr, b_ptr->media->tolerance); + l_ptr->state = RESET_UNKNOWN; + + l_ptr->pmsg = (struct tipc_msg *)&l_ptr->proto_msg; + msg = l_ptr->pmsg; + msg_init(msg, LINK_PROTOCOL, RESET_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr); + msg_set_size(msg, sizeof(l_ptr->proto_msg)); + msg_set_session(msg, tipc_random); + msg_set_bearer_id(msg, b_ptr->identity); + strcpy((char *)msg_data(msg), if_name); + + l_ptr->priority = b_ptr->priority; + link_set_queue_limits(l_ptr, b_ptr->media->window); + + link_init_max_pkt(l_ptr); + + l_ptr->next_out_no = 1; + INIT_LIST_HEAD(&l_ptr->waiting_ports); + + link_reset_statistics(l_ptr); + + l_ptr->owner = node_attach_link(l_ptr); + if (!l_ptr->owner) { + kfree(l_ptr); + return NULL; + } + + if (LINK_LOG_BUF_SIZE) { + char *pb = kmalloc(LINK_LOG_BUF_SIZE, GFP_ATOMIC); + + if (!pb) { + kfree(l_ptr); + warn("Memory squeeze; Failed to create link\n"); + return NULL; + } + printbuf_init(&l_ptr->print_buf, pb, LINK_LOG_BUF_SIZE); + } + + k_signal((Handler)link_start, (unsigned long)l_ptr); + + dbg("link_create(): tolerance = %u,cont intv = %u, abort_limit = %u\n", + l_ptr->tolerance, l_ptr->continuity_interval, l_ptr->abort_limit); + + return l_ptr; +} + +/** + * link_delete - delete a link + * @l_ptr: pointer to link + * + * Note: 'net_lock' is write_locked, bearer is locked. + * This routine must not grab the node lock until after link timer cancellation + * to avoid a potential deadlock situation. + */ + +void link_delete(struct link *l_ptr) +{ + if (!l_ptr) { + err("Attempt to delete non-existent link\n"); + return; + } + + dbg("link_delete()\n"); + + k_cancel_timer(&l_ptr->timer); + + node_lock(l_ptr->owner); + link_reset(l_ptr); + node_detach_link(l_ptr->owner, l_ptr); + link_stop(l_ptr); + list_del_init(&l_ptr->link_list); + if (LINK_LOG_BUF_SIZE) + kfree(l_ptr->print_buf.buf); + node_unlock(l_ptr->owner); + k_term_timer(&l_ptr->timer); + kfree(l_ptr); +} + +void link_start(struct link *l_ptr) +{ + dbg("link_start %x\n", l_ptr); + link_state_event(l_ptr, STARTING_EVT); +} + +/** + * link_schedule_port - schedule port for deferred sending + * @l_ptr: pointer to link + * @origport: reference to sending port + * @sz: amount of data to be sent + * + * Schedules port for renewed sending of messages after link congestion + * has abated. + */ + +static int link_schedule_port(struct link *l_ptr, u32 origport, u32 sz) +{ + struct port *p_ptr; + + spin_lock_bh(&port_list_lock); + p_ptr = port_lock(origport); + if (p_ptr) { + if (!p_ptr->wakeup) + goto exit; + if (!list_empty(&p_ptr->wait_list)) + goto exit; + p_ptr->congested_link = l_ptr; + p_ptr->publ.congested = 1; + p_ptr->waiting_pkts = 1 + ((sz - 1) / link_max_pkt(l_ptr)); + list_add_tail(&p_ptr->wait_list, &l_ptr->waiting_ports); + l_ptr->stats.link_congs++; +exit: + port_unlock(p_ptr); + } + spin_unlock_bh(&port_list_lock); + return -ELINKCONG; +} + +void link_wakeup_ports(struct link *l_ptr, int all) +{ + struct port *p_ptr; + struct port *temp_p_ptr; + int win = l_ptr->queue_limit[0] - l_ptr->out_queue_size; + + if (all) + win = 100000; + if (win <= 0) + return; + if (!spin_trylock_bh(&port_list_lock)) + return; + if (link_congested(l_ptr)) + goto exit; + list_for_each_entry_safe(p_ptr, temp_p_ptr, &l_ptr->waiting_ports, + wait_list) { + if (win <= 0) + break; + list_del_init(&p_ptr->wait_list); + p_ptr->congested_link = 0; + assert(p_ptr->wakeup); + spin_lock_bh(p_ptr->publ.lock); + p_ptr->publ.congested = 0; + p_ptr->wakeup(&p_ptr->publ); + win -= p_ptr->waiting_pkts; + spin_unlock_bh(p_ptr->publ.lock); + } + +exit: + spin_unlock_bh(&port_list_lock); +} + +/** + * link_release_outqueue - purge link's outbound message queue + * @l_ptr: pointer to link + */ + +static void link_release_outqueue(struct link *l_ptr) +{ + struct sk_buff *buf = l_ptr->first_out; + struct sk_buff *next; + + while (buf) { + next = buf->next; + buf_discard(buf); + buf = next; + } + l_ptr->first_out = NULL; + l_ptr->out_queue_size = 0; +} + +/** + * link_reset_fragments - purge link's inbound message fragments queue + * @l_ptr: pointer to link + */ + +void link_reset_fragments(struct link *l_ptr) +{ + struct sk_buff *buf = l_ptr->defragm_buf; + struct sk_buff *next; + + while (buf) { + next = buf->next; + buf_discard(buf); + buf = next; + } + l_ptr->defragm_buf = NULL; +} + +/** + * link_stop - purge all inbound and outbound messages associated with link + * @l_ptr: pointer to link + */ + +void link_stop(struct link *l_ptr) +{ + struct sk_buff *buf; + struct sk_buff *next; + + buf = l_ptr->oldest_deferred_in; + while (buf) { + next = buf->next; + buf_discard(buf); + buf = next; + } + + buf = l_ptr->first_out; + while (buf) { + next = buf->next; + buf_discard(buf); + buf = next; + } + + link_reset_fragments(l_ptr); + + buf_discard(l_ptr->proto_msg_queue); + l_ptr->proto_msg_queue = NULL; +} + +#if 0 + +/* LINK EVENT CODE IS NOT SUPPORTED AT PRESENT */ + +static void link_recv_event(struct link_event *ev) +{ + ev->fcn(ev->addr, ev->name, ev->up); + kfree(ev); +} + +static void link_send_event(void (*fcn)(u32 a, char *n, int up), + struct link *l_ptr, int up) +{ + struct link_event *ev; + + ev = kmalloc(sizeof(*ev), GFP_ATOMIC); + if (!ev) { + warn("Link event allocation failure\n"); + return; + } + ev->addr = l_ptr->addr; + ev->up = up; + ev->fcn = fcn; + memcpy(ev->name, l_ptr->name, TIPC_MAX_LINK_NAME); + k_signal((Handler)link_recv_event, (unsigned long)ev); +} + +#else + +#define link_send_event(fcn, l_ptr, up) do { } while (0) + +#endif + +void link_reset(struct link *l_ptr) +{ + struct sk_buff *buf; + u32 prev_state = l_ptr->state; + u32 checkpoint = l_ptr->next_in_no; + + msg_set_session(l_ptr->pmsg, msg_session(l_ptr->pmsg) + 1); + + /* Link is down, accept any session: */ + l_ptr->peer_session = 0; + + /* Prepare for max packet size negotiation */ + link_init_max_pkt(l_ptr); + + l_ptr->state = RESET_UNKNOWN; + dbg_link_state("Resetting Link\n"); + + if ((prev_state == RESET_UNKNOWN) || (prev_state == RESET_RESET)) + return; + + node_link_down(l_ptr->owner, l_ptr); + bearer_remove_dest(l_ptr->b_ptr, l_ptr->addr); +#if 0 + tipc_printf(CONS, "\nReset link <%s>\n", l_ptr->name); + dbg_link_dump(); +#endif + if (node_has_active_links(l_ptr->owner) && + l_ptr->owner->permit_changeover) { + l_ptr->reset_checkpoint = checkpoint; + l_ptr->exp_msg_count = START_CHANGEOVER; + } + + /* Clean up all queues: */ + + link_release_outqueue(l_ptr); + buf_discard(l_ptr->proto_msg_queue); + l_ptr->proto_msg_queue = NULL; + buf = l_ptr->oldest_deferred_in; + while (buf) { + struct sk_buff *next = buf->next; + buf_discard(buf); + buf = next; + } + if (!list_empty(&l_ptr->waiting_ports)) + link_wakeup_ports(l_ptr, 1); + + l_ptr->retransm_queue_head = 0; + l_ptr->retransm_queue_size = 0; + l_ptr->last_out = NULL; + l_ptr->first_out = NULL; + l_ptr->next_out = NULL; + l_ptr->unacked_window = 0; + l_ptr->checkpoint = 1; + l_ptr->next_out_no = 1; + l_ptr->deferred_inqueue_sz = 0; + l_ptr->oldest_deferred_in = NULL; + l_ptr->newest_deferred_in = NULL; + l_ptr->fsm_msg_cnt = 0; + l_ptr->stale_count = 0; + link_reset_statistics(l_ptr); + + link_send_event(cfg_link_event, l_ptr, 0); + if (!in_own_cluster(l_ptr->addr)) + link_send_event(disc_link_event, l_ptr, 0); +} + + +static void link_activate(struct link *l_ptr) +{ + l_ptr->next_in_no = 1; + node_link_up(l_ptr->owner, l_ptr); + bearer_add_dest(l_ptr->b_ptr, l_ptr->addr); + link_send_event(cfg_link_event, l_ptr, 1); + if (!in_own_cluster(l_ptr->addr)) + link_send_event(disc_link_event, l_ptr, 1); +} + +/** + * link_state_event - link finite state machine + * @l_ptr: pointer to link + * @event: state machine event to process + */ + +static void link_state_event(struct link *l_ptr, unsigned event) +{ + struct link *other; + u32 cont_intv = l_ptr->continuity_interval; + + if (!l_ptr->started && (event != STARTING_EVT)) + return; /* Not yet. */ + + if (link_blocked(l_ptr)) { + if (event == TIMEOUT_EVT) { + link_set_timer(l_ptr, cont_intv); + } + return; /* Changeover going on */ + } + dbg_link("STATE_EV: <%s> ", l_ptr->name); + + switch (l_ptr->state) { + case WORKING_WORKING: + dbg_link("WW/"); + switch (event) { + case TRAFFIC_MSG_EVT: + dbg_link("TRF-"); + /* fall through */ + case ACTIVATE_MSG: + dbg_link("ACT\n"); + break; + case TIMEOUT_EVT: + dbg_link("TIM "); + if (l_ptr->next_in_no != l_ptr->checkpoint) { + l_ptr->checkpoint = l_ptr->next_in_no; + if (bclink_acks_missing(l_ptr->owner)) { + link_send_proto_msg(l_ptr, STATE_MSG, + 0, 0, 0, 0, 0); + l_ptr->fsm_msg_cnt++; + } else if (l_ptr->max_pkt < l_ptr->max_pkt_target) { + link_send_proto_msg(l_ptr, STATE_MSG, + 1, 0, 0, 0, 0); + l_ptr->fsm_msg_cnt++; + } + link_set_timer(l_ptr, cont_intv); + break; + } + dbg_link(" -> WU\n"); + l_ptr->state = WORKING_UNKNOWN; + l_ptr->fsm_msg_cnt = 0; + link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); + l_ptr->fsm_msg_cnt++; + link_set_timer(l_ptr, cont_intv / 4); + break; + case RESET_MSG: + dbg_link("RES -> RR\n"); + link_reset(l_ptr); + l_ptr->state = RESET_RESET; + l_ptr->fsm_msg_cnt = 0; + link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0); + l_ptr->fsm_msg_cnt++; + link_set_timer(l_ptr, cont_intv); + break; + default: + err("Unknown link event %u in WW state\n", event); + } + break; + case WORKING_UNKNOWN: + dbg_link("WU/"); + switch (event) { + case TRAFFIC_MSG_EVT: + dbg_link("TRF-"); + case ACTIVATE_MSG: + dbg_link("ACT -> WW\n"); + l_ptr->state = WORKING_WORKING; + l_ptr->fsm_msg_cnt = 0; + link_set_timer(l_ptr, cont_intv); + break; + case RESET_MSG: + dbg_link("RES -> RR\n"); + link_reset(l_ptr); + l_ptr->state = RESET_RESET; + l_ptr->fsm_msg_cnt = 0; + link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0); + l_ptr->fsm_msg_cnt++; + link_set_timer(l_ptr, cont_intv); + break; + case TIMEOUT_EVT: + dbg_link("TIM "); + if (l_ptr->next_in_no != l_ptr->checkpoint) { + dbg_link("-> WW \n"); + l_ptr->state = WORKING_WORKING; + l_ptr->fsm_msg_cnt = 0; + l_ptr->checkpoint = l_ptr->next_in_no; + if (bclink_acks_missing(l_ptr->owner)) { + link_send_proto_msg(l_ptr, STATE_MSG, + 0, 0, 0, 0, 0); + l_ptr->fsm_msg_cnt++; + } + link_set_timer(l_ptr, cont_intv); + } else if (l_ptr->fsm_msg_cnt < l_ptr->abort_limit) { + dbg_link("Probing %u/%u,timer = %u ms)\n", + l_ptr->fsm_msg_cnt, l_ptr->abort_limit, + cont_intv / 4); + link_send_proto_msg(l_ptr, STATE_MSG, + 1, 0, 0, 0, 0); + l_ptr->fsm_msg_cnt++; + link_set_timer(l_ptr, cont_intv / 4); + } else { /* Link has failed */ + dbg_link("-> RU (%u probes unanswered)\n", + l_ptr->fsm_msg_cnt); + link_reset(l_ptr); + l_ptr->state = RESET_UNKNOWN; + l_ptr->fsm_msg_cnt = 0; + link_send_proto_msg(l_ptr, RESET_MSG, + 0, 0, 0, 0, 0); + l_ptr->fsm_msg_cnt++; + link_set_timer(l_ptr, cont_intv); + } + break; + default: + err("Unknown link event %u in WU state\n", event); + } + break; + case RESET_UNKNOWN: + dbg_link("RU/"); + switch (event) { + case TRAFFIC_MSG_EVT: + dbg_link("TRF-\n"); + break; + case ACTIVATE_MSG: + other = l_ptr->owner->active_links[0]; + if (other && link_working_unknown(other)) { + dbg_link("ACT\n"); + break; + } + dbg_link("ACT -> WW\n"); + l_ptr->state = WORKING_WORKING; + l_ptr->fsm_msg_cnt = 0; + link_activate(l_ptr); + link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); + l_ptr->fsm_msg_cnt++; + link_set_timer(l_ptr, cont_intv); + break; + case RESET_MSG: + dbg_link("RES \n"); + dbg_link(" -> RR\n"); + l_ptr->state = RESET_RESET; + l_ptr->fsm_msg_cnt = 0; + link_send_proto_msg(l_ptr, ACTIVATE_MSG, 1, 0, 0, 0, 0); + l_ptr->fsm_msg_cnt++; + link_set_timer(l_ptr, cont_intv); + break; + case STARTING_EVT: + dbg_link("START-"); + l_ptr->started = 1; + /* fall through */ + case TIMEOUT_EVT: + dbg_link("TIM \n"); + link_send_proto_msg(l_ptr, RESET_MSG, 0, 0, 0, 0, 0); + l_ptr->fsm_msg_cnt++; + link_set_timer(l_ptr, cont_intv); + break; + default: + err("Unknown link event %u in RU state\n", event); + } + break; + case RESET_RESET: + dbg_link("RR/ "); + switch (event) { + case TRAFFIC_MSG_EVT: + dbg_link("TRF-"); + /* fall through */ + case ACTIVATE_MSG: + other = l_ptr->owner->active_links[0]; + if (other && link_working_unknown(other)) { + dbg_link("ACT\n"); + break; + } + dbg_link("ACT -> WW\n"); + l_ptr->state = WORKING_WORKING; + l_ptr->fsm_msg_cnt = 0; + link_activate(l_ptr); + link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); + l_ptr->fsm_msg_cnt++; + link_set_timer(l_ptr, cont_intv); + break; + case RESET_MSG: + dbg_link("RES\n"); + break; + case TIMEOUT_EVT: + dbg_link("TIM\n"); + link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0); + l_ptr->fsm_msg_cnt++; + link_set_timer(l_ptr, cont_intv); + dbg_link("fsm_msg_cnt %u\n", l_ptr->fsm_msg_cnt); + break; + default: + err("Unknown link event %u in RR state\n", event); + } + break; + default: + err("Unknown link state %u/%u\n", l_ptr->state, event); + } +} + +/* + * link_bundle_buf(): Append contents of a buffer to + * the tail of an existing one. + */ + +static int link_bundle_buf(struct link *l_ptr, + struct sk_buff *bundler, + struct sk_buff *buf) +{ + struct tipc_msg *bundler_msg = buf_msg(bundler); + struct tipc_msg *msg = buf_msg(buf); + u32 size = msg_size(msg); + u32 to_pos = align(msg_size(bundler_msg)); + u32 rest = link_max_pkt(l_ptr) - to_pos; + + if (msg_user(bundler_msg) != MSG_BUNDLER) + return 0; + if (msg_type(bundler_msg) != OPEN_MSG) + return 0; + if (rest < align(size)) + return 0; + + skb_put(bundler, (to_pos - msg_size(bundler_msg)) + size); + memcpy(bundler->data + to_pos, buf->data, size); + msg_set_size(bundler_msg, to_pos + size); + msg_set_msgcnt(bundler_msg, msg_msgcnt(bundler_msg) + 1); + dbg("Packed msg # %u(%u octets) into pos %u in buf(#%u)\n", + msg_msgcnt(bundler_msg), size, to_pos, msg_seqno(bundler_msg)); + msg_dbg(msg, "PACKD:"); + buf_discard(buf); + l_ptr->stats.sent_bundled++; + return 1; +} + +static inline void link_add_to_outqueue(struct link *l_ptr, + struct sk_buff *buf, + struct tipc_msg *msg) +{ + u32 ack = mod(l_ptr->next_in_no - 1); + u32 seqno = mod(l_ptr->next_out_no++); + + msg_set_word(msg, 2, ((ack << 16) | seqno)); + msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); + buf->next = NULL; + if (l_ptr->first_out) { + l_ptr->last_out->next = buf; + l_ptr->last_out = buf; + } else + l_ptr->first_out = l_ptr->last_out = buf; + l_ptr->out_queue_size++; +} + +/* + * link_send_buf() is the 'full path' for messages, called from + * inside TIPC when the 'fast path' in tipc_send_buf + * has failed, and from link_send() + */ + +int link_send_buf(struct link *l_ptr, struct sk_buff *buf) +{ + struct tipc_msg *msg = buf_msg(buf); + u32 size = msg_size(msg); + u32 dsz = msg_data_sz(msg); + u32 queue_size = l_ptr->out_queue_size; + u32 imp = msg_tot_importance(msg); + u32 queue_limit = l_ptr->queue_limit[imp]; + u32 max_packet = link_max_pkt(l_ptr); + + msg_set_prevnode(msg, tipc_own_addr); /* If routed message */ + + /* Match msg importance against queue limits: */ + + if (unlikely(queue_size >= queue_limit)) { + if (imp <= TIPC_CRITICAL_IMPORTANCE) { + return link_schedule_port(l_ptr, msg_origport(msg), + size); + } + msg_dbg(msg, "TIPC: Congestion, throwing away\n"); + buf_discard(buf); + if (imp > CONN_MANAGER) { + warn("Resetting <%s>, send queue full", l_ptr->name); + link_reset(l_ptr); + } + return dsz; + } + + /* Fragmentation needed ? */ + + if (size > max_packet) + return link_send_long_buf(l_ptr, buf); + + /* Packet can be queued or sent: */ + + if (queue_size > l_ptr->stats.max_queue_sz) + l_ptr->stats.max_queue_sz = queue_size; + + if (likely(!bearer_congested(l_ptr->b_ptr, l_ptr) && + !link_congested(l_ptr))) { + link_add_to_outqueue(l_ptr, buf, msg); + + if (likely(bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr))) { + l_ptr->unacked_window = 0; + } else { + bearer_schedule(l_ptr->b_ptr, l_ptr); + l_ptr->stats.bearer_congs++; + l_ptr->next_out = buf; + } + return dsz; + } + /* Congestion: can message be bundled ?: */ + + if ((msg_user(msg) != CHANGEOVER_PROTOCOL) && + (msg_user(msg) != MSG_FRAGMENTER)) { + + /* Try adding message to an existing bundle */ + + if (l_ptr->next_out && + link_bundle_buf(l_ptr, l_ptr->last_out, buf)) { + bearer_resolve_congestion(l_ptr->b_ptr, l_ptr); + return dsz; + } + + /* Try creating a new bundle */ + + if (size <= max_packet * 2 / 3) { + struct sk_buff *bundler = buf_acquire(max_packet); + struct tipc_msg bundler_hdr; + + if (bundler) { + msg_init(&bundler_hdr, MSG_BUNDLER, OPEN_MSG, + TIPC_OK, INT_H_SIZE, l_ptr->addr); + memcpy(bundler->data, (unchar *)&bundler_hdr, + INT_H_SIZE); + skb_trim(bundler, INT_H_SIZE); + link_bundle_buf(l_ptr, bundler, buf); + buf = bundler; + msg = buf_msg(buf); + l_ptr->stats.sent_bundles++; + } + } + } + if (!l_ptr->next_out) + l_ptr->next_out = buf; + link_add_to_outqueue(l_ptr, buf, msg); + bearer_resolve_congestion(l_ptr->b_ptr, l_ptr); + return dsz; +} + +/* + * link_send(): same as link_send_buf(), but the link to use has + * not been selected yet, and the the owner node is not locked + * Called by TIPC internal users, e.g. the name distributor + */ + +int link_send(struct sk_buff *buf, u32 dest, u32 selector) +{ + struct link *l_ptr; + struct node *n_ptr; + int res = -ELINKCONG; + + read_lock_bh(&net_lock); + n_ptr = node_select(dest, selector); + if (n_ptr) { + node_lock(n_ptr); + l_ptr = n_ptr->active_links[selector & 1]; + dbg("link_send: found link %x for dest %x\n", l_ptr, dest); + if (l_ptr) { + res = link_send_buf(l_ptr, buf); + } + node_unlock(n_ptr); + } else { + dbg("Attempt to send msg to unknown node:\n"); + msg_dbg(buf_msg(buf),">>>"); + buf_discard(buf); + } + read_unlock_bh(&net_lock); + return res; +} + +/* + * link_send_buf_fast: Entry for data messages where the + * destination link is known and the header is complete, + * inclusive total message length. Very time critical. + * Link is locked. Returns user data length. + */ + +static inline int link_send_buf_fast(struct link *l_ptr, struct sk_buff *buf, + u32 *used_max_pkt) +{ + struct tipc_msg *msg = buf_msg(buf); + int res = msg_data_sz(msg); + + if (likely(!link_congested(l_ptr))) { + if (likely(msg_size(msg) <= link_max_pkt(l_ptr))) { + if (likely(list_empty(&l_ptr->b_ptr->cong_links))) { + link_add_to_outqueue(l_ptr, buf, msg); + if (likely(bearer_send(l_ptr->b_ptr, buf, + &l_ptr->media_addr))) { + l_ptr->unacked_window = 0; + msg_dbg(msg,"SENT_FAST:"); + return res; + } + dbg("failed sent fast...\n"); + bearer_schedule(l_ptr->b_ptr, l_ptr); + l_ptr->stats.bearer_congs++; + l_ptr->next_out = buf; + return res; + } + } + else + *used_max_pkt = link_max_pkt(l_ptr); + } + return link_send_buf(l_ptr, buf); /* All other cases */ +} + +/* + * tipc_send_buf_fast: Entry for data messages where the + * destination node is known and the header is complete, + * inclusive total message length. + * Returns user data length. + */ +int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode) +{ + struct link *l_ptr; + struct node *n_ptr; + int res; + u32 selector = msg_origport(buf_msg(buf)) & 1; + u32 dummy; + + if (destnode == tipc_own_addr) + return port_recv_msg(buf); + + read_lock_bh(&net_lock); + n_ptr = node_select(destnode, selector); + if (likely(n_ptr)) { + node_lock(n_ptr); + l_ptr = n_ptr->active_links[selector]; + dbg("send_fast: buf %x selected %x, destnode = %x\n", + buf, l_ptr, destnode); + if (likely(l_ptr)) { + res = link_send_buf_fast(l_ptr, buf, &dummy); + node_unlock(n_ptr); + read_unlock_bh(&net_lock); + return res; + } + node_unlock(n_ptr); + } + read_unlock_bh(&net_lock); + res = msg_data_sz(buf_msg(buf)); + tipc_reject_msg(buf, TIPC_ERR_NO_NODE); + return res; +} + + +/* + * link_send_sections_fast: Entry for messages where the + * destination processor is known and the header is complete, + * except for total message length. + * Returns user data length or errno. + */ +int link_send_sections_fast(struct port *sender, + struct iovec const *msg_sect, + const u32 num_sect, + u32 destaddr) +{ + struct tipc_msg *hdr = &sender->publ.phdr; + struct link *l_ptr; + struct sk_buff *buf; + struct node *node; + int res; + u32 selector = msg_origport(hdr) & 1; + + assert(destaddr != tipc_own_addr); + +again: + /* + * Try building message using port's max_pkt hint. + * (Must not hold any locks while building message.) + */ + + res = msg_build(hdr, msg_sect, num_sect, sender->max_pkt, + !sender->user_port, &buf); + + read_lock_bh(&net_lock); + node = node_select(destaddr, selector); + if (likely(node)) { + node_lock(node); + l_ptr = node->active_links[selector]; + if (likely(l_ptr)) { + if (likely(buf)) { + res = link_send_buf_fast(l_ptr, buf, + &sender->max_pkt); + if (unlikely(res < 0)) + buf_discard(buf); +exit: + node_unlock(node); + read_unlock_bh(&net_lock); + return res; + } + + /* Exit if build request was invalid */ + + if (unlikely(res < 0)) + goto exit; + + /* Exit if link (or bearer) is congested */ + + if (link_congested(l_ptr) || + !list_empty(&l_ptr->b_ptr->cong_links)) { + res = link_schedule_port(l_ptr, + sender->publ.ref, res); + goto exit; + } + + /* + * Message size exceeds max_pkt hint; update hint, + * then re-try fast path or fragment the message + */ + + sender->max_pkt = link_max_pkt(l_ptr); + node_unlock(node); + read_unlock_bh(&net_lock); + + + if ((msg_hdr_sz(hdr) + res) <= sender->max_pkt) + goto again; + + return link_send_sections_long(sender, msg_sect, + num_sect, destaddr); + } + node_unlock(node); + } + read_unlock_bh(&net_lock); + + /* Couldn't find a link to the destination node */ + + if (buf) + return tipc_reject_msg(buf, TIPC_ERR_NO_NODE); + if (res >= 0) + return port_reject_sections(sender, hdr, msg_sect, num_sect, + TIPC_ERR_NO_NODE); + return res; +} + +/* + * link_send_sections_long(): Entry for long messages where the + * destination node is known and the header is complete, + * inclusive total message length. + * Link and bearer congestion status have been checked to be ok, + * and are ignored if they change. + * + * Note that fragments do not use the full link MTU so that they won't have + * to undergo refragmentation if link changeover causes them to be sent + * over another link with an additional tunnel header added as prefix. + * (Refragmentation will still occur if the other link has a smaller MTU.) + * + * Returns user data length or errno. + */ +static int link_send_sections_long(struct port *sender, + struct iovec const *msg_sect, + u32 num_sect, + u32 destaddr) +{ + struct link *l_ptr; + struct node *node; + struct tipc_msg *hdr = &sender->publ.phdr; + u32 dsz = msg_data_sz(hdr); + u32 max_pkt,fragm_sz,rest; + struct tipc_msg fragm_hdr; + struct sk_buff *buf,*buf_chain,*prev; + u32 fragm_crs,fragm_rest,hsz,sect_rest; + const unchar *sect_crs; + int curr_sect; + u32 fragm_no; + +again: + fragm_no = 1; + max_pkt = sender->max_pkt - INT_H_SIZE; + /* leave room for tunnel header in case of link changeover */ + fragm_sz = max_pkt - INT_H_SIZE; + /* leave room for fragmentation header in each fragment */ + rest = dsz; + fragm_crs = 0; + fragm_rest = 0; + sect_rest = 0; + sect_crs = 0; + curr_sect = -1; + + /* Prepare reusable fragment header: */ + + msg_dbg(hdr, ">FRAGMENTING>"); + msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, + TIPC_OK, INT_H_SIZE, msg_destnode(hdr)); + msg_set_link_selector(&fragm_hdr, sender->publ.ref); + msg_set_size(&fragm_hdr, max_pkt); + msg_set_fragm_no(&fragm_hdr, 1); + + /* Prepare header of first fragment: */ + + buf_chain = buf = buf_acquire(max_pkt); + if (!buf) + return -ENOMEM; + buf->next = NULL; + memcpy(buf->data, (unchar *)&fragm_hdr, INT_H_SIZE); + hsz = msg_hdr_sz(hdr); + memcpy(buf->data + INT_H_SIZE, (unchar *)hdr, hsz); + msg_dbg(buf_msg(buf), ">BUILD>"); + + /* Chop up message: */ + + fragm_crs = INT_H_SIZE + hsz; + fragm_rest = fragm_sz - hsz; + + do { /* For all sections */ + u32 sz; + + if (!sect_rest) { + sect_rest = msg_sect[++curr_sect].iov_len; + sect_crs = (const unchar *)msg_sect[curr_sect].iov_base; + } + + if (sect_rest < fragm_rest) + sz = sect_rest; + else + sz = fragm_rest; + + if (likely(!sender->user_port)) { + if (copy_from_user(buf->data + fragm_crs, sect_crs, sz)) { +error: + for (; buf_chain; buf_chain = buf) { + buf = buf_chain->next; + buf_discard(buf_chain); + } + return -EFAULT; + } + } else + memcpy(buf->data + fragm_crs, sect_crs, sz); + + sect_crs += sz; + sect_rest -= sz; + fragm_crs += sz; + fragm_rest -= sz; + rest -= sz; + + if (!fragm_rest && rest) { + + /* Initiate new fragment: */ + if (rest <= fragm_sz) { + fragm_sz = rest; + msg_set_type(&fragm_hdr,LAST_FRAGMENT); + } else { + msg_set_type(&fragm_hdr, FRAGMENT); + } + msg_set_size(&fragm_hdr, fragm_sz + INT_H_SIZE); + msg_set_fragm_no(&fragm_hdr, ++fragm_no); + prev = buf; + buf = buf_acquire(fragm_sz + INT_H_SIZE); + if (!buf) + goto error; + + buf->next = NULL; + prev->next = buf; + memcpy(buf->data, (unchar *)&fragm_hdr, INT_H_SIZE); + fragm_crs = INT_H_SIZE; + fragm_rest = fragm_sz; + msg_dbg(buf_msg(buf)," >BUILD>"); + } + } + while (rest > 0); + + /* + * Now we have a buffer chain. Select a link and check + * that packet size is still OK + */ + node = node_select(destaddr, sender->publ.ref & 1); + if (likely(node)) { + node_lock(node); + l_ptr = node->active_links[sender->publ.ref & 1]; + if (!l_ptr) { + node_unlock(node); + goto reject; + } + if (link_max_pkt(l_ptr) < max_pkt) { + sender->max_pkt = link_max_pkt(l_ptr); + node_unlock(node); + for (; buf_chain; buf_chain = buf) { + buf = buf_chain->next; + buf_discard(buf_chain); + } + goto again; + } + } else { +reject: + for (; buf_chain; buf_chain = buf) { + buf = buf_chain->next; + buf_discard(buf_chain); + } + return port_reject_sections(sender, hdr, msg_sect, num_sect, + TIPC_ERR_NO_NODE); + } + + /* Append whole chain to send queue: */ + + buf = buf_chain; + l_ptr->long_msg_seq_no = mod(l_ptr->long_msg_seq_no + 1); + if (!l_ptr->next_out) + l_ptr->next_out = buf_chain; + l_ptr->stats.sent_fragmented++; + while (buf) { + struct sk_buff *next = buf->next; + struct tipc_msg *msg = buf_msg(buf); + + l_ptr->stats.sent_fragments++; + msg_set_long_msgno(msg, l_ptr->long_msg_seq_no); + link_add_to_outqueue(l_ptr, buf, msg); + msg_dbg(msg, ">ADD>"); + buf = next; + } + + /* Send it, if possible: */ + + link_push_queue(l_ptr); + node_unlock(node); + return dsz; +} + +/* + * link_push_packet: Push one unsent packet to the media + */ +u32 link_push_packet(struct link *l_ptr) +{ + struct sk_buff *buf = l_ptr->first_out; + u32 r_q_size = l_ptr->retransm_queue_size; + u32 r_q_head = l_ptr->retransm_queue_head; + + /* Step to position where retransmission failed, if any, */ + /* consider that buffers may have been released in meantime */ + + if (r_q_size && buf) { + u32 last = lesser(mod(r_q_head + r_q_size), + link_last_sent(l_ptr)); + u32 first = msg_seqno(buf_msg(buf)); + + while (buf && less(first, r_q_head)) { + first = mod(first + 1); + buf = buf->next; + } + l_ptr->retransm_queue_head = r_q_head = first; + l_ptr->retransm_queue_size = r_q_size = mod(last - first); + } + + /* Continue retransmission now, if there is anything: */ + + if (r_q_size && buf && !skb_cloned(buf)) { + msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1)); + msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in); + if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { + msg_dbg(buf_msg(buf), ">DEF-RETR>"); + l_ptr->retransm_queue_head = mod(++r_q_head); + l_ptr->retransm_queue_size = --r_q_size; + l_ptr->stats.retransmitted++; + return TIPC_OK; + } else { + l_ptr->stats.bearer_congs++; + msg_dbg(buf_msg(buf), "|>DEF-RETR>"); + return PUSH_FAILED; + } + } + + /* Send deferred protocol message, if any: */ + + buf = l_ptr->proto_msg_queue; + if (buf) { + msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1)); + msg_set_bcast_ack(buf_msg(buf),l_ptr->owner->bclink.last_in); + if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { + msg_dbg(buf_msg(buf), ">DEF-PROT>"); + l_ptr->unacked_window = 0; + buf_discard(buf); + l_ptr->proto_msg_queue = 0; + return TIPC_OK; + } else { + msg_dbg(buf_msg(buf), "|>DEF-PROT>"); + l_ptr->stats.bearer_congs++; + return PUSH_FAILED; + } + } + + /* Send one deferred data message, if send window not full: */ + + buf = l_ptr->next_out; + if (buf) { + struct tipc_msg *msg = buf_msg(buf); + u32 next = msg_seqno(msg); + u32 first = msg_seqno(buf_msg(l_ptr->first_out)); + + if (mod(next - first) < l_ptr->queue_limit[0]) { + msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); + msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); + if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { + if (msg_user(msg) == MSG_BUNDLER) + msg_set_type(msg, CLOSED_MSG); + msg_dbg(msg, ">PUSH-DATA>"); + l_ptr->next_out = buf->next; + return TIPC_OK; + } else { + msg_dbg(msg, "|PUSH-DATA|"); + l_ptr->stats.bearer_congs++; + return PUSH_FAILED; + } + } + } + return PUSH_FINISHED; +} + +/* + * push_queue(): push out the unsent messages of a link where + * congestion has abated. Node is locked + */ +void link_push_queue(struct link *l_ptr) +{ + u32 res; + + if (bearer_congested(l_ptr->b_ptr, l_ptr)) + return; + + do { + res = link_push_packet(l_ptr); + } + while (res == TIPC_OK); + if (res == PUSH_FAILED) + bearer_schedule(l_ptr->b_ptr, l_ptr); +} + +void link_retransmit(struct link *l_ptr, struct sk_buff *buf, + u32 retransmits) +{ + struct tipc_msg *msg; + + dbg("Retransmitting %u in link %x\n", retransmits, l_ptr); + + if (bearer_congested(l_ptr->b_ptr, l_ptr) && buf && !skb_cloned(buf)) { + msg_dbg(buf_msg(buf), ">NO_RETR->BCONG>"); + dbg_print_link(l_ptr, " "); + l_ptr->retransm_queue_head = msg_seqno(buf_msg(buf)); + l_ptr->retransm_queue_size = retransmits; + return; + } + while (retransmits && (buf != l_ptr->next_out) && buf && !skb_cloned(buf)) { + msg = buf_msg(buf); + msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); + msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); + if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { + /* Catch if retransmissions fail repeatedly: */ + if (l_ptr->last_retransmitted == msg_seqno(msg)) { + if (++l_ptr->stale_count > 100) { + msg_print(CONS, buf_msg(buf), ">RETR>"); + info("...Retransmitted %u times\n", + l_ptr->stale_count); + link_print(l_ptr, CONS, "Resetting Link\n");; + link_reset(l_ptr); + break; + } + } else { + l_ptr->stale_count = 0; + } + l_ptr->last_retransmitted = msg_seqno(msg); + + msg_dbg(buf_msg(buf), ">RETR>"); + buf = buf->next; + retransmits--; + l_ptr->stats.retransmitted++; + } else { + bearer_schedule(l_ptr->b_ptr, l_ptr); + l_ptr->stats.bearer_congs++; + l_ptr->retransm_queue_head = msg_seqno(buf_msg(buf)); + l_ptr->retransm_queue_size = retransmits; + return; + } + } + l_ptr->retransm_queue_head = l_ptr->retransm_queue_size = 0; +} + +/* + * link_recv_non_seq: Receive packets which are outside + * the link sequence flow + */ + +static void link_recv_non_seq(struct sk_buff *buf) +{ + struct tipc_msg *msg = buf_msg(buf); + + if (msg_user(msg) == LINK_CONFIG) + disc_recv_msg(buf); + else + bclink_recv_pkt(buf); +} + +/** + * link_insert_deferred_queue - insert deferred messages back into receive chain + */ + +static struct sk_buff *link_insert_deferred_queue(struct link *l_ptr, + struct sk_buff *buf) +{ + u32 seq_no; + + if (l_ptr->oldest_deferred_in == NULL) + return buf; + + seq_no = msg_seqno(buf_msg(l_ptr->oldest_deferred_in)); + if (seq_no == mod(l_ptr->next_in_no)) { + l_ptr->newest_deferred_in->next = buf; + buf = l_ptr->oldest_deferred_in; + l_ptr->oldest_deferred_in = NULL; + l_ptr->deferred_inqueue_sz = 0; + } + return buf; +} + +void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr) +{ + read_lock_bh(&net_lock); + while (head) { + struct bearer *b_ptr; + struct node *n_ptr; + struct link *l_ptr; + struct sk_buff *crs; + struct sk_buff *buf = head; + struct tipc_msg *msg = buf_msg(buf); + u32 seq_no = msg_seqno(msg); + u32 ackd = msg_ack(msg); + u32 released = 0; + int type; + + b_ptr = (struct bearer *)tb_ptr; + TIPC_SKB_CB(buf)->handle = b_ptr; + + head = head->next; + if (unlikely(msg_version(msg) != TIPC_VERSION)) + goto cont; +#if 0 + if (msg_user(msg) != LINK_PROTOCOL) +#endif + msg_dbg(msg,"links[b_ptr->identity]; + if (unlikely(!l_ptr)) { + node_unlock(n_ptr); + goto cont; + } + /* + * Release acked messages + */ + if (less(n_ptr->bclink.acked, msg_bcast_ack(msg))) { + if (node_is_up(n_ptr) && n_ptr->bclink.supported) + bclink_acknowledge(n_ptr, msg_bcast_ack(msg)); + } + + crs = l_ptr->first_out; + while ((crs != l_ptr->next_out) && + less_eq(msg_seqno(buf_msg(crs)), ackd)) { + struct sk_buff *next = crs->next; + + buf_discard(crs); + crs = next; + released++; + } + if (released) { + l_ptr->first_out = crs; + l_ptr->out_queue_size -= released; + } + if (unlikely(l_ptr->next_out)) + link_push_queue(l_ptr); + if (unlikely(!list_empty(&l_ptr->waiting_ports))) + link_wakeup_ports(l_ptr, 0); + if (unlikely(++l_ptr->unacked_window >= TIPC_MIN_LINK_WIN)) { + l_ptr->stats.sent_acks++; + link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); + } + +protocol_check: + if (likely(link_working_working(l_ptr))) { + if (likely(seq_no == mod(l_ptr->next_in_no))) { + l_ptr->next_in_no++; + if (unlikely(l_ptr->oldest_deferred_in)) + head = link_insert_deferred_queue(l_ptr, + head); + if (likely(msg_is_dest(msg, tipc_own_addr))) { +deliver: + if (likely(msg_isdata(msg))) { + node_unlock(n_ptr); + port_recv_msg(buf); + continue; + } + switch (msg_user(msg)) { + case MSG_BUNDLER: + l_ptr->stats.recv_bundles++; + l_ptr->stats.recv_bundled += + msg_msgcnt(msg); + node_unlock(n_ptr); + link_recv_bundle(buf); + continue; + case ROUTE_DISTRIBUTOR: + node_unlock(n_ptr); + cluster_recv_routing_table(buf); + continue; + case NAME_DISTRIBUTOR: + node_unlock(n_ptr); + named_recv(buf); + continue; + case CONN_MANAGER: + node_unlock(n_ptr); + port_recv_proto_msg(buf); + continue; + case MSG_FRAGMENTER: + l_ptr->stats.recv_fragments++; + if (link_recv_fragment( + &l_ptr->defragm_buf, + &buf, &msg)) { + l_ptr->stats.recv_fragmented++; + goto deliver; + } + break; + case CHANGEOVER_PROTOCOL: + type = msg_type(msg); + if (link_recv_changeover_msg( + &l_ptr, &buf)) { + msg = buf_msg(buf); + seq_no = msg_seqno(msg); + TIPC_SKB_CB(buf)->handle + = b_ptr; + if (type == ORIGINAL_MSG) + goto deliver; + goto protocol_check; + } + break; + } + } + node_unlock(n_ptr); + net_route_msg(buf); + continue; + } + link_handle_out_of_seq_msg(l_ptr, buf); + head = link_insert_deferred_queue(l_ptr, head); + node_unlock(n_ptr); + continue; + } + + if (msg_user(msg) == LINK_PROTOCOL) { + link_recv_proto_msg(l_ptr, buf); + head = link_insert_deferred_queue(l_ptr, head); + node_unlock(n_ptr); + continue; + } + msg_dbg(msg,"NSEQnext = head; + head = buf; + node_unlock(n_ptr); + continue; + } + node_unlock(n_ptr); +cont: + buf_discard(buf); + } + read_unlock_bh(&net_lock); +} + +/* + * link_defer_buf(): Sort a received out-of-sequence packet + * into the deferred reception queue. + * Returns the increase of the queue length,i.e. 0 or 1 + */ + +u32 link_defer_pkt(struct sk_buff **head, + struct sk_buff **tail, + struct sk_buff *buf) +{ + struct sk_buff *prev = 0; + struct sk_buff *crs = *head; + u32 seq_no = msg_seqno(buf_msg(buf)); + + buf->next = NULL; + + /* Empty queue ? */ + if (*head == NULL) { + *head = *tail = buf; + return 1; + } + + /* Last ? */ + if (less(msg_seqno(buf_msg(*tail)), seq_no)) { + (*tail)->next = buf; + *tail = buf; + return 1; + } + + /* Scan through queue and sort it in */ + do { + struct tipc_msg *msg = buf_msg(crs); + + if (less(seq_no, msg_seqno(msg))) { + buf->next = crs; + if (prev) + prev->next = buf; + else + *head = buf; + return 1; + } + if (seq_no == msg_seqno(msg)) { + break; + } + prev = crs; + crs = crs->next; + } + while (crs); + + /* Message is a duplicate of an existing message */ + + buf_discard(buf); + return 0; +} + +/** + * link_handle_out_of_seq_msg - handle arrival of out-of-sequence packet + */ + +static void link_handle_out_of_seq_msg(struct link *l_ptr, + struct sk_buff *buf) +{ + u32 seq_no = msg_seqno(buf_msg(buf)); + + if (likely(msg_user(buf_msg(buf)) == LINK_PROTOCOL)) { + link_recv_proto_msg(l_ptr, buf); + return; + } + + dbg("rx OOS msg: seq_no %u, expecting %u (%u)\n", + seq_no, mod(l_ptr->next_in_no), l_ptr->next_in_no); + + /* Record OOS packet arrival (force mismatch on next timeout) */ + + l_ptr->checkpoint--; + + /* + * Discard packet if a duplicate; otherwise add it to deferred queue + * and notify peer of gap as per protocol specification + */ + + if (less(seq_no, mod(l_ptr->next_in_no))) { + l_ptr->stats.duplicates++; + buf_discard(buf); + return; + } + + if (link_defer_pkt(&l_ptr->oldest_deferred_in, + &l_ptr->newest_deferred_in, buf)) { + l_ptr->deferred_inqueue_sz++; + l_ptr->stats.deferred_recv++; + if ((l_ptr->deferred_inqueue_sz % 16) == 1) + link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); + } else + l_ptr->stats.duplicates++; +} + +/* + * Send protocol message to the other endpoint. + */ +void link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg, + u32 gap, u32 tolerance, u32 priority, u32 ack_mtu) +{ + struct sk_buff *buf = 0; + struct tipc_msg *msg = l_ptr->pmsg; + u32 msg_size = sizeof(l_ptr->proto_msg); + + if (link_blocked(l_ptr)) + return; + msg_set_type(msg, msg_typ); + msg_set_net_plane(msg, l_ptr->b_ptr->net_plane); + msg_set_bcast_ack(msg, mod(l_ptr->owner->bclink.last_in)); + msg_set_last_bcast(msg, bclink_get_last_sent()); + + if (msg_typ == STATE_MSG) { + u32 next_sent = mod(l_ptr->next_out_no); + + if (!link_is_up(l_ptr)) + return; + if (l_ptr->next_out) + next_sent = msg_seqno(buf_msg(l_ptr->next_out)); + msg_set_next_sent(msg, next_sent); + if (l_ptr->oldest_deferred_in) { + u32 rec = msg_seqno(buf_msg(l_ptr->oldest_deferred_in)); + gap = mod(rec - mod(l_ptr->next_in_no)); + } + msg_set_seq_gap(msg, gap); + if (gap) + l_ptr->stats.sent_nacks++; + msg_set_link_tolerance(msg, tolerance); + msg_set_linkprio(msg, priority); + msg_set_max_pkt(msg, ack_mtu); + msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); + msg_set_probe(msg, probe_msg != 0); + if (probe_msg) { + u32 mtu = l_ptr->max_pkt; + + if ((mtu < l_ptr->max_pkt_target) && + link_working_working(l_ptr) && + l_ptr->fsm_msg_cnt) { + msg_size = (mtu + (l_ptr->max_pkt_target - mtu)/2 + 2) & ~3; + if (l_ptr->max_pkt_probes == 10) { + l_ptr->max_pkt_target = (msg_size - 4); + l_ptr->max_pkt_probes = 0; + msg_size = (mtu + (l_ptr->max_pkt_target - mtu)/2 + 2) & ~3; + } + l_ptr->max_pkt_probes++; + } + + l_ptr->stats.sent_probes++; + } + l_ptr->stats.sent_states++; + } else { /* RESET_MSG or ACTIVATE_MSG */ + msg_set_ack(msg, mod(l_ptr->reset_checkpoint - 1)); + msg_set_seq_gap(msg, 0); + msg_set_next_sent(msg, 1); + msg_set_link_tolerance(msg, l_ptr->tolerance); + msg_set_linkprio(msg, l_ptr->priority); + msg_set_max_pkt(msg, l_ptr->max_pkt_target); + } + + if (node_has_redundant_links(l_ptr->owner)) { + msg_set_redundant_link(msg); + } else { + msg_clear_redundant_link(msg); + } + msg_set_linkprio(msg, l_ptr->priority); + + /* Ensure sequence number will not fit : */ + + msg_set_seqno(msg, mod(l_ptr->next_out_no + (0xffff/2))); + + /* Congestion? */ + + if (bearer_congested(l_ptr->b_ptr, l_ptr)) { + if (!l_ptr->proto_msg_queue) { + l_ptr->proto_msg_queue = + buf_acquire(sizeof(l_ptr->proto_msg)); + } + buf = l_ptr->proto_msg_queue; + if (!buf) + return; + memcpy(buf->data, (unchar *)msg, sizeof(l_ptr->proto_msg)); + return; + } + msg_set_timestamp(msg, jiffies_to_msecs(jiffies)); + + /* Message can be sent */ + + msg_dbg(msg, ">>"); + + buf = buf_acquire(msg_size); + if (!buf) + return; + + memcpy(buf->data, (unchar *)msg, sizeof(l_ptr->proto_msg)); + msg_set_size(buf_msg(buf), msg_size); + + if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { + l_ptr->unacked_window = 0; + buf_discard(buf); + return; + } + + /* New congestion */ + bearer_schedule(l_ptr->b_ptr, l_ptr); + l_ptr->proto_msg_queue = buf; + l_ptr->stats.bearer_congs++; +} + +/* + * Receive protocol message : + * Note that network plane id propagates through the network, and may + * change at any time. The node with lowest address rules + */ + +static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf) +{ + u32 rec_gap = 0; + u32 max_pkt_info; + u32 max_pkt_ack; + u32 msg_tol; + struct tipc_msg *msg = buf_msg(buf); + + dbg("AT(%u):", jiffies_to_msecs(jiffies)); + msg_dbg(msg, "<<"); + if (link_blocked(l_ptr)) + goto exit; + + /* record unnumbered packet arrival (force mismatch on next timeout) */ + + l_ptr->checkpoint--; + + if (l_ptr->b_ptr->net_plane != msg_net_plane(msg)) + if (tipc_own_addr > msg_prevnode(msg)) + l_ptr->b_ptr->net_plane = msg_net_plane(msg); + + l_ptr->owner->permit_changeover = msg_redundant_link(msg); + + switch (msg_type(msg)) { + + case RESET_MSG: + if (!link_working_unknown(l_ptr) && l_ptr->peer_session) { + if (msg_session(msg) == l_ptr->peer_session) { + dbg("Duplicate RESET: %u<->%u\n", + msg_session(msg), l_ptr->peer_session); + break; /* duplicate: ignore */ + } + } + /* fall thru' */ + case ACTIVATE_MSG: + /* Update link settings according other endpoint's values */ + + strcpy((strrchr(l_ptr->name, ':') + 1), (char *)msg_data(msg)); + + if ((msg_tol = msg_link_tolerance(msg)) && + (msg_tol > l_ptr->tolerance)) + link_set_supervision_props(l_ptr, msg_tol); + + if (msg_linkprio(msg) > l_ptr->priority) + l_ptr->priority = msg_linkprio(msg); + + max_pkt_info = msg_max_pkt(msg); + if (max_pkt_info) { + if (max_pkt_info < l_ptr->max_pkt_target) + l_ptr->max_pkt_target = max_pkt_info; + if (l_ptr->max_pkt > l_ptr->max_pkt_target) + l_ptr->max_pkt = l_ptr->max_pkt_target; + } else { + l_ptr->max_pkt = l_ptr->max_pkt_target; + } + l_ptr->owner->bclink.supported = (max_pkt_info != 0); + + link_state_event(l_ptr, msg_type(msg)); + + l_ptr->peer_session = msg_session(msg); + l_ptr->peer_bearer_id = msg_bearer_id(msg); + + /* Synchronize broadcast sequence numbers */ + if (!node_has_redundant_links(l_ptr->owner)) { + l_ptr->owner->bclink.last_in = mod(msg_last_bcast(msg)); + } + break; + case STATE_MSG: + + if ((msg_tol = msg_link_tolerance(msg))) + link_set_supervision_props(l_ptr, msg_tol); + + if (msg_linkprio(msg) && + (msg_linkprio(msg) != l_ptr->priority)) { + warn("Changing prio <%s>: %u->%u\n", + l_ptr->name, l_ptr->priority, msg_linkprio(msg)); + l_ptr->priority = msg_linkprio(msg); + link_reset(l_ptr); /* Enforce change to take effect */ + break; + } + link_state_event(l_ptr, TRAFFIC_MSG_EVT); + l_ptr->stats.recv_states++; + if (link_reset_unknown(l_ptr)) + break; + + if (less_eq(mod(l_ptr->next_in_no), msg_next_sent(msg))) { + rec_gap = mod(msg_next_sent(msg) - + mod(l_ptr->next_in_no)); + } + + max_pkt_ack = msg_max_pkt(msg); + if (max_pkt_ack > l_ptr->max_pkt) { + dbg("Link <%s> updated MTU %u -> %u\n", + l_ptr->name, l_ptr->max_pkt, max_pkt_ack); + l_ptr->max_pkt = max_pkt_ack; + l_ptr->max_pkt_probes = 0; + } + + max_pkt_ack = 0; + if (msg_probe(msg)) { + l_ptr->stats.recv_probes++; + if (msg_size(msg) > sizeof(l_ptr->proto_msg)) { + max_pkt_ack = msg_size(msg); + } + } + + /* Protocol message before retransmits, reduce loss risk */ + + bclink_check_gap(l_ptr->owner, msg_last_bcast(msg)); + + if (rec_gap || (msg_probe(msg))) { + link_send_proto_msg(l_ptr, STATE_MSG, + 0, rec_gap, 0, 0, max_pkt_ack); + } + if (msg_seq_gap(msg)) { + msg_dbg(msg, "With Gap:"); + l_ptr->stats.recv_nacks++; + link_retransmit(l_ptr, l_ptr->first_out, + msg_seq_gap(msg)); + } + break; + default: + msg_dbg(buf_msg(buf), "owner->active_links[selector & 1]; + if (!link_is_up(tunnel)) + return; + msg_set_size(tunnel_hdr, length + INT_H_SIZE); + buf = buf_acquire(length + INT_H_SIZE); + if (!buf) + return; + memcpy(buf->data, (unchar *)tunnel_hdr, INT_H_SIZE); + memcpy(buf->data + INT_H_SIZE, (unchar *)msg, length); + dbg("%c->%c:", l_ptr->b_ptr->net_plane, tunnel->b_ptr->net_plane); + msg_dbg(buf_msg(buf), ">SEND>"); + assert(tunnel); + link_send_buf(tunnel, buf); +} + + + +/* + * changeover(): Send whole message queue via the remaining link + * Owner node is locked. + */ + +void link_changeover(struct link *l_ptr) +{ + u32 msgcount = l_ptr->out_queue_size; + struct sk_buff *crs = l_ptr->first_out; + struct link *tunnel = l_ptr->owner->active_links[0]; + int split_bundles = node_has_redundant_links(l_ptr->owner); + struct tipc_msg tunnel_hdr; + + if (!tunnel) + return; + + if (!l_ptr->owner->permit_changeover) + return; + + msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL, + ORIGINAL_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr); + msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id); + msg_set_msgcnt(&tunnel_hdr, msgcount); + if (!l_ptr->first_out) { + struct sk_buff *buf; + + assert(!msgcount); + buf = buf_acquire(INT_H_SIZE); + if (buf) { + memcpy(buf->data, (unchar *)&tunnel_hdr, INT_H_SIZE); + msg_set_size(&tunnel_hdr, INT_H_SIZE); + dbg("%c->%c:", l_ptr->b_ptr->net_plane, + tunnel->b_ptr->net_plane); + msg_dbg(&tunnel_hdr, "EMPTY>SEND>"); + link_send_buf(tunnel, buf); + } else { + warn("Memory squeeze; link changeover failed\n"); + } + return; + } + while (crs) { + struct tipc_msg *msg = buf_msg(crs); + + if ((msg_user(msg) == MSG_BUNDLER) && split_bundles) { + u32 msgcount = msg_msgcnt(msg); + struct tipc_msg *m = msg_get_wrapped(msg); + unchar* pos = (unchar*)m; + + while (msgcount--) { + msg_set_seqno(m,msg_seqno(msg)); + link_tunnel(l_ptr, &tunnel_hdr, m, + msg_link_selector(m)); + pos += align(msg_size(m)); + m = (struct tipc_msg *)pos; + } + } else { + link_tunnel(l_ptr, &tunnel_hdr, msg, + msg_link_selector(msg)); + } + crs = crs->next; + } +} + +void link_send_duplicate(struct link *l_ptr, struct link *tunnel) +{ + struct sk_buff *iter; + struct tipc_msg tunnel_hdr; + + msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL, + DUPLICATE_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr); + msg_set_msgcnt(&tunnel_hdr, l_ptr->out_queue_size); + msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id); + iter = l_ptr->first_out; + while (iter) { + struct sk_buff *outbuf; + struct tipc_msg *msg = buf_msg(iter); + u32 length = msg_size(msg); + + if (msg_user(msg) == MSG_BUNDLER) + msg_set_type(msg, CLOSED_MSG); + msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); /* Update */ + msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); + msg_set_size(&tunnel_hdr, length + INT_H_SIZE); + outbuf = buf_acquire(length + INT_H_SIZE); + if (outbuf == NULL) { + warn("Memory squeeze; buffer duplication failed\n"); + return; + } + memcpy(outbuf->data, (unchar *)&tunnel_hdr, INT_H_SIZE); + memcpy(outbuf->data + INT_H_SIZE, iter->data, length); + dbg("%c->%c:", l_ptr->b_ptr->net_plane, + tunnel->b_ptr->net_plane); + msg_dbg(buf_msg(outbuf), ">SEND>"); + link_send_buf(tunnel, outbuf); + if (!link_is_up(l_ptr)) + return; + iter = iter->next; + } +} + + + +/** + * buf_extract - extracts embedded TIPC message from another message + * @skb: encapsulating message buffer + * @from_pos: offset to extract from + * + * Returns a new message buffer containing an embedded message. The + * encapsulating message itself is left unchanged. + */ + +static struct sk_buff *buf_extract(struct sk_buff *skb, u32 from_pos) +{ + struct tipc_msg *msg = (struct tipc_msg *)(skb->data + from_pos); + u32 size = msg_size(msg); + struct sk_buff *eb; + + eb = buf_acquire(size); + if (eb) + memcpy(eb->data, (unchar *)msg, size); + return eb; +} + +/* + * link_recv_changeover_msg(): Receive tunneled packet sent + * via other link. Node is locked. Return extracted buffer. + */ + +static int link_recv_changeover_msg(struct link **l_ptr, + struct sk_buff **buf) +{ + struct sk_buff *tunnel_buf = *buf; + struct link *dest_link; + struct tipc_msg *msg; + struct tipc_msg *tunnel_msg = buf_msg(tunnel_buf); + u32 msg_typ = msg_type(tunnel_msg); + u32 msg_count = msg_msgcnt(tunnel_msg); + + dest_link = (*l_ptr)->owner->links[msg_bearer_id(tunnel_msg)]; + assert(dest_link != *l_ptr); + if (!dest_link) { + msg_dbg(tunnel_msg, "NOLINK/b_ptr->net_plane, + (*l_ptr)->b_ptr->net_plane); + *l_ptr = dest_link; + msg = msg_get_wrapped(tunnel_msg); + + if (msg_typ == DUPLICATE_MSG) { + if (less(msg_seqno(msg), mod(dest_link->next_in_no))) { + msg_dbg(tunnel_msg, "DROP/exp_msg_count = msg_count; + if (!msg_count) + goto exit; + } else if (dest_link->exp_msg_count == START_CHANGEOVER) { + msg_dbg(tunnel_msg, "BLK/FIRST/exp_msg_count = msg_count; + if (!msg_count) + goto exit; + } + + /* Receive original message */ + + if (dest_link->exp_msg_count == 0) { + msg_dbg(tunnel_msg, "OVERDUE/DROP/exp_msg_count--; + if (less(msg_seqno(msg), dest_link->reset_checkpoint)) { + msg_dbg(tunnel_msg, "DROP/DUPL/data; + u32 rest = insize; + u32 pack_sz = link_max_pkt(l_ptr); + u32 fragm_sz = pack_sz - INT_H_SIZE; + u32 fragm_no = 1; + u32 destaddr = msg_destnode(inmsg); + + if (msg_short(inmsg)) + destaddr = l_ptr->addr; + + if (msg_routed(inmsg)) + msg_set_prevnode(inmsg, tipc_own_addr); + + /* Prepare reusable fragment header: */ + + msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, + TIPC_OK, INT_H_SIZE, destaddr); + msg_set_link_selector(&fragm_hdr, msg_link_selector(inmsg)); + msg_set_long_msgno(&fragm_hdr, mod(l_ptr->long_msg_seq_no++)); + msg_set_fragm_no(&fragm_hdr, fragm_no); + l_ptr->stats.sent_fragmented++; + + /* Chop up message: */ + + while (rest > 0) { + struct sk_buff *fragm; + + if (rest <= fragm_sz) { + fragm_sz = rest; + msg_set_type(&fragm_hdr, LAST_FRAGMENT); + } + fragm = buf_acquire(fragm_sz + INT_H_SIZE); + if (fragm == NULL) { + warn("Memory squeeze; failed to fragment msg\n"); + dsz = -ENOMEM; + goto exit; + } + msg_set_size(&fragm_hdr, fragm_sz + INT_H_SIZE); + memcpy(fragm->data, (unchar *)&fragm_hdr, INT_H_SIZE); + memcpy(fragm->data + INT_H_SIZE, crs, fragm_sz); + + /* Send queued messages first, if any: */ + + l_ptr->stats.sent_fragments++; + link_send_buf(l_ptr, fragm); + if (!link_is_up(l_ptr)) + return dsz; + msg_set_fragm_no(&fragm_hdr, ++fragm_no); + rest -= fragm_sz; + crs += fragm_sz; + msg_set_type(&fragm_hdr, FRAGMENT); + } +exit: + buf_discard(buf); + return dsz; +} + +/* + * A pending message being re-assembled must store certain values + * to handle subsequent fragments correctly. The following functions + * help storing these values in unused, available fields in the + * pending message. This makes dynamic memory allocation unecessary. + */ + +static inline u32 get_long_msg_seqno(struct sk_buff *buf) +{ + return msg_seqno(buf_msg(buf)); +} + +static inline void set_long_msg_seqno(struct sk_buff *buf, u32 seqno) +{ + msg_set_seqno(buf_msg(buf), seqno); +} + +static inline u32 get_fragm_size(struct sk_buff *buf) +{ + return msg_ack(buf_msg(buf)); +} + +static inline void set_fragm_size(struct sk_buff *buf, u32 sz) +{ + msg_set_ack(buf_msg(buf), sz); +} + +static inline u32 get_expected_frags(struct sk_buff *buf) +{ + return msg_bcast_ack(buf_msg(buf)); +} + +static inline void set_expected_frags(struct sk_buff *buf, u32 exp) +{ + msg_set_bcast_ack(buf_msg(buf), exp); +} + +static inline u32 get_timer_cnt(struct sk_buff *buf) +{ + return msg_reroute_cnt(buf_msg(buf)); +} + +static inline void incr_timer_cnt(struct sk_buff *buf) +{ + msg_incr_reroute_cnt(buf_msg(buf)); +} + +/* + * link_recv_fragment(): Called with node lock on. Returns + * the reassembled buffer if message is complete. + */ +int link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, + struct tipc_msg **m) +{ + struct sk_buff *prev = 0; + struct sk_buff *fbuf = *fb; + struct tipc_msg *fragm = buf_msg(fbuf); + struct sk_buff *pbuf = *pending; + u32 long_msg_seq_no = msg_long_msgno(fragm); + + *fb = 0; + msg_dbg(fragm,"FRGnext; + } + + if (!pbuf && (msg_type(fragm) == FIRST_FRAGMENT)) { + struct tipc_msg *imsg = (struct tipc_msg *)msg_data(fragm); + u32 msg_sz = msg_size(imsg); + u32 fragm_sz = msg_data_sz(fragm); + u32 exp_fragm_cnt = msg_sz/fragm_sz + !!(msg_sz % fragm_sz); + u32 max = TIPC_MAX_USER_MSG_SIZE + LONG_H_SIZE; + if (msg_type(imsg) == TIPC_MCAST_MSG) + max = TIPC_MAX_USER_MSG_SIZE + MCAST_H_SIZE; + if (msg_size(imsg) > max) { + msg_dbg(fragm,"next = *pending; + *pending = pbuf; + memcpy(pbuf->data, (unchar *)imsg, msg_data_sz(fragm)); + + /* Prepare buffer for subsequent fragments. */ + + set_long_msg_seqno(pbuf, long_msg_seq_no); + set_fragm_size(pbuf,fragm_sz); + set_expected_frags(pbuf,exp_fragm_cnt - 1); + } else { + warn("Memory squeeze; got no defragmenting buffer\n"); + } + buf_discard(fbuf); + return 0; + } else if (pbuf && (msg_type(fragm) != FIRST_FRAGMENT)) { + u32 dsz = msg_data_sz(fragm); + u32 fsz = get_fragm_size(pbuf); + u32 crs = ((msg_fragm_no(fragm) - 1) * fsz); + u32 exp_frags = get_expected_frags(pbuf) - 1; + memcpy(pbuf->data + crs, msg_data(fragm), dsz); + buf_discard(fbuf); + + /* Is message complete? */ + + if (exp_frags == 0) { + if (prev) + prev->next = pbuf->next; + else + *pending = pbuf->next; + msg_reset_reroute_cnt(buf_msg(pbuf)); + *fb = pbuf; + *m = buf_msg(pbuf); + return 1; + } + set_expected_frags(pbuf,exp_frags); + return 0; + } + dbg(" Discarding orphan fragment %x\n",fbuf); + msg_dbg(fragm,"ORPHAN:"); + dbg("Pending long buffers:\n"); + dbg_print_buf_chain(*pending); + buf_discard(fbuf); + return 0; +} + +/** + * link_check_defragm_bufs - flush stale incoming message fragments + * @l_ptr: pointer to link + */ + +static void link_check_defragm_bufs(struct link *l_ptr) +{ + struct sk_buff *prev = 0; + struct sk_buff *next = 0; + struct sk_buff *buf = l_ptr->defragm_buf; + + if (!buf) + return; + if (!link_working_working(l_ptr)) + return; + while (buf) { + u32 cnt = get_timer_cnt(buf); + + next = buf->next; + if (cnt < 4) { + incr_timer_cnt(buf); + prev = buf; + } else { + dbg(" Discarding incomplete long buffer\n"); + msg_dbg(buf_msg(buf), "LONG:"); + dbg_print_link(l_ptr, "curr:"); + dbg("Pending long buffers:\n"); + dbg_print_buf_chain(l_ptr->defragm_buf); + if (prev) + prev->next = buf->next; + else + l_ptr->defragm_buf = buf->next; + buf_discard(buf); + } + buf = next; + } +} + + + +static void link_set_supervision_props(struct link *l_ptr, u32 tolerance) +{ + l_ptr->tolerance = tolerance; + l_ptr->continuity_interval = + ((tolerance / 4) > 500) ? 500 : tolerance / 4; + l_ptr->abort_limit = tolerance / (l_ptr->continuity_interval / 4); +} + + +void link_set_queue_limits(struct link *l_ptr, u32 window) +{ + /* Data messages from this node, inclusive FIRST_FRAGM */ + l_ptr->queue_limit[DATA_LOW] = window; + l_ptr->queue_limit[DATA_MEDIUM] = (window / 3) * 4; + l_ptr->queue_limit[DATA_HIGH] = (window / 3) * 5; + l_ptr->queue_limit[DATA_CRITICAL] = (window / 3) * 6; + /* Transiting data messages,inclusive FIRST_FRAGM */ + l_ptr->queue_limit[DATA_LOW + 4] = 300; + l_ptr->queue_limit[DATA_MEDIUM + 4] = 600; + l_ptr->queue_limit[DATA_HIGH + 4] = 900; + l_ptr->queue_limit[DATA_CRITICAL + 4] = 1200; + l_ptr->queue_limit[CONN_MANAGER] = 1200; + l_ptr->queue_limit[ROUTE_DISTRIBUTOR] = 1200; + l_ptr->queue_limit[CHANGEOVER_PROTOCOL] = 2500; + l_ptr->queue_limit[NAME_DISTRIBUTOR] = 3000; + /* FRAGMENT and LAST_FRAGMENT packets */ + l_ptr->queue_limit[MSG_FRAGMENTER] = 4000; +} + +/** + * link_find_link - locate link by name + * @name - ptr to link name string + * @node - ptr to area to be filled with ptr to associated node + * + * Caller must hold 'net_lock' to ensure node and bearer are not deleted; + * this also prevents link deletion. + * + * Returns pointer to link (or 0 if invalid link name). + */ + +static struct link *link_find_link(const char *name, struct node **node) +{ + struct link_name link_name_parts; + struct bearer *b_ptr; + struct link *l_ptr; + + if (!link_name_validate(name, &link_name_parts)) + return 0; + + b_ptr = bearer_find_interface(link_name_parts.if_local); + if (!b_ptr) + return 0; + + *node = node_find(link_name_parts.addr_peer); + if (!*node) + return 0; + + l_ptr = (*node)->links[b_ptr->identity]; + if (!l_ptr || strcmp(l_ptr->name, name)) + return 0; + + return l_ptr; +} + +struct sk_buff *link_cmd_config(const void *req_tlv_area, int req_tlv_space, + u16 cmd) +{ + struct tipc_link_config *args; + u32 new_value; + struct link *l_ptr; + struct node *node; + int res; + + if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_CONFIG)) + return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + + args = (struct tipc_link_config *)TLV_DATA(req_tlv_area); + new_value = ntohl(args->value); + + if (!strcmp(args->name, bc_link_name)) { + if ((cmd == TIPC_CMD_SET_LINK_WINDOW) && + (bclink_set_queue_limits(new_value) == 0)) + return cfg_reply_none(); + return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED + " (cannot change setting on broadcast link)"); + } + + read_lock_bh(&net_lock); + l_ptr = link_find_link(args->name, &node); + if (!l_ptr) { + read_unlock_bh(&net_lock); + return cfg_reply_error_string("link not found"); + } + + node_lock(node); + res = -EINVAL; + switch (cmd) { + case TIPC_CMD_SET_LINK_TOL: + if ((new_value >= TIPC_MIN_LINK_TOL) && + (new_value <= TIPC_MAX_LINK_TOL)) { + link_set_supervision_props(l_ptr, new_value); + link_send_proto_msg(l_ptr, STATE_MSG, + 0, 0, new_value, 0, 0); + res = TIPC_OK; + } + break; + case TIPC_CMD_SET_LINK_PRI: + if (new_value < TIPC_NUM_LINK_PRI) { + l_ptr->priority = new_value; + link_send_proto_msg(l_ptr, STATE_MSG, + 0, 0, 0, new_value, 0); + res = TIPC_OK; + } + break; + case TIPC_CMD_SET_LINK_WINDOW: + if ((new_value >= TIPC_MIN_LINK_WIN) && + (new_value <= TIPC_MAX_LINK_WIN)) { + link_set_queue_limits(l_ptr, new_value); + res = TIPC_OK; + } + break; + } + node_unlock(node); + + read_unlock_bh(&net_lock); + if (res) + return cfg_reply_error_string("cannot change link setting"); + + return cfg_reply_none(); +} + +/** + * link_reset_statistics - reset link statistics + * @l_ptr: pointer to link + */ + +static void link_reset_statistics(struct link *l_ptr) +{ + memset(&l_ptr->stats, 0, sizeof(l_ptr->stats)); + l_ptr->stats.sent_info = l_ptr->next_out_no; + l_ptr->stats.recv_info = l_ptr->next_in_no; +} + +struct sk_buff *link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space) +{ + char *link_name; + struct link *l_ptr; + struct node *node; + + if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME)) + return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + + link_name = (char *)TLV_DATA(req_tlv_area); + if (!strcmp(link_name, bc_link_name)) { + if (bclink_reset_stats()) + return cfg_reply_error_string("link not found"); + return cfg_reply_none(); + } + + read_lock_bh(&net_lock); + l_ptr = link_find_link(link_name, &node); + if (!l_ptr) { + read_unlock_bh(&net_lock); + return cfg_reply_error_string("link not found"); + } + + node_lock(node); + link_reset_statistics(l_ptr); + node_unlock(node); + read_unlock_bh(&net_lock); + return cfg_reply_none(); +} + +/** + * percent - convert count to a percentage of total (rounding up or down) + */ + +static u32 percent(u32 count, u32 total) +{ + return (count * 100 + (total / 2)) / total; +} + +/** + * link_stats - print link statistics + * @name: link name + * @buf: print buffer area + * @buf_size: size of print buffer area + * + * Returns length of print buffer data string (or 0 if error) + */ + +static int link_stats(const char *name, char *buf, const u32 buf_size) +{ + struct print_buf pb; + struct link *l_ptr; + struct node *node; + char *status; + u32 profile_total = 0; + + if (!strcmp(name, bc_link_name)) + return bclink_stats(buf, buf_size); + + printbuf_init(&pb, buf, buf_size); + + read_lock_bh(&net_lock); + l_ptr = link_find_link(name, &node); + if (!l_ptr) { + read_unlock_bh(&net_lock); + return 0; + } + node_lock(node); + + if (link_is_active(l_ptr)) + status = "ACTIVE"; + else if (link_is_up(l_ptr)) + status = "STANDBY"; + else + status = "DEFUNCT"; + tipc_printf(&pb, "Link <%s>\n" + " %s MTU:%u Priority:%u Tolerance:%u ms" + " Window:%u packets\n", + l_ptr->name, status, link_max_pkt(l_ptr), + l_ptr->priority, l_ptr->tolerance, l_ptr->queue_limit[0]); + tipc_printf(&pb, " RX packets:%u fragments:%u/%u bundles:%u/%u\n", + l_ptr->next_in_no - l_ptr->stats.recv_info, + l_ptr->stats.recv_fragments, + l_ptr->stats.recv_fragmented, + l_ptr->stats.recv_bundles, + l_ptr->stats.recv_bundled); + tipc_printf(&pb, " TX packets:%u fragments:%u/%u bundles:%u/%u\n", + l_ptr->next_out_no - l_ptr->stats.sent_info, + l_ptr->stats.sent_fragments, + l_ptr->stats.sent_fragmented, + l_ptr->stats.sent_bundles, + l_ptr->stats.sent_bundled); + profile_total = l_ptr->stats.msg_length_counts; + if (!profile_total) + profile_total = 1; + tipc_printf(&pb, " TX profile sample:%u packets average:%u octets\n" + " 0-64:%u%% -256:%u%% -1024:%u%% -4096:%u%% " + "-16354:%u%% -32768:%u%% -66000:%u%%\n", + l_ptr->stats.msg_length_counts, + l_ptr->stats.msg_lengths_total / profile_total, + percent(l_ptr->stats.msg_length_profile[0], profile_total), + percent(l_ptr->stats.msg_length_profile[1], profile_total), + percent(l_ptr->stats.msg_length_profile[2], profile_total), + percent(l_ptr->stats.msg_length_profile[3], profile_total), + percent(l_ptr->stats.msg_length_profile[4], profile_total), + percent(l_ptr->stats.msg_length_profile[5], profile_total), + percent(l_ptr->stats.msg_length_profile[6], profile_total)); + tipc_printf(&pb, " RX states:%u probes:%u naks:%u defs:%u dups:%u\n", + l_ptr->stats.recv_states, + l_ptr->stats.recv_probes, + l_ptr->stats.recv_nacks, + l_ptr->stats.deferred_recv, + l_ptr->stats.duplicates); + tipc_printf(&pb, " TX states:%u probes:%u naks:%u acks:%u dups:%u\n", + l_ptr->stats.sent_states, + l_ptr->stats.sent_probes, + l_ptr->stats.sent_nacks, + l_ptr->stats.sent_acks, + l_ptr->stats.retransmitted); + tipc_printf(&pb, " Congestion bearer:%u link:%u Send queue max:%u avg:%u\n", + l_ptr->stats.bearer_congs, + l_ptr->stats.link_congs, + l_ptr->stats.max_queue_sz, + l_ptr->stats.queue_sz_counts + ? (l_ptr->stats.accu_queue_sz / l_ptr->stats.queue_sz_counts) + : 0); + + node_unlock(node); + read_unlock_bh(&net_lock); + return printbuf_validate(&pb); +} + +#define MAX_LINK_STATS_INFO 2000 + +struct sk_buff *link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space) +{ + struct sk_buff *buf; + struct tlv_desc *rep_tlv; + int str_len; + + if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME)) + return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + + buf = cfg_reply_alloc(TLV_SPACE(MAX_LINK_STATS_INFO)); + if (!buf) + return NULL; + + rep_tlv = (struct tlv_desc *)buf->data; + + str_len = link_stats((char *)TLV_DATA(req_tlv_area), + (char *)TLV_DATA(rep_tlv), MAX_LINK_STATS_INFO); + if (!str_len) { + buf_discard(buf); + return cfg_reply_error_string("link not found"); + } + + skb_put(buf, TLV_SPACE(str_len)); + TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); + + return buf; +} + +#if 0 +int link_control(const char *name, u32 op, u32 val) +{ + int res = -EINVAL; + struct link *l_ptr; + u32 bearer_id; + struct node * node; + u32 a; + + a = link_name2addr(name, &bearer_id); + read_lock_bh(&net_lock); + node = node_find(a); + if (node) { + node_lock(node); + l_ptr = node->links[bearer_id]; + if (l_ptr) { + if (op == TIPC_REMOVE_LINK) { + struct bearer *b_ptr = l_ptr->b_ptr; + spin_lock_bh(&b_ptr->publ.lock); + link_delete(l_ptr); + spin_unlock_bh(&b_ptr->publ.lock); + } + if (op == TIPC_CMD_BLOCK_LINK) { + link_reset(l_ptr); + l_ptr->blocked = 1; + } + if (op == TIPC_CMD_UNBLOCK_LINK) { + l_ptr->blocked = 0; + } + res = TIPC_OK; + } + node_unlock(node); + } + read_unlock_bh(&net_lock); + return res; +} +#endif + +/** + * link_get_max_pkt - get maximum packet size to use when sending to destination + * @dest: network address of destination node + * @selector: used to select from set of active links + * + * If no active link can be found, uses default maximum packet size. + */ + +u32 link_get_max_pkt(u32 dest, u32 selector) +{ + struct node *n_ptr; + struct link *l_ptr; + u32 res = MAX_PKT_DEFAULT; + + if (dest == tipc_own_addr) + return MAX_MSG_SIZE; + + read_lock_bh(&net_lock); + n_ptr = node_select(dest, selector); + if (n_ptr) { + node_lock(n_ptr); + l_ptr = n_ptr->active_links[selector & 1]; + if (l_ptr) + res = link_max_pkt(l_ptr); + node_unlock(n_ptr); + } + read_unlock_bh(&net_lock); + return res; +} + +#if 0 +static void link_dump_rec_queue(struct link *l_ptr) +{ + struct sk_buff *crs; + + if (!l_ptr->oldest_deferred_in) { + info("Reception queue empty\n"); + return; + } + info("Contents of Reception queue:\n"); + crs = l_ptr->oldest_deferred_in; + while (crs) { + if (crs->data == (void *)0x0000a3a3) { + info("buffer %x invalid\n", crs); + return; + } + msg_dbg(buf_msg(crs), "In rec queue: \n"); + crs = crs->next; + } +} +#endif + +static void link_dump_send_queue(struct link *l_ptr) +{ + if (l_ptr->next_out) { + info("\nContents of unsent queue:\n"); + dbg_print_buf_chain(l_ptr->next_out); + } + info("\nContents of send queue:\n"); + if (l_ptr->first_out) { + dbg_print_buf_chain(l_ptr->first_out); + } + info("Empty send queue\n"); +} + +static void link_print(struct link *l_ptr, struct print_buf *buf, + const char *str) +{ + tipc_printf(buf, str); + if (link_reset_reset(l_ptr) || link_reset_unknown(l_ptr)) + return; + tipc_printf(buf, "Link %x<%s>:", + l_ptr->addr, l_ptr->b_ptr->publ.name); + tipc_printf(buf, ": NXO(%u):", mod(l_ptr->next_out_no)); + tipc_printf(buf, "NXI(%u):", mod(l_ptr->next_in_no)); + tipc_printf(buf, "SQUE"); + if (l_ptr->first_out) { + tipc_printf(buf, "[%u..", msg_seqno(buf_msg(l_ptr->first_out))); + if (l_ptr->next_out) + tipc_printf(buf, "%u..", + msg_seqno(buf_msg(l_ptr->next_out))); + tipc_printf(buf, "%u]", + msg_seqno(buf_msg + (l_ptr->last_out)), l_ptr->out_queue_size); + if ((mod(msg_seqno(buf_msg(l_ptr->last_out)) - + msg_seqno(buf_msg(l_ptr->first_out))) + != (l_ptr->out_queue_size - 1)) + || (l_ptr->last_out->next != 0)) { + tipc_printf(buf, "\nSend queue inconsistency\n"); + tipc_printf(buf, "first_out= %x ", l_ptr->first_out); + tipc_printf(buf, "next_out= %x ", l_ptr->next_out); + tipc_printf(buf, "last_out= %x ", l_ptr->last_out); + link_dump_send_queue(l_ptr); + } + } else + tipc_printf(buf, "[]"); + tipc_printf(buf, "SQSIZ(%u)", l_ptr->out_queue_size); + if (l_ptr->oldest_deferred_in) { + u32 o = msg_seqno(buf_msg(l_ptr->oldest_deferred_in)); + u32 n = msg_seqno(buf_msg(l_ptr->newest_deferred_in)); + tipc_printf(buf, ":RQUE[%u..%u]", o, n); + if (l_ptr->deferred_inqueue_sz != mod((n + 1) - o)) { + tipc_printf(buf, ":RQSIZ(%u)", + l_ptr->deferred_inqueue_sz); + } + } + if (link_working_unknown(l_ptr)) + tipc_printf(buf, ":WU"); + if (link_reset_reset(l_ptr)) + tipc_printf(buf, ":RR"); + if (link_reset_unknown(l_ptr)) + tipc_printf(buf, ":RU"); + if (link_working_working(l_ptr)) + tipc_printf(buf, ":WW"); + tipc_printf(buf, "\n"); +} + diff --git a/net/tipc/link.h b/net/tipc/link.h new file mode 100644 index 00000000000..e7db3476d84 --- /dev/null +++ b/net/tipc/link.h @@ -0,0 +1,293 @@ +/* + * net/tipc/link.h: Include file for TIPC link code + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2004-2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _TIPC_LINK_H +#define _TIPC_LINK_H + +#include "dbg.h" +#include "msg.h" +#include "bearer.h" +#include "node.h" + +#define PUSH_FAILED 1 +#define PUSH_FINISHED 2 + +/* + * Link states + */ + +#define WORKING_WORKING 560810u +#define WORKING_UNKNOWN 560811u +#define RESET_UNKNOWN 560812u +#define RESET_RESET 560813u + +/* + * Starting value for maximum packet size negotiation on unicast links + * (unless bearer MTU is less) + */ + +#define MAX_PKT_DEFAULT 1500 + +/** + * struct link - TIPC link data structure + * @addr: network address of link's peer node + * @name: link name character string + * @media_addr: media address to use when sending messages over link + * @timer: link timer + * @owner: pointer to peer node + * @link_list: adjacent links in bearer's list of links + * @started: indicates if link has been started + * @checkpoint: reference point for triggering link continuity checking + * @peer_session: link session # being used by peer end of link + * @peer_bearer_id: bearer id used by link's peer endpoint + * @b_ptr: pointer to bearer used by link + * @tolerance: minimum link continuity loss needed to reset link [in ms] + * @continuity_interval: link continuity testing interval [in ms] + * @abort_limit: # of unacknowledged continuity probes needed to reset link + * @state: current state of link FSM + * @blocked: indicates if link has been administratively blocked + * @fsm_msg_cnt: # of protocol messages link FSM has sent in current state + * @proto_msg: template for control messages generated by link + * @pmsg: convenience pointer to "proto_msg" field + * @priority: current link priority + * @queue_limit: outbound message queue congestion thresholds (indexed by user) + * @exp_msg_count: # of tunnelled messages expected during link changeover + * @reset_checkpoint: seq # of last acknowledged message at time of link reset + * @max_pkt: current maximum packet size for this link + * @max_pkt_target: desired maximum packet size for this link + * @max_pkt_probes: # of probes based on current (max_pkt, max_pkt_target) + * @out_queue_size: # of messages in outbound message queue + * @first_out: ptr to first outbound message in queue + * @last_out: ptr to last outbound message in queue + * @next_out_no: next sequence number to use for outbound messages + * @last_retransmitted: sequence number of most recently retransmitted message + * @stale_count: # of identical retransmit requests made by peer + * @next_in_no: next sequence number to expect for inbound messages + * @deferred_inqueue_sz: # of messages in inbound message queue + * @oldest_deferred_in: ptr to first inbound message in queue + * @newest_deferred_in: ptr to last inbound message in queue + * @unacked_window: # of inbound messages rx'd without ack'ing back to peer + * @proto_msg_queue: ptr to (single) outbound control message + * @retransm_queue_size: number of messages to retransmit + * @retransm_queue_head: sequence number of first message to retransmit + * @next_out: ptr to first unsent outbound message in queue + * @waiting_ports: linked list of ports waiting for link congestion to abate + * @long_msg_seq_no: next identifier to use for outbound fragmented messages + * @defragm_buf: list of partially reassembled inbound message fragments + * @stats: collects statistics regarding link activity + * @print_buf: print buffer used to log link activity + */ + +struct link { + u32 addr; + char name[TIPC_MAX_LINK_NAME]; + struct tipc_media_addr media_addr; + struct timer_list timer; + struct node *owner; + struct list_head link_list; + + /* Management and link supervision data */ + int started; + u32 checkpoint; + u32 peer_session; + u32 peer_bearer_id; + struct bearer *b_ptr; + u32 tolerance; + u32 continuity_interval; + u32 abort_limit; + int state; + int blocked; + u32 fsm_msg_cnt; + struct { + unchar hdr[INT_H_SIZE]; + unchar body[TIPC_MAX_IF_NAME]; + } proto_msg; + struct tipc_msg *pmsg; + u32 priority; + u32 queue_limit[15]; /* queue_limit[0]==window limit */ + + /* Changeover */ + u32 exp_msg_count; + u32 reset_checkpoint; + + /* Max packet negotiation */ + u32 max_pkt; + u32 max_pkt_target; + u32 max_pkt_probes; + + /* Sending */ + u32 out_queue_size; + struct sk_buff *first_out; + struct sk_buff *last_out; + u32 next_out_no; + u32 last_retransmitted; + u32 stale_count; + + /* Reception */ + u32 next_in_no; + u32 deferred_inqueue_sz; + struct sk_buff *oldest_deferred_in; + struct sk_buff *newest_deferred_in; + u32 unacked_window; + + /* Congestion handling */ + struct sk_buff *proto_msg_queue; + u32 retransm_queue_size; + u32 retransm_queue_head; + struct sk_buff *next_out; + struct list_head waiting_ports; + + /* Fragmentation/defragmentation */ + u32 long_msg_seq_no; + struct sk_buff *defragm_buf; + + /* Statistics */ + struct { + u32 sent_info; /* used in counting # sent packets */ + u32 recv_info; /* used in counting # recv'd packets */ + u32 sent_states; + u32 recv_states; + u32 sent_probes; + u32 recv_probes; + u32 sent_nacks; + u32 recv_nacks; + u32 sent_acks; + u32 sent_bundled; + u32 sent_bundles; + u32 recv_bundled; + u32 recv_bundles; + u32 retransmitted; + u32 sent_fragmented; + u32 sent_fragments; + u32 recv_fragmented; + u32 recv_fragments; + u32 link_congs; /* # port sends blocked by congestion */ + u32 bearer_congs; + u32 deferred_recv; + u32 duplicates; + + /* for statistical profiling of send queue size */ + + u32 max_queue_sz; + u32 accu_queue_sz; + u32 queue_sz_counts; + + /* for statistical profiling of message lengths */ + + u32 msg_length_counts; + u32 msg_lengths_total; + u32 msg_length_profile[7]; +#if 0 + u32 sent_tunneled; + u32 recv_tunneled; +#endif + } stats; + + struct print_buf print_buf; +}; + +struct port; + +struct link *link_create(struct bearer *b_ptr, const u32 peer, + const struct tipc_media_addr *media_addr); +void link_delete(struct link *l_ptr); +void link_changeover(struct link *l_ptr); +void link_send_duplicate(struct link *l_ptr, struct link *dest); +void link_reset_fragments(struct link *l_ptr); +int link_is_up(struct link *l_ptr); +int link_is_active(struct link *l_ptr); +void link_start(struct link *l_ptr); +u32 link_push_packet(struct link *l_ptr); +void link_stop(struct link *l_ptr); +struct sk_buff *link_cmd_config(const void *req_tlv_area, int req_tlv_space, u16 cmd); +struct sk_buff *link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space); +struct sk_buff *link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space); +void link_reset(struct link *l_ptr); +int link_send(struct sk_buff *buf, u32 dest, u32 selector); +int link_send_buf(struct link *l_ptr, struct sk_buff *buf); +u32 link_get_max_pkt(u32 dest,u32 selector); +int link_send_sections_fast(struct port* sender, + struct iovec const *msg_sect, + const u32 num_sect, + u32 destnode); + +int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf); +void link_tunnel(struct link *l_ptr, struct tipc_msg *tnl_hdr, + struct tipc_msg *msg, u32 selector); +void link_recv_bundle(struct sk_buff *buf); +int link_recv_fragment(struct sk_buff **pending, + struct sk_buff **fb, + struct tipc_msg **msg); +void link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int prob, u32 gap, + u32 tolerance, u32 priority, u32 acked_mtu); +void link_push_queue(struct link *l_ptr); +u32 link_defer_pkt(struct sk_buff **head, struct sk_buff **tail, + struct sk_buff *buf); +void link_wakeup_ports(struct link *l_ptr, int all); +void link_set_queue_limits(struct link *l_ptr, u32 window); +void link_retransmit(struct link *l_ptr, struct sk_buff *start, u32 retransmits); + +/* + * Link sequence number manipulation routines (uses modulo 2**16 arithmetic) + */ + +static inline u32 mod(u32 x) +{ + return x & 0xffffu; +} + +static inline int between(u32 lower, u32 upper, u32 n) +{ + if ((lower < n) && (n < upper)) + return 1; + if ((upper < lower) && ((n > lower) || (n < upper))) + return 1; + return 0; +} + +static inline int less_eq(u32 left, u32 right) +{ + return (mod(right - left) < 32768u); +} + +static inline int less(u32 left, u32 right) +{ + return (less_eq(left, right) && (mod(right) != mod(left))); +} + +static inline u32 lesser(u32 left, u32 right) +{ + return less_eq(left, right) ? left : right; +} + +#endif diff --git a/net/tipc/msg.c b/net/tipc/msg.c new file mode 100644 index 00000000000..c6e90efd59f --- /dev/null +++ b/net/tipc/msg.c @@ -0,0 +1,331 @@ +/* + * net/tipc/msg.c: TIPC message header routines + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "core.h" +#include "addr.h" +#include "dbg.h" +#include "msg.h" +#include "bearer.h" + + +void msg_set_media_addr(struct tipc_msg *m, struct tipc_media_addr *a) +{ + memcpy(&((int *)m)[5], a, sizeof(*a)); +} + +void msg_get_media_addr(struct tipc_msg *m, struct tipc_media_addr *a) +{ + memcpy(a, &((int*)m)[5], sizeof(*a)); +} + + +void msg_print(struct print_buf *buf, struct tipc_msg *msg, const char *str) +{ + u32 usr = msg_user(msg); + tipc_printf(buf, str); + + switch (usr) { + case MSG_BUNDLER: + tipc_printf(buf, "BNDL::"); + tipc_printf(buf, "MSGS(%u):", msg_msgcnt(msg)); + break; + case BCAST_PROTOCOL: + tipc_printf(buf, "BCASTP::"); + break; + case MSG_FRAGMENTER: + tipc_printf(buf, "FRAGM::"); + switch (msg_type(msg)) { + case FIRST_FRAGMENT: + tipc_printf(buf, "FIRST:"); + break; + case FRAGMENT: + tipc_printf(buf, "BODY:"); + break; + case LAST_FRAGMENT: + tipc_printf(buf, "LAST:"); + break; + default: + tipc_printf(buf, "UNKNOWN:%x",msg_type(msg)); + + } + tipc_printf(buf, "NO(%u/%u):",msg_long_msgno(msg), + msg_fragm_no(msg)); + break; + case DATA_LOW: + case DATA_MEDIUM: + case DATA_HIGH: + case DATA_CRITICAL: + tipc_printf(buf, "DAT%u:", msg_user(msg)); + if (msg_short(msg)) { + tipc_printf(buf, "CON:"); + break; + } + switch (msg_type(msg)) { + case TIPC_CONN_MSG: + tipc_printf(buf, "CON:"); + break; + case TIPC_MCAST_MSG: + tipc_printf(buf, "MCST:"); + break; + case TIPC_NAMED_MSG: + tipc_printf(buf, "NAM:"); + break; + case TIPC_DIRECT_MSG: + tipc_printf(buf, "DIR:"); + break; + default: + tipc_printf(buf, "UNKNOWN TYPE %u",msg_type(msg)); + } + if (msg_routed(msg) && !msg_non_seq(msg)) + tipc_printf(buf, "ROUT:"); + if (msg_reroute_cnt(msg)) + tipc_printf(buf, "REROUTED(%u):", + msg_reroute_cnt(msg)); + break; + case NAME_DISTRIBUTOR: + tipc_printf(buf, "NMD::"); + switch (msg_type(msg)) { + case PUBLICATION: + tipc_printf(buf, "PUBL(%u):", (msg_size(msg) - msg_hdr_sz(msg)) / 20); /* Items */ + break; + case WITHDRAWAL: + tipc_printf(buf, "WDRW:"); + break; + default: + tipc_printf(buf, "UNKNOWN:%x",msg_type(msg)); + } + if (msg_routed(msg)) + tipc_printf(buf, "ROUT:"); + if (msg_reroute_cnt(msg)) + tipc_printf(buf, "REROUTED(%u):", + msg_reroute_cnt(msg)); + break; + case CONN_MANAGER: + tipc_printf(buf, "CONN_MNG:"); + switch (msg_type(msg)) { + case CONN_PROBE: + tipc_printf(buf, "PROBE:"); + break; + case CONN_PROBE_REPLY: + tipc_printf(buf, "PROBE_REPLY:"); + break; + case CONN_ACK: + tipc_printf(buf, "CONN_ACK:"); + tipc_printf(buf, "ACK(%u):",msg_msgcnt(msg)); + break; + default: + tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg)); + } + if (msg_routed(msg)) + tipc_printf(buf, "ROUT:"); + if (msg_reroute_cnt(msg)) + tipc_printf(buf, "REROUTED(%u):",msg_reroute_cnt(msg)); + break; + case LINK_PROTOCOL: + tipc_printf(buf, "PROT:TIM(%u):",msg_timestamp(msg)); + switch (msg_type(msg)) { + case STATE_MSG: + tipc_printf(buf, "STATE:"); + tipc_printf(buf, "%s:",msg_probe(msg) ? "PRB" :""); + tipc_printf(buf, "NXS(%u):",msg_next_sent(msg)); + tipc_printf(buf, "GAP(%u):",msg_seq_gap(msg)); + tipc_printf(buf, "LSTBC(%u):",msg_last_bcast(msg)); + break; + case RESET_MSG: + tipc_printf(buf, "RESET:"); + if (msg_size(msg) != msg_hdr_sz(msg)) + tipc_printf(buf, "BEAR:%s:",msg_data(msg)); + break; + case ACTIVATE_MSG: + tipc_printf(buf, "ACTIVATE:"); + break; + default: + tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg)); + } + tipc_printf(buf, "PLANE(%c):",msg_net_plane(msg)); + tipc_printf(buf, "SESS(%u):",msg_session(msg)); + break; + case CHANGEOVER_PROTOCOL: + tipc_printf(buf, "TUNL:"); + switch (msg_type(msg)) { + case DUPLICATE_MSG: + tipc_printf(buf, "DUPL:"); + break; + case ORIGINAL_MSG: + tipc_printf(buf, "ORIG:"); + tipc_printf(buf, "EXP(%u)",msg_msgcnt(msg)); + break; + default: + tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg)); + } + break; + case ROUTE_DISTRIBUTOR: + tipc_printf(buf, "ROUTING_MNG:"); + switch (msg_type(msg)) { + case EXT_ROUTING_TABLE: + tipc_printf(buf, "EXT_TBL:"); + tipc_printf(buf, "TO:%x:",msg_remote_node(msg)); + break; + case LOCAL_ROUTING_TABLE: + tipc_printf(buf, "LOCAL_TBL:"); + tipc_printf(buf, "TO:%x:",msg_remote_node(msg)); + break; + case SLAVE_ROUTING_TABLE: + tipc_printf(buf, "DP_TBL:"); + tipc_printf(buf, "TO:%x:",msg_remote_node(msg)); + break; + case ROUTE_ADDITION: + tipc_printf(buf, "ADD:"); + tipc_printf(buf, "TO:%x:",msg_remote_node(msg)); + break; + case ROUTE_REMOVAL: + tipc_printf(buf, "REMOVE:"); + tipc_printf(buf, "TO:%x:",msg_remote_node(msg)); + break; + default: + tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg)); + } + break; + case LINK_CONFIG: + tipc_printf(buf, "CFG:"); + switch (msg_type(msg)) { + case DSC_REQ_MSG: + tipc_printf(buf, "DSC_REQ:"); + break; + case DSC_RESP_MSG: + tipc_printf(buf, "DSC_RESP:"); + break; + default: + tipc_printf(buf, "UNKNOWN TYPE:%x:",msg_type(msg)); + break; + } + break; + default: + tipc_printf(buf, "UNKNOWN USER:"); + } + + switch (usr) { + case CONN_MANAGER: + case NAME_DISTRIBUTOR: + case DATA_LOW: + case DATA_MEDIUM: + case DATA_HIGH: + case DATA_CRITICAL: + if (msg_short(msg)) + break; /* No error */ + switch (msg_errcode(msg)) { + case TIPC_OK: + break; + case TIPC_ERR_NO_NAME: + tipc_printf(buf, "NO_NAME:"); + break; + case TIPC_ERR_NO_PORT: + tipc_printf(buf, "NO_PORT:"); + break; + case TIPC_ERR_NO_NODE: + tipc_printf(buf, "NO_PROC:"); + break; + case TIPC_ERR_OVERLOAD: + tipc_printf(buf, "OVERLOAD:"); + break; + case TIPC_CONN_SHUTDOWN: + tipc_printf(buf, "SHUTDOWN:"); + break; + default: + tipc_printf(buf, "UNKNOWN ERROR(%x):", + msg_errcode(msg)); + } + default:{} + } + + tipc_printf(buf, "HZ(%u):", msg_hdr_sz(msg)); + tipc_printf(buf, "SZ(%u):", msg_size(msg)); + tipc_printf(buf, "SQNO(%u):", msg_seqno(msg)); + + if (msg_non_seq(msg)) + tipc_printf(buf, "NOSEQ:"); + else { + tipc_printf(buf, "ACK(%u):", msg_ack(msg)); + } + tipc_printf(buf, "BACK(%u):", msg_bcast_ack(msg)); + tipc_printf(buf, "PRND(%x)", msg_prevnode(msg)); + + if (msg_isdata(msg)) { + if (msg_named(msg)) { + tipc_printf(buf, "NTYP(%u):", msg_nametype(msg)); + tipc_printf(buf, "NINST(%u)", msg_nameinst(msg)); + } + } + + if ((usr != LINK_PROTOCOL) && (usr != LINK_CONFIG) && + (usr != MSG_BUNDLER)) { + if (!msg_short(msg)) { + tipc_printf(buf, ":ORIG(%x:%u):", + msg_orignode(msg), msg_origport(msg)); + tipc_printf(buf, ":DEST(%x:%u):", + msg_destnode(msg), msg_destport(msg)); + } else { + tipc_printf(buf, ":OPRT(%u):", msg_origport(msg)); + tipc_printf(buf, ":DPRT(%u):", msg_destport(msg)); + } + if (msg_routed(msg) && !msg_non_seq(msg)) + tipc_printf(buf, ":TSEQN(%u)", msg_transp_seqno(msg)); + } + if (msg_user(msg) == NAME_DISTRIBUTOR) { + tipc_printf(buf, ":ONOD(%x):", msg_orignode(msg)); + tipc_printf(buf, ":DNOD(%x):", msg_destnode(msg)); + if (msg_routed(msg)) { + tipc_printf(buf, ":CSEQN(%u)", msg_transp_seqno(msg)); + } + } + + if (msg_user(msg) == LINK_CONFIG) { + u32* raw = (u32*)msg; + struct tipc_media_addr* orig = (struct tipc_media_addr*)&raw[5]; + tipc_printf(buf, ":REQL(%u):", msg_req_links(msg)); + tipc_printf(buf, ":DDOM(%x):", msg_dest_domain(msg)); + tipc_printf(buf, ":NETID(%u):", msg_bc_netid(msg)); + media_addr_printf(buf, orig); + } + if (msg_user(msg) == BCAST_PROTOCOL) { + tipc_printf(buf, "BCNACK:AFTER(%u):", msg_bcgap_after(msg)); + tipc_printf(buf, "TO(%u):", msg_bcgap_to(msg)); + } + tipc_printf(buf, "\n"); + if ((usr == CHANGEOVER_PROTOCOL) && (msg_msgcnt(msg))) { + msg_print(buf,msg_get_wrapped(msg)," /"); + } + if ((usr == MSG_FRAGMENTER) && (msg_type(msg) == FIRST_FRAGMENT)) { + msg_print(buf,msg_get_wrapped(msg)," /"); + } +} diff --git a/net/tipc/msg.h b/net/tipc/msg.h new file mode 100644 index 00000000000..3dcd23f5188 --- /dev/null +++ b/net/tipc/msg.h @@ -0,0 +1,815 @@ +/* + * net/tipc/msg.h: Include file for TIPC message header routines + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _TIPC_MSG_H +#define _TIPC_MSG_H + +#include + +#define TIPC_VERSION 2 +#define DATA_LOW TIPC_LOW_IMPORTANCE +#define DATA_MEDIUM TIPC_MEDIUM_IMPORTANCE +#define DATA_HIGH TIPC_HIGH_IMPORTANCE +#define DATA_CRITICAL TIPC_CRITICAL_IMPORTANCE +#define SHORT_H_SIZE 24 /* Connected,in cluster */ +#define DIR_MSG_H_SIZE 32 /* Directly addressed messages */ +#define CONN_MSG_H_SIZE 36 /* Routed connected msgs*/ +#define LONG_H_SIZE 40 /* Named Messages */ +#define MCAST_H_SIZE 44 /* Multicast messages */ +#define MAX_H_SIZE 60 /* Inclusive full options */ +#define MAX_MSG_SIZE (MAX_H_SIZE + TIPC_MAX_USER_MSG_SIZE) +#define LINK_CONFIG 13 + + +/* + TIPC user data message header format, version 2 + + - Fundamental definitions available to privileged TIPC users + are located in tipc_msg.h. + - Remaining definitions available to TIPC internal users appear below. +*/ + + +static inline void msg_set_word(struct tipc_msg *m, u32 w, u32 val) +{ + m->hdr[w] = htonl(val); +} + +static inline void msg_set_bits(struct tipc_msg *m, u32 w, + u32 pos, u32 mask, u32 val) +{ + u32 word = msg_word(m,w) & ~(mask << pos); + msg_set_word(m, w, (word |= (val << pos))); +} + +/* + * Word 0 + */ + +static inline u32 msg_version(struct tipc_msg *m) +{ + return msg_bits(m, 0, 29, 7); +} + +static inline void msg_set_version(struct tipc_msg *m) +{ + msg_set_bits(m, 0, 29, 0xf, TIPC_VERSION); +} + +static inline u32 msg_user(struct tipc_msg *m) +{ + return msg_bits(m, 0, 25, 0xf); +} + +static inline u32 msg_isdata(struct tipc_msg *m) +{ + return (msg_user(m) <= DATA_CRITICAL); +} + +static inline void msg_set_user(struct tipc_msg *m, u32 n) +{ + msg_set_bits(m, 0, 25, 0xf, n); +} + +static inline void msg_set_importance(struct tipc_msg *m, u32 i) +{ + msg_set_user(m, i); +} + +static inline void msg_set_hdr_sz(struct tipc_msg *m,u32 n) +{ + msg_set_bits(m, 0, 21, 0xf, n>>2); +} + +static inline int msg_non_seq(struct tipc_msg *m) +{ + return msg_bits(m, 0, 20, 1); +} + +static inline void msg_set_non_seq(struct tipc_msg *m) +{ + msg_set_bits(m, 0, 20, 1, 1); +} + +static inline int msg_dest_droppable(struct tipc_msg *m) +{ + return msg_bits(m, 0, 19, 1); +} + +static inline void msg_set_dest_droppable(struct tipc_msg *m, u32 d) +{ + msg_set_bits(m, 0, 19, 1, d); +} + +static inline int msg_src_droppable(struct tipc_msg *m) +{ + return msg_bits(m, 0, 18, 1); +} + +static inline void msg_set_src_droppable(struct tipc_msg *m, u32 d) +{ + msg_set_bits(m, 0, 18, 1, d); +} + +static inline void msg_set_size(struct tipc_msg *m, u32 sz) +{ + m->hdr[0] = htonl((msg_word(m, 0) & ~0x1ffff) | sz); +} + + +/* + * Word 1 + */ + +static inline void msg_set_type(struct tipc_msg *m, u32 n) +{ + msg_set_bits(m, 1, 29, 0x7, n); +} + +static inline void msg_set_errcode(struct tipc_msg *m, u32 err) +{ + msg_set_bits(m, 1, 25, 0xf, err); +} + +static inline u32 msg_reroute_cnt(struct tipc_msg *m) +{ + return msg_bits(m, 1, 21, 0xf); +} + +static inline void msg_incr_reroute_cnt(struct tipc_msg *m) +{ + msg_set_bits(m, 1, 21, 0xf, msg_reroute_cnt(m) + 1); +} + +static inline void msg_reset_reroute_cnt(struct tipc_msg *m) +{ + msg_set_bits(m, 1, 21, 0xf, 0); +} + +static inline u32 msg_lookup_scope(struct tipc_msg *m) +{ + return msg_bits(m, 1, 19, 0x3); +} + +static inline void msg_set_lookup_scope(struct tipc_msg *m, u32 n) +{ + msg_set_bits(m, 1, 19, 0x3, n); +} + +static inline void msg_set_options(struct tipc_msg *m, const char *opt, u32 sz) +{ + u32 hsz = msg_hdr_sz(m); + char *to = (char *)&m->hdr[hsz/4]; + + if ((hsz < DIR_MSG_H_SIZE) || ((hsz + sz) > MAX_H_SIZE)) + return; + msg_set_bits(m, 1, 16, 0x7, (hsz - 28)/4); + msg_set_hdr_sz(m, hsz + sz); + memcpy(to, opt, sz); +} + +static inline u32 msg_bcast_ack(struct tipc_msg *m) +{ + return msg_bits(m, 1, 0, 0xffff); +} + +static inline void msg_set_bcast_ack(struct tipc_msg *m, u32 n) +{ + msg_set_bits(m, 1, 0, 0xffff, n); +} + + +/* + * Word 2 + */ + +static inline u32 msg_ack(struct tipc_msg *m) +{ + return msg_bits(m, 2, 16, 0xffff); +} + +static inline void msg_set_ack(struct tipc_msg *m, u32 n) +{ + msg_set_bits(m, 2, 16, 0xffff, n); +} + +static inline u32 msg_seqno(struct tipc_msg *m) +{ + return msg_bits(m, 2, 0, 0xffff); +} + +static inline void msg_set_seqno(struct tipc_msg *m, u32 n) +{ + msg_set_bits(m, 2, 0, 0xffff, n); +} + + +/* + * Words 3-10 + */ + + +static inline void msg_set_prevnode(struct tipc_msg *m, u32 a) +{ + msg_set_word(m, 3, a); +} + +static inline void msg_set_origport(struct tipc_msg *m, u32 p) +{ + msg_set_word(m, 4, p); +} + +static inline void msg_set_destport(struct tipc_msg *m, u32 p) +{ + msg_set_word(m, 5, p); +} + +static inline void msg_set_mc_netid(struct tipc_msg *m, u32 p) +{ + msg_set_word(m, 5, p); +} + +static inline void msg_set_orignode(struct tipc_msg *m, u32 a) +{ + msg_set_word(m, 6, a); +} + +static inline void msg_set_destnode(struct tipc_msg *m, u32 a) +{ + msg_set_word(m, 7, a); +} + +static inline int msg_is_dest(struct tipc_msg *m, u32 d) +{ + return(msg_short(m) || (msg_destnode(m) == d)); +} + +static inline u32 msg_routed(struct tipc_msg *m) +{ + if (likely(msg_short(m))) + return 0; + return(msg_destnode(m) ^ msg_orignode(m)) >> 11; +} + +static inline void msg_set_nametype(struct tipc_msg *m, u32 n) +{ + msg_set_word(m, 8, n); +} + +static inline u32 msg_transp_seqno(struct tipc_msg *m) +{ + return msg_word(m, 8); +} + +static inline void msg_set_timestamp(struct tipc_msg *m, u32 n) +{ + msg_set_word(m, 8, n); +} + +static inline u32 msg_timestamp(struct tipc_msg *m) +{ + return msg_word(m, 8); +} + +static inline void msg_set_transp_seqno(struct tipc_msg *m, u32 n) +{ + msg_set_word(m, 8, n); +} + +static inline void msg_set_namelower(struct tipc_msg *m, u32 n) +{ + msg_set_word(m, 9, n); +} + +static inline void msg_set_nameinst(struct tipc_msg *m, u32 n) +{ + msg_set_namelower(m, n); +} + +static inline void msg_set_nameupper(struct tipc_msg *m, u32 n) +{ + msg_set_word(m, 10, n); +} + +static inline struct tipc_msg *msg_get_wrapped(struct tipc_msg *m) +{ + return (struct tipc_msg *)msg_data(m); +} + +static inline void msg_expand(struct tipc_msg *m, u32 destnode) +{ + if (!msg_short(m)) + return; + msg_set_hdr_sz(m, LONG_H_SIZE); + msg_set_orignode(m, msg_prevnode(m)); + msg_set_destnode(m, destnode); + memset(&m->hdr[8], 0, 12); +} + + + +/* + TIPC internal message header format, version 2 + + 1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + w0:|vers |msg usr|hdr sz |n|resrv| packet size | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + w1:|m typ|rsv=0| sequence gap | broadcast ack no | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + w2:| link level ack no/bc_gap_from | seq no / bcast_gap_to | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + w3:| previous node | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + w4:| next sent broadcast/fragm no | next sent pkt/ fragm msg no | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + w5:| session no |rsv=0|r|berid|link prio|netpl|p| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + w6:| originating node | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + w7:| destination node | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + w8:| transport sequence number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + w9:| msg count / bcast tag | link tolerance | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + \ \ + / User Specific Data / + \ \ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + NB: CONN_MANAGER use data message format. LINK_CONFIG has own format. +*/ + +/* + * Internal users + */ + +#define BCAST_PROTOCOL 5 +#define MSG_BUNDLER 6 +#define LINK_PROTOCOL 7 +#define CONN_MANAGER 8 +#define ROUTE_DISTRIBUTOR 9 +#define CHANGEOVER_PROTOCOL 10 +#define NAME_DISTRIBUTOR 11 +#define MSG_FRAGMENTER 12 +#define LINK_CONFIG 13 +#define INT_H_SIZE 40 +#define DSC_H_SIZE 40 + +/* + * Connection management protocol messages + */ + +#define CONN_PROBE 0 +#define CONN_PROBE_REPLY 1 +#define CONN_ACK 2 + +/* + * Name distributor messages + */ + +#define PUBLICATION 0 +#define WITHDRAWAL 1 + + +/* + * Word 1 + */ + +static inline u32 msg_seq_gap(struct tipc_msg *m) +{ + return msg_bits(m, 1, 16, 0xff); +} + +static inline void msg_set_seq_gap(struct tipc_msg *m, u32 n) +{ + msg_set_bits(m, 1, 16, 0xff, n); +} + +static inline u32 msg_req_links(struct tipc_msg *m) +{ + return msg_bits(m, 1, 16, 0xfff); +} + +static inline void msg_set_req_links(struct tipc_msg *m, u32 n) +{ + msg_set_bits(m, 1, 16, 0xfff, n); +} + + +/* + * Word 2 + */ + +static inline u32 msg_dest_domain(struct tipc_msg *m) +{ + return msg_word(m, 2); +} + +static inline void msg_set_dest_domain(struct tipc_msg *m, u32 n) +{ + msg_set_word(m, 2, n); +} + +static inline u32 msg_bcgap_after(struct tipc_msg *m) +{ + return msg_bits(m, 2, 16, 0xffff); +} + +static inline void msg_set_bcgap_after(struct tipc_msg *m, u32 n) +{ + msg_set_bits(m, 2, 16, 0xffff, n); +} + +static inline u32 msg_bcgap_to(struct tipc_msg *m) +{ + return msg_bits(m, 2, 0, 0xffff); +} + +static inline void msg_set_bcgap_to(struct tipc_msg *m, u32 n) +{ + msg_set_bits(m, 2, 0, 0xffff, n); +} + + +/* + * Word 4 + */ + +static inline u32 msg_last_bcast(struct tipc_msg *m) +{ + return msg_bits(m, 4, 16, 0xffff); +} + +static inline void msg_set_last_bcast(struct tipc_msg *m, u32 n) +{ + msg_set_bits(m, 4, 16, 0xffff, n); +} + + +static inline u32 msg_fragm_no(struct tipc_msg *m) +{ + return msg_bits(m, 4, 16, 0xffff); +} + +static inline void msg_set_fragm_no(struct tipc_msg *m, u32 n) +{ + msg_set_bits(m, 4, 16, 0xffff, n); +} + + +static inline u32 msg_next_sent(struct tipc_msg *m) +{ + return msg_bits(m, 4, 0, 0xffff); +} + +static inline void msg_set_next_sent(struct tipc_msg *m, u32 n) +{ + msg_set_bits(m, 4, 0, 0xffff, n); +} + + +static inline u32 msg_long_msgno(struct tipc_msg *m) +{ + return msg_bits(m, 4, 0, 0xffff); +} + +static inline void msg_set_long_msgno(struct tipc_msg *m, u32 n) +{ + msg_set_bits(m, 4, 0, 0xffff, n); +} + +static inline u32 msg_bc_netid(struct tipc_msg *m) +{ + return msg_word(m, 4); +} + +static inline void msg_set_bc_netid(struct tipc_msg *m, u32 id) +{ + msg_set_word(m, 4, id); +} + +static inline u32 msg_link_selector(struct tipc_msg *m) +{ + return msg_bits(m, 4, 0, 1); +} + +static inline void msg_set_link_selector(struct tipc_msg *m, u32 n) +{ + msg_set_bits(m, 4, 0, 1, (n & 1)); +} + +/* + * Word 5 + */ + +static inline u32 msg_session(struct tipc_msg *m) +{ + return msg_bits(m, 5, 16, 0xffff); +} + +static inline void msg_set_session(struct tipc_msg *m, u32 n) +{ + msg_set_bits(m, 5, 16, 0xffff, n); +} + +static inline u32 msg_probe(struct tipc_msg *m) +{ + return msg_bits(m, 5, 0, 1); +} + +static inline void msg_set_probe(struct tipc_msg *m, u32 val) +{ + msg_set_bits(m, 5, 0, 1, (val & 1)); +} + +static inline char msg_net_plane(struct tipc_msg *m) +{ + return msg_bits(m, 5, 1, 7) + 'A'; +} + +static inline void msg_set_net_plane(struct tipc_msg *m, char n) +{ + msg_set_bits(m, 5, 1, 7, (n - 'A')); +} + +static inline u32 msg_linkprio(struct tipc_msg *m) +{ + return msg_bits(m, 5, 4, 0x1f); +} + +static inline void msg_set_linkprio(struct tipc_msg *m, u32 n) +{ + msg_set_bits(m, 5, 4, 0x1f, n); +} + +static inline u32 msg_bearer_id(struct tipc_msg *m) +{ + return msg_bits(m, 5, 9, 0x7); +} + +static inline void msg_set_bearer_id(struct tipc_msg *m, u32 n) +{ + msg_set_bits(m, 5, 9, 0x7, n); +} + +static inline u32 msg_redundant_link(struct tipc_msg *m) +{ + return msg_bits(m, 5, 12, 0x1); +} + +static inline void msg_set_redundant_link(struct tipc_msg *m) +{ + msg_set_bits(m, 5, 12, 0x1, 1); +} + +static inline void msg_clear_redundant_link(struct tipc_msg *m) +{ + msg_set_bits(m, 5, 12, 0x1, 0); +} + + +/* + * Word 9 + */ + +static inline u32 msg_msgcnt(struct tipc_msg *m) +{ + return msg_bits(m, 9, 16, 0xffff); +} + +static inline void msg_set_msgcnt(struct tipc_msg *m, u32 n) +{ + msg_set_bits(m, 9, 16, 0xffff, n); +} + +static inline u32 msg_bcast_tag(struct tipc_msg *m) +{ + return msg_bits(m, 9, 16, 0xffff); +} + +static inline void msg_set_bcast_tag(struct tipc_msg *m, u32 n) +{ + msg_set_bits(m, 9, 16, 0xffff, n); +} + +static inline u32 msg_max_pkt(struct tipc_msg *m) +{ + return (msg_bits(m, 9, 16, 0xffff) * 4); +} + +static inline void msg_set_max_pkt(struct tipc_msg *m, u32 n) +{ + msg_set_bits(m, 9, 16, 0xffff, (n / 4)); +} + +static inline u32 msg_link_tolerance(struct tipc_msg *m) +{ + return msg_bits(m, 9, 0, 0xffff); +} + +static inline void msg_set_link_tolerance(struct tipc_msg *m, u32 n) +{ + msg_set_bits(m, 9, 0, 0xffff, n); +} + +/* + * Routing table message data + */ + + +static inline u32 msg_remote_node(struct tipc_msg *m) +{ + return msg_word(m, msg_hdr_sz(m)/4); +} + +static inline void msg_set_remote_node(struct tipc_msg *m, u32 a) +{ + msg_set_word(m, msg_hdr_sz(m)/4, a); +} + +static inline int msg_dataoctet(struct tipc_msg *m, u32 pos) +{ + return(msg_data(m)[pos + 4] != 0); +} + +static inline void msg_set_dataoctet(struct tipc_msg *m, u32 pos) +{ + msg_data(m)[pos + 4] = 1; +} + +/* + * Segmentation message types + */ + +#define FIRST_FRAGMENT 0 +#define FRAGMENT 1 +#define LAST_FRAGMENT 2 + +/* + * Link management protocol message types + */ + +#define STATE_MSG 0 +#define RESET_MSG 1 +#define ACTIVATE_MSG 2 + +/* + * Changeover tunnel message types + */ +#define DUPLICATE_MSG 0 +#define ORIGINAL_MSG 1 + +/* + * Routing table message types + */ +#define EXT_ROUTING_TABLE 0 +#define LOCAL_ROUTING_TABLE 1 +#define SLAVE_ROUTING_TABLE 2 +#define ROUTE_ADDITION 3 +#define ROUTE_REMOVAL 4 + +/* + * Config protocol message types + */ + +#define DSC_REQ_MSG 0 +#define DSC_RESP_MSG 1 + +static inline u32 msg_tot_importance(struct tipc_msg *m) +{ + if (likely(msg_isdata(m))) { + if (likely(msg_orignode(m) == tipc_own_addr)) + return msg_importance(m); + return msg_importance(m) + 4; + } + if ((msg_user(m) == MSG_FRAGMENTER) && + (msg_type(m) == FIRST_FRAGMENT)) + return msg_importance(msg_get_wrapped(m)); + return msg_importance(m); +} + + +static inline void msg_init(struct tipc_msg *m, u32 user, u32 type, + u32 err, u32 hsize, u32 destnode) +{ + memset(m, 0, hsize); + msg_set_version(m); + msg_set_user(m, user); + msg_set_hdr_sz(m, hsize); + msg_set_size(m, hsize); + msg_set_prevnode(m, tipc_own_addr); + msg_set_type(m, type); + msg_set_errcode(m, err); + if (!msg_short(m)) { + msg_set_orignode(m, tipc_own_addr); + msg_set_destnode(m, destnode); + } +} + +/** + * msg_calc_data_size - determine total data size for message + */ + +static inline int msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect) +{ + int dsz = 0; + int i; + + for (i = 0; i < num_sect; i++) + dsz += msg_sect[i].iov_len; + return dsz; +} + +/** + * msg_build - create message using specified header and data + * + * Note: Caller must not hold any locks in case copy_from_user() is interrupted! + * + * Returns message data size or errno + */ + +static inline int msg_build(struct tipc_msg *hdr, + struct iovec const *msg_sect, u32 num_sect, + int max_size, int usrmem, struct sk_buff** buf) +{ + int dsz, sz, hsz, pos, res, cnt; + + dsz = msg_calc_data_size(msg_sect, num_sect); + if (unlikely(dsz > TIPC_MAX_USER_MSG_SIZE)) { + *buf = NULL; + return -EINVAL; + } + + pos = hsz = msg_hdr_sz(hdr); + sz = hsz + dsz; + msg_set_size(hdr, sz); + if (unlikely(sz > max_size)) { + *buf = NULL; + return dsz; + } + + *buf = buf_acquire(sz); + if (!(*buf)) + return -ENOMEM; + memcpy((*buf)->data, (unchar *)hdr, hsz); + for (res = 1, cnt = 0; res && (cnt < num_sect); cnt++) { + if (likely(usrmem)) + res = !copy_from_user((*buf)->data + pos, + msg_sect[cnt].iov_base, + msg_sect[cnt].iov_len); + else + memcpy((*buf)->data + pos, msg_sect[cnt].iov_base, + msg_sect[cnt].iov_len); + pos += msg_sect[cnt].iov_len; + } + if (likely(res)) + return dsz; + + buf_discard(*buf); + *buf = NULL; + return -EFAULT; +} + + +struct tipc_media_addr; + +extern void msg_set_media_addr(struct tipc_msg *m, + struct tipc_media_addr *a); + +extern void msg_get_media_addr(struct tipc_msg *m, + struct tipc_media_addr *a); + + +#endif diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c new file mode 100644 index 00000000000..5e0604cb3ae --- /dev/null +++ b/net/tipc/name_distr.c @@ -0,0 +1,306 @@ +/* + * net/tipc/name_distr.c: TIPC name distribution code + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "core.h" +#include "cluster.h" +#include "dbg.h" +#include "link.h" +#include "msg.h" +#include "name_distr.h" + +#undef DBG_OUTPUT +#define DBG_OUTPUT NULL + +#define ITEM_SIZE sizeof(struct distr_item) + +/** + * struct distr_item - publication info distributed to other nodes + * @type: name sequence type + * @lower: name sequence lower bound + * @upper: name sequence upper bound + * @ref: publishing port reference + * @key: publication key + * + * ===> All fields are stored in network byte order. <=== + * + * First 3 fields identify (name or) name sequence being published. + * Reference field uniquely identifies port that published name sequence. + * Key field uniquely identifies publication, in the event a port has + * multiple publications of the same name sequence. + * + * Note: There is no field that identifies the publishing node because it is + * the same for all items contained within a publication message. + */ + +struct distr_item { + u32 type; + u32 lower; + u32 upper; + u32 ref; + u32 key; +}; + +/** + * List of externally visible publications by this node -- + * that is, all publications having scope > TIPC_NODE_SCOPE. + */ + +static LIST_HEAD(publ_root); +static u32 publ_cnt = 0; + +/** + * publ_to_item - add publication info to a publication message + */ + +static void publ_to_item(struct distr_item *i, struct publication *p) +{ + i->type = htonl(p->type); + i->lower = htonl(p->lower); + i->upper = htonl(p->upper); + i->ref = htonl(p->ref); + i->key = htonl(p->key); + dbg("publ_to_item: %u, %u, %u\n", p->type, p->lower, p->upper); +} + +/** + * named_prepare_buf - allocate & initialize a publication message + */ + +static struct sk_buff *named_prepare_buf(u32 type, u32 size, u32 dest) +{ + struct sk_buff *buf = buf_acquire(LONG_H_SIZE + size); + struct tipc_msg *msg; + + if (buf != NULL) { + msg = buf_msg(buf); + msg_init(msg, NAME_DISTRIBUTOR, type, TIPC_OK, + LONG_H_SIZE, dest); + msg_set_size(msg, LONG_H_SIZE + size); + } + return buf; +} + +/** + * named_publish - tell other nodes about a new publication by this node + */ + +void named_publish(struct publication *publ) +{ + struct sk_buff *buf; + struct distr_item *item; + + list_add(&publ->local_list, &publ_root); + publ_cnt++; + + buf = named_prepare_buf(PUBLICATION, ITEM_SIZE, 0); + if (!buf) { + warn("Memory squeeze; failed to distribute publication\n"); + return; + } + + item = (struct distr_item *)msg_data(buf_msg(buf)); + publ_to_item(item, publ); + dbg("named_withdraw: broadcasting publish msg\n"); + cluster_broadcast(buf); +} + +/** + * named_withdraw - tell other nodes about a withdrawn publication by this node + */ + +void named_withdraw(struct publication *publ) +{ + struct sk_buff *buf; + struct distr_item *item; + + list_del(&publ->local_list); + publ_cnt--; + + buf = named_prepare_buf(WITHDRAWAL, ITEM_SIZE, 0); + if (!buf) { + warn("Memory squeeze; failed to distribute withdrawal\n"); + return; + } + + item = (struct distr_item *)msg_data(buf_msg(buf)); + publ_to_item(item, publ); + dbg("named_withdraw: broadcasting withdraw msg\n"); + cluster_broadcast(buf); +} + +/** + * named_node_up - tell specified node about all publications by this node + */ + +void named_node_up(unsigned long node) +{ + struct publication *publ; + struct distr_item *item = 0; + struct sk_buff *buf = 0; + u32 left = 0; + u32 rest; + u32 max_item_buf; + + assert(in_own_cluster(node)); + read_lock_bh(&nametbl_lock); + max_item_buf = TIPC_MAX_USER_MSG_SIZE / ITEM_SIZE; + max_item_buf *= ITEM_SIZE; + rest = publ_cnt * ITEM_SIZE; + + list_for_each_entry(publ, &publ_root, local_list) { + if (!buf) { + left = (rest <= max_item_buf) ? rest : max_item_buf; + rest -= left; + buf = named_prepare_buf(PUBLICATION, left, node); + if (buf == NULL) { + warn("Memory Squeeze; could not send publication\n"); + goto exit; + } + item = (struct distr_item *)msg_data(buf_msg(buf)); + } + publ_to_item(item, publ); + item++; + left -= ITEM_SIZE; + if (!left) { + msg_set_link_selector(buf_msg(buf), node); + dbg("named_node_up: sending publish msg to " + "<%u.%u.%u>\n", tipc_zone(node), + tipc_cluster(node), tipc_node(node)); + link_send(buf, node, node); + buf = 0; + } + } +exit: + read_unlock_bh(&nametbl_lock); +} + +/** + * node_is_down - remove publication associated with a failed node + * + * Invoked for each publication issued by a newly failed node. + * Removes publication structure from name table & deletes it. + * In rare cases the link may have come back up again when this + * function is called, and we have two items representing the same + * publication. Nudge this item's key to distinguish it from the other. + * (Note: Publication's node subscription is already unsubscribed.) + */ + +static void node_is_down(struct publication *publ) +{ + struct publication *p; + write_lock_bh(&nametbl_lock); + dbg("node_is_down: withdrawing %u, %u, %u\n", + publ->type, publ->lower, publ->upper); + publ->key += 1222345; + p = nametbl_remove_publ(publ->type, publ->lower, + publ->node, publ->ref, publ->key); + assert(p == publ); + write_unlock_bh(&nametbl_lock); + if (publ) + kfree(publ); +} + +/** + * named_recv - process name table update message sent by another node + */ + +void named_recv(struct sk_buff *buf) +{ + struct publication *publ; + struct tipc_msg *msg = buf_msg(buf); + struct distr_item *item = (struct distr_item *)msg_data(msg); + u32 count = msg_data_sz(msg) / ITEM_SIZE; + + write_lock_bh(&nametbl_lock); + while (count--) { + if (msg_type(msg) == PUBLICATION) { + dbg("named_recv: got publication for %u, %u, %u\n", + ntohl(item->type), ntohl(item->lower), + ntohl(item->upper)); + publ = nametbl_insert_publ(ntohl(item->type), + ntohl(item->lower), + ntohl(item->upper), + TIPC_CLUSTER_SCOPE, + msg_orignode(msg), + ntohl(item->ref), + ntohl(item->key)); + if (publ) { + nodesub_subscribe(&publ->subscr, + msg_orignode(msg), + publ, + (net_ev_handler)node_is_down); + } + } else if (msg_type(msg) == WITHDRAWAL) { + dbg("named_recv: got withdrawl for %u, %u, %u\n", + ntohl(item->type), ntohl(item->lower), + ntohl(item->upper)); + publ = nametbl_remove_publ(ntohl(item->type), + ntohl(item->lower), + msg_orignode(msg), + ntohl(item->ref), + ntohl(item->key)); + + if (publ) { + nodesub_unsubscribe(&publ->subscr); + kfree(publ); + } + } else { + warn("named_recv: unknown msg\n"); + } + item++; + } + write_unlock_bh(&nametbl_lock); + buf_discard(buf); +} + +/** + * named_reinit - re-initialize local publication list + * + * This routine is called whenever TIPC networking is (re)enabled. + * All existing publications by this node that have "cluster" or "zone" scope + * are updated to reflect the node's current network address. + * (If the node's address is unchanged, the update loop terminates immediately.) + */ + +void named_reinit(void) +{ + struct publication *publ; + + write_lock_bh(&nametbl_lock); + list_for_each_entry(publ, &publ_root, local_list) { + if (publ->node == tipc_own_addr) + break; + publ->node = tipc_own_addr; + } + write_unlock_bh(&nametbl_lock); +} diff --git a/net/tipc/name_distr.h b/net/tipc/name_distr.h new file mode 100644 index 00000000000..7c6616aecc0 --- /dev/null +++ b/net/tipc/name_distr.h @@ -0,0 +1,45 @@ +/* + * net/tipc/name_distr.h: Include file for TIPC name distribution code + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _TIPC_NAME_DISTR_H +#define _TIPC_NAME_DISTR_H + +#include "name_table.h" + +void named_publish(struct publication *publ); +void named_withdraw(struct publication *publ); +void named_node_up(unsigned long node); +void named_recv(struct sk_buff *buf); +void named_reinit(void); + +#endif diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c new file mode 100644 index 00000000000..9626c5b3067 --- /dev/null +++ b/net/tipc/name_table.c @@ -0,0 +1,1076 @@ +/* + * net/tipc/name_table.c: TIPC name table code + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2004-2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "core.h" +#include "config.h" +#include "dbg.h" +#include "name_table.h" +#include "name_distr.h" +#include "addr.h" +#include "node_subscr.h" +#include "subscr.h" +#include "port.h" +#include "cluster.h" +#include "bcast.h" + +int tipc_nametbl_size = 1024; /* must be a power of 2 */ + +/** + * struct sub_seq - container for all published instances of a name sequence + * @lower: name sequence lower bound + * @upper: name sequence upper bound + * @node_list: circular list of matching publications with >= node scope + * @cluster_list: circular list of matching publications with >= cluster scope + * @zone_list: circular list of matching publications with >= zone scope + */ + +struct sub_seq { + u32 lower; + u32 upper; + struct publication *node_list; + struct publication *cluster_list; + struct publication *zone_list; +}; + +/** + * struct name_seq - container for all published instances of a name type + * @type: 32 bit 'type' value for name sequence + * @sseq: pointer to dynamically-sized array of sub-sequences of this 'type'; + * sub-sequences are sorted in ascending order + * @alloc: number of sub-sequences currently in array + * @first_free: upper bound of highest sub-sequence + 1 + * @ns_list: links to adjacent name sequences in hash chain + * @subscriptions: list of subscriptions for this 'type' + * @lock: spinlock controlling access to name sequence structure + */ + +struct name_seq { + u32 type; + struct sub_seq *sseqs; + u32 alloc; + u32 first_free; + struct hlist_node ns_list; + struct list_head subscriptions; + spinlock_t lock; +}; + +/** + * struct name_table - table containing all existing port name publications + * @types: pointer to fixed-sized array of name sequence lists, + * accessed via hashing on 'type'; name sequence lists are *not* sorted + * @local_publ_count: number of publications issued by this node + */ + +struct name_table { + struct hlist_head *types; + u32 local_publ_count; +}; + +struct name_table table = { NULL } ; +static atomic_t rsv_publ_ok = ATOMIC_INIT(0); +rwlock_t nametbl_lock = RW_LOCK_UNLOCKED; + + +static inline int hash(int x) +{ + return(x & (tipc_nametbl_size - 1)); +} + +/** + * publ_create - create a publication structure + */ + +static struct publication *publ_create(u32 type, u32 lower, u32 upper, + u32 scope, u32 node, u32 port_ref, + u32 key) +{ + struct publication *publ = + (struct publication *)kmalloc(sizeof(*publ), GFP_ATOMIC); + if (publ == NULL) { + warn("Memory squeeze; failed to create publication\n"); + return 0; + } + + memset(publ, 0, sizeof(*publ)); + publ->type = type; + publ->lower = lower; + publ->upper = upper; + publ->scope = scope; + publ->node = node; + publ->ref = port_ref; + publ->key = key; + INIT_LIST_HEAD(&publ->local_list); + INIT_LIST_HEAD(&publ->pport_list); + INIT_LIST_HEAD(&publ->subscr.nodesub_list); + return publ; +} + +/** + * subseq_alloc - allocate a specified number of sub-sequence structures + */ + +struct sub_seq *subseq_alloc(u32 cnt) +{ + u32 sz = cnt * sizeof(struct sub_seq); + struct sub_seq *sseq = (struct sub_seq *)kmalloc(sz, GFP_ATOMIC); + + if (sseq) + memset(sseq, 0, sz); + return sseq; +} + +/** + * nameseq_create - create a name sequence structure for the specified 'type' + * + * Allocates a single sub-sequence structure and sets it to all 0's. + */ + +struct name_seq *nameseq_create(u32 type, struct hlist_head *seq_head) +{ + struct name_seq *nseq = + (struct name_seq *)kmalloc(sizeof(*nseq), GFP_ATOMIC); + struct sub_seq *sseq = subseq_alloc(1); + + if (!nseq || !sseq) { + warn("Memory squeeze; failed to create name sequence\n"); + kfree(nseq); + kfree(sseq); + return 0; + } + + memset(nseq, 0, sizeof(*nseq)); + nseq->lock = SPIN_LOCK_UNLOCKED; + nseq->type = type; + nseq->sseqs = sseq; + dbg("nameseq_create() nseq = %x type %u, ssseqs %x, ff: %u\n", + nseq, type, nseq->sseqs, nseq->first_free); + nseq->alloc = 1; + INIT_HLIST_NODE(&nseq->ns_list); + INIT_LIST_HEAD(&nseq->subscriptions); + hlist_add_head(&nseq->ns_list, seq_head); + return nseq; +} + +/** + * nameseq_find_subseq - find sub-sequence (if any) matching a name instance + * + * Very time-critical, so binary searches through sub-sequence array. + */ + +static inline struct sub_seq *nameseq_find_subseq(struct name_seq *nseq, + u32 instance) +{ + struct sub_seq *sseqs = nseq->sseqs; + int low = 0; + int high = nseq->first_free - 1; + int mid; + + while (low <= high) { + mid = (low + high) / 2; + if (instance < sseqs[mid].lower) + high = mid - 1; + else if (instance > sseqs[mid].upper) + low = mid + 1; + else + return &sseqs[mid]; + } + return 0; +} + +/** + * nameseq_locate_subseq - determine position of name instance in sub-sequence + * + * Returns index in sub-sequence array of the entry that contains the specified + * instance value; if no entry contains that value, returns the position + * where a new entry for it would be inserted in the array. + * + * Note: Similar to binary search code for locating a sub-sequence. + */ + +static u32 nameseq_locate_subseq(struct name_seq *nseq, u32 instance) +{ + struct sub_seq *sseqs = nseq->sseqs; + int low = 0; + int high = nseq->first_free - 1; + int mid; + + while (low <= high) { + mid = (low + high) / 2; + if (instance < sseqs[mid].lower) + high = mid - 1; + else if (instance > sseqs[mid].upper) + low = mid + 1; + else + return mid; + } + return low; +} + +/** + * nameseq_insert_publ - + */ + +struct publication *nameseq_insert_publ(struct name_seq *nseq, + u32 type, u32 lower, u32 upper, + u32 scope, u32 node, u32 port, u32 key) +{ + struct subscription *s; + struct subscription *st; + struct publication *publ; + struct sub_seq *sseq; + int created_subseq = 0; + + assert(nseq->first_free <= nseq->alloc); + sseq = nameseq_find_subseq(nseq, lower); + dbg("nameseq_ins: for seq %x,<%u,%u>, found sseq %x\n", + nseq, type, lower, sseq); + if (sseq) { + + /* Lower end overlaps existing entry => need an exact match */ + + if ((sseq->lower != lower) || (sseq->upper != upper)) { + warn("Overlapping publ <%u,%u,%u>\n", type, lower, upper); + return 0; + } + } else { + u32 inspos; + struct sub_seq *freesseq; + + /* Find where lower end should be inserted */ + + inspos = nameseq_locate_subseq(nseq, lower); + + /* Fail if upper end overlaps into an existing entry */ + + if ((inspos < nseq->first_free) && + (upper >= nseq->sseqs[inspos].lower)) { + warn("Overlapping publ <%u,%u,%u>\n", type, lower, upper); + return 0; + } + + /* Ensure there is space for new sub-sequence */ + + if (nseq->first_free == nseq->alloc) { + struct sub_seq *sseqs = nseq->sseqs; + nseq->sseqs = subseq_alloc(nseq->alloc * 2); + if (nseq->sseqs != NULL) { + memcpy(nseq->sseqs, sseqs, + nseq->alloc * sizeof (struct sub_seq)); + kfree(sseqs); + dbg("Allocated %u sseqs\n", nseq->alloc); + nseq->alloc *= 2; + } else { + warn("Memory squeeze; failed to create sub-sequence\n"); + return 0; + } + } + dbg("Have %u sseqs for type %u\n", nseq->alloc, type); + + /* Insert new sub-sequence */ + + dbg("ins in pos %u, ff = %u\n", inspos, nseq->first_free); + sseq = &nseq->sseqs[inspos]; + freesseq = &nseq->sseqs[nseq->first_free]; + memmove(sseq + 1, sseq, (freesseq - sseq) * sizeof (*sseq)); + memset(sseq, 0, sizeof (*sseq)); + nseq->first_free++; + sseq->lower = lower; + sseq->upper = upper; + created_subseq = 1; + } + dbg("inserting (%u %u %u) from %x:%u into sseq %x(%u,%u) of seq %x\n", + type, lower, upper, node, port, sseq, + sseq->lower, sseq->upper, nseq); + + /* Insert a publication: */ + + publ = publ_create(type, lower, upper, scope, node, port, key); + if (!publ) + return 0; + dbg("inserting publ %x, node=%x publ->node=%x, subscr->node=%x\n", + publ, node, publ->node, publ->subscr.node); + + if (!sseq->zone_list) + sseq->zone_list = publ->zone_list_next = publ; + else { + publ->zone_list_next = sseq->zone_list->zone_list_next; + sseq->zone_list->zone_list_next = publ; + } + + if (in_own_cluster(node)) { + if (!sseq->cluster_list) + sseq->cluster_list = publ->cluster_list_next = publ; + else { + publ->cluster_list_next = + sseq->cluster_list->cluster_list_next; + sseq->cluster_list->cluster_list_next = publ; + } + } + + if (node == tipc_own_addr) { + if (!sseq->node_list) + sseq->node_list = publ->node_list_next = publ; + else { + publ->node_list_next = sseq->node_list->node_list_next; + sseq->node_list->node_list_next = publ; + } + } + + /* + * Any subscriptions waiting for notification? + */ + list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) { + dbg("calling report_overlap()\n"); + subscr_report_overlap(s, + publ->lower, + publ->upper, + TIPC_PUBLISHED, + publ->ref, + publ->node, + created_subseq); + } + return publ; +} + +/** + * nameseq_remove_publ - + */ + +struct publication *nameseq_remove_publ(struct name_seq *nseq, u32 inst, + u32 node, u32 ref, u32 key) +{ + struct publication *publ; + struct publication *prev; + struct sub_seq *sseq = nameseq_find_subseq(nseq, inst); + struct sub_seq *free; + struct subscription *s, *st; + int removed_subseq = 0; + + assert(nseq); + + if (!sseq) { + int i; + + warn("Withdraw unknown <%u,%u>?\n", nseq->type, inst); + assert(nseq->sseqs); + dbg("Dumping subseqs %x for %x, alloc = %u,ff=%u\n", + nseq->sseqs, nseq, nseq->alloc, + nseq->first_free); + for (i = 0; i < nseq->first_free; i++) { + dbg("Subseq %u(%x): lower = %u,upper = %u\n", + i, &nseq->sseqs[i], nseq->sseqs[i].lower, + nseq->sseqs[i].upper); + } + return 0; + } + dbg("nameseq_remove: seq: %x, sseq %x, <%u,%u> key %u\n", + nseq, sseq, nseq->type, inst, key); + + prev = sseq->zone_list; + publ = sseq->zone_list->zone_list_next; + while ((publ->key != key) || (publ->ref != ref) || + (publ->node && (publ->node != node))) { + prev = publ; + publ = publ->zone_list_next; + assert(prev != sseq->zone_list); + } + if (publ != sseq->zone_list) + prev->zone_list_next = publ->zone_list_next; + else if (publ->zone_list_next != publ) { + prev->zone_list_next = publ->zone_list_next; + sseq->zone_list = publ->zone_list_next; + } else { + sseq->zone_list = 0; + } + + if (in_own_cluster(node)) { + prev = sseq->cluster_list; + publ = sseq->cluster_list->cluster_list_next; + while ((publ->key != key) || (publ->ref != ref) || + (publ->node && (publ->node != node))) { + prev = publ; + publ = publ->cluster_list_next; + assert(prev != sseq->cluster_list); + } + if (publ != sseq->cluster_list) + prev->cluster_list_next = publ->cluster_list_next; + else if (publ->cluster_list_next != publ) { + prev->cluster_list_next = publ->cluster_list_next; + sseq->cluster_list = publ->cluster_list_next; + } else { + sseq->cluster_list = 0; + } + } + + if (node == tipc_own_addr) { + prev = sseq->node_list; + publ = sseq->node_list->node_list_next; + while ((publ->key != key) || (publ->ref != ref) || + (publ->node && (publ->node != node))) { + prev = publ; + publ = publ->node_list_next; + assert(prev != sseq->node_list); + } + if (publ != sseq->node_list) + prev->node_list_next = publ->node_list_next; + else if (publ->node_list_next != publ) { + prev->node_list_next = publ->node_list_next; + sseq->node_list = publ->node_list_next; + } else { + sseq->node_list = 0; + } + } + assert(!publ->node || (publ->node == node)); + assert(publ->ref == ref); + assert(publ->key == key); + + /* + * Contract subseq list if no more publications: + */ + if (!sseq->node_list && !sseq->cluster_list && !sseq->zone_list) { + free = &nseq->sseqs[nseq->first_free--]; + memmove(sseq, sseq + 1, (free - (sseq + 1)) * sizeof (*sseq)); + removed_subseq = 1; + } + + /* + * Any subscriptions waiting ? + */ + list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) { + subscr_report_overlap(s, + publ->lower, + publ->upper, + TIPC_WITHDRAWN, + publ->ref, + publ->node, + removed_subseq); + } + return publ; +} + +/** + * nameseq_subscribe: attach a subscription, and issue + * the prescribed number of events if there is any sub- + * sequence overlapping with the requested sequence + */ + +void nameseq_subscribe(struct name_seq *nseq, struct subscription *s) +{ + struct sub_seq *sseq = nseq->sseqs; + + list_add(&s->nameseq_list, &nseq->subscriptions); + + if (!sseq) + return; + + while (sseq != &nseq->sseqs[nseq->first_free]) { + struct publication *zl = sseq->zone_list; + if (zl && subscr_overlap(s,sseq->lower,sseq->upper)) { + struct publication *crs = zl; + int must_report = 1; + + do { + subscr_report_overlap(s, + sseq->lower, + sseq->upper, + TIPC_PUBLISHED, + crs->ref, + crs->node, + must_report); + must_report = 0; + crs = crs->zone_list_next; + } while (crs != zl); + } + sseq++; + } +} + +static struct name_seq *nametbl_find_seq(u32 type) +{ + struct hlist_head *seq_head; + struct hlist_node *seq_node; + struct name_seq *ns; + + dbg("find_seq %u,(%u,0x%x) table = %p, hash[type] = %u\n", + type, ntohl(type), type, table.types, hash(type)); + + seq_head = &table.types[hash(type)]; + hlist_for_each_entry(ns, seq_node, seq_head, ns_list) { + if (ns->type == type) { + dbg("found %x\n", ns); + return ns; + } + } + + return 0; +}; + +struct publication *nametbl_insert_publ(u32 type, u32 lower, u32 upper, + u32 scope, u32 node, u32 port, u32 key) +{ + struct name_seq *seq = nametbl_find_seq(type); + + dbg("ins_publ: <%u,%x,%x> found %x\n", type, lower, upper, seq); + if (lower > upper) { + warn("Failed to publish illegal <%u,%u,%u>\n", + type, lower, upper); + return 0; + } + + dbg("Publishing <%u,%u,%u> from %x\n", type, lower, upper, node); + if (!seq) { + seq = nameseq_create(type, &table.types[hash(type)]); + dbg("nametbl_insert_publ: created %x\n", seq); + } + if (!seq) + return 0; + + assert(seq->type == type); + return nameseq_insert_publ(seq, type, lower, upper, + scope, node, port, key); +} + +struct publication *nametbl_remove_publ(u32 type, u32 lower, + u32 node, u32 ref, u32 key) +{ + struct publication *publ; + struct name_seq *seq = nametbl_find_seq(type); + + if (!seq) + return 0; + + dbg("Withdrawing <%u,%u> from %x\n", type, lower, node); + publ = nameseq_remove_publ(seq, lower, node, ref, key); + + if (!seq->first_free && list_empty(&seq->subscriptions)) { + hlist_del_init(&seq->ns_list); + kfree(seq->sseqs); + kfree(seq); + } + return publ; +} + +/* + * nametbl_translate(): Translate tipc_name -> tipc_portid. + * Very time-critical. + * + * Note: on entry 'destnode' is the search domain used during translation; + * on exit it passes back the node address of the matching port (if any) + */ + +u32 nametbl_translate(u32 type, u32 instance, u32 *destnode) +{ + struct sub_seq *sseq; + struct publication *publ = 0; + struct name_seq *seq; + u32 ref; + + if (!in_scope(*destnode, tipc_own_addr)) + return 0; + + read_lock_bh(&nametbl_lock); + seq = nametbl_find_seq(type); + if (unlikely(!seq)) + goto not_found; + sseq = nameseq_find_subseq(seq, instance); + if (unlikely(!sseq)) + goto not_found; + spin_lock_bh(&seq->lock); + + /* Closest-First Algorithm: */ + if (likely(!*destnode)) { + publ = sseq->node_list; + if (publ) { + sseq->node_list = publ->node_list_next; +found: + ref = publ->ref; + *destnode = publ->node; + spin_unlock_bh(&seq->lock); + read_unlock_bh(&nametbl_lock); + return ref; + } + publ = sseq->cluster_list; + if (publ) { + sseq->cluster_list = publ->cluster_list_next; + goto found; + } + publ = sseq->zone_list; + if (publ) { + sseq->zone_list = publ->zone_list_next; + goto found; + } + } + + /* Round-Robin Algorithm: */ + else if (*destnode == tipc_own_addr) { + publ = sseq->node_list; + if (publ) { + sseq->node_list = publ->node_list_next; + goto found; + } + } else if (in_own_cluster(*destnode)) { + publ = sseq->cluster_list; + if (publ) { + sseq->cluster_list = publ->cluster_list_next; + goto found; + } + } else { + publ = sseq->zone_list; + if (publ) { + sseq->zone_list = publ->zone_list_next; + goto found; + } + } + spin_unlock_bh(&seq->lock); +not_found: + *destnode = 0; + read_unlock_bh(&nametbl_lock); + return 0; +} + +/** + * nametbl_mc_translate - find multicast destinations + * + * Creates list of all local ports that overlap the given multicast address; + * also determines if any off-node ports overlap. + * + * Note: Publications with a scope narrower than 'limit' are ignored. + * (i.e. local node-scope publications mustn't receive messages arriving + * from another node, even if the multcast link brought it here) + * + * Returns non-zero if any off-node ports overlap + */ + +int nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, + struct port_list *dports) +{ + struct name_seq *seq; + struct sub_seq *sseq; + struct sub_seq *sseq_stop; + int res = 0; + + read_lock_bh(&nametbl_lock); + seq = nametbl_find_seq(type); + if (!seq) + goto exit; + + spin_lock_bh(&seq->lock); + + sseq = seq->sseqs + nameseq_locate_subseq(seq, lower); + sseq_stop = seq->sseqs + seq->first_free; + for (; sseq != sseq_stop; sseq++) { + struct publication *publ; + + if (sseq->lower > upper) + break; + publ = sseq->cluster_list; + if (publ && (publ->scope <= limit)) + do { + if (publ->node == tipc_own_addr) + port_list_add(dports, publ->ref); + else + res = 1; + publ = publ->cluster_list_next; + } while (publ != sseq->cluster_list); + } + + spin_unlock_bh(&seq->lock); +exit: + read_unlock_bh(&nametbl_lock); + return res; +} + +/** + * nametbl_publish_rsv - publish port name using a reserved name type + */ + +int nametbl_publish_rsv(u32 ref, unsigned int scope, + struct tipc_name_seq const *seq) +{ + int res; + + atomic_inc(&rsv_publ_ok); + res = tipc_publish(ref, scope, seq); + atomic_dec(&rsv_publ_ok); + return res; +} + +/** + * nametbl_publish - add name publication to network name tables + */ + +struct publication *nametbl_publish(u32 type, u32 lower, u32 upper, + u32 scope, u32 port_ref, u32 key) +{ + struct publication *publ; + + if (table.local_publ_count >= tipc_max_publications) { + warn("Failed publish: max %u local publication\n", + tipc_max_publications); + return 0; + } + if ((type < TIPC_RESERVED_TYPES) && !atomic_read(&rsv_publ_ok)) { + warn("Failed to publish reserved name <%u,%u,%u>\n", + type, lower, upper); + return 0; + } + + write_lock_bh(&nametbl_lock); + table.local_publ_count++; + publ = nametbl_insert_publ(type, lower, upper, scope, + tipc_own_addr, port_ref, key); + if (publ && (scope != TIPC_NODE_SCOPE)) { + named_publish(publ); + } + write_unlock_bh(&nametbl_lock); + return publ; +} + +/** + * nametbl_withdraw - withdraw name publication from network name tables + */ + +int nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key) +{ + struct publication *publ; + + dbg("nametbl_withdraw:<%d,%d,%d>\n", type, lower, key); + write_lock_bh(&nametbl_lock); + publ = nametbl_remove_publ(type, lower, tipc_own_addr, ref, key); + if (publ) { + table.local_publ_count--; + if (publ->scope != TIPC_NODE_SCOPE) + named_withdraw(publ); + write_unlock_bh(&nametbl_lock); + list_del_init(&publ->pport_list); + kfree(publ); + return 1; + } + write_unlock_bh(&nametbl_lock); + return 0; +} + +/** + * nametbl_subscribe - add a subscription object to the name table + */ + +void +nametbl_subscribe(struct subscription *s) +{ + u32 type = s->seq.type; + struct name_seq *seq; + + write_lock_bh(&nametbl_lock); + seq = nametbl_find_seq(type); + if (!seq) { + seq = nameseq_create(type, &table.types[hash(type)]); + } + if (seq){ + spin_lock_bh(&seq->lock); + dbg("nametbl_subscribe:found %x for <%u,%u,%u>\n", + seq, type, s->seq.lower, s->seq.upper); + assert(seq->type == type); + nameseq_subscribe(seq, s); + spin_unlock_bh(&seq->lock); + } + write_unlock_bh(&nametbl_lock); +} + +/** + * nametbl_unsubscribe - remove a subscription object from name table + */ + +void +nametbl_unsubscribe(struct subscription *s) +{ + struct name_seq *seq; + + write_lock_bh(&nametbl_lock); + seq = nametbl_find_seq(s->seq.type); + if (seq != NULL){ + spin_lock_bh(&seq->lock); + list_del_init(&s->nameseq_list); + spin_unlock_bh(&seq->lock); + if ((seq->first_free == 0) && list_empty(&seq->subscriptions)) { + hlist_del_init(&seq->ns_list); + kfree(seq->sseqs); + kfree(seq); + } + } + write_unlock_bh(&nametbl_lock); +} + + +/** + * subseq_list: print specified sub-sequence contents into the given buffer + */ + +static void subseq_list(struct sub_seq *sseq, struct print_buf *buf, u32 depth, + u32 index) +{ + char portIdStr[27]; + char *scopeStr; + struct publication *publ = sseq->zone_list; + + tipc_printf(buf, "%-10u %-10u ", sseq->lower, sseq->upper); + + if (depth == 2 || !publ) { + tipc_printf(buf, "\n"); + return; + } + + do { + sprintf (portIdStr, "<%u.%u.%u:%u>", + tipc_zone(publ->node), tipc_cluster(publ->node), + tipc_node(publ->node), publ->ref); + tipc_printf(buf, "%-26s ", portIdStr); + if (depth > 3) { + if (publ->node != tipc_own_addr) + scopeStr = ""; + else if (publ->scope == TIPC_NODE_SCOPE) + scopeStr = "node"; + else if (publ->scope == TIPC_CLUSTER_SCOPE) + scopeStr = "cluster"; + else + scopeStr = "zone"; + tipc_printf(buf, "%-10u %s", publ->key, scopeStr); + } + + publ = publ->zone_list_next; + if (publ == sseq->zone_list) + break; + + tipc_printf(buf, "\n%33s", " "); + } while (1); + + tipc_printf(buf, "\n"); +} + +/** + * nameseq_list: print specified name sequence contents into the given buffer + */ + +static void nameseq_list(struct name_seq *seq, struct print_buf *buf, u32 depth, + u32 type, u32 lowbound, u32 upbound, u32 index) +{ + struct sub_seq *sseq; + char typearea[11]; + + sprintf(typearea, "%-10u", seq->type); + + if (depth == 1) { + tipc_printf(buf, "%s\n", typearea); + return; + } + + for (sseq = seq->sseqs; sseq != &seq->sseqs[seq->first_free]; sseq++) { + if ((lowbound <= sseq->upper) && (upbound >= sseq->lower)) { + tipc_printf(buf, "%s ", typearea); + subseq_list(sseq, buf, depth, index); + sprintf(typearea, "%10s", " "); + } + } +} + +/** + * nametbl_header - print name table header into the given buffer + */ + +static void nametbl_header(struct print_buf *buf, u32 depth) +{ + tipc_printf(buf, "Type "); + + if (depth > 1) + tipc_printf(buf, "Lower Upper "); + if (depth > 2) + tipc_printf(buf, "Port Identity "); + if (depth > 3) + tipc_printf(buf, "Publication"); + + tipc_printf(buf, "\n-----------"); + + if (depth > 1) + tipc_printf(buf, "--------------------- "); + if (depth > 2) + tipc_printf(buf, "-------------------------- "); + if (depth > 3) + tipc_printf(buf, "------------------"); + + tipc_printf(buf, "\n"); +} + +/** + * nametbl_list - print specified name table contents into the given buffer + */ + +static void nametbl_list(struct print_buf *buf, u32 depth_info, + u32 type, u32 lowbound, u32 upbound) +{ + struct hlist_head *seq_head; + struct hlist_node *seq_node; + struct name_seq *seq; + int all_types; + u32 depth; + u32 i; + + all_types = (depth_info & TIPC_NTQ_ALLTYPES); + depth = (depth_info & ~TIPC_NTQ_ALLTYPES); + + if (depth == 0) + return; + + if (all_types) { + /* display all entries in name table to specified depth */ + nametbl_header(buf, depth); + lowbound = 0; + upbound = ~0; + for (i = 0; i < tipc_nametbl_size; i++) { + seq_head = &table.types[i]; + hlist_for_each_entry(seq, seq_node, seq_head, ns_list) { + nameseq_list(seq, buf, depth, seq->type, + lowbound, upbound, i); + } + } + } else { + /* display only the sequence that matches the specified type */ + if (upbound < lowbound) { + tipc_printf(buf, "invalid name sequence specified\n"); + return; + } + nametbl_header(buf, depth); + i = hash(type); + seq_head = &table.types[i]; + hlist_for_each_entry(seq, seq_node, seq_head, ns_list) { + if (seq->type == type) { + nameseq_list(seq, buf, depth, type, + lowbound, upbound, i); + break; + } + } + } +} + +void nametbl_print(struct print_buf *buf, const char *str) +{ + tipc_printf(buf, str); + read_lock_bh(&nametbl_lock); + nametbl_list(buf, 0, 0, 0, 0); + read_unlock_bh(&nametbl_lock); +} + +#define MAX_NAME_TBL_QUERY 32768 + +struct sk_buff *nametbl_get(const void *req_tlv_area, int req_tlv_space) +{ + struct sk_buff *buf; + struct tipc_name_table_query *argv; + struct tlv_desc *rep_tlv; + struct print_buf b; + int str_len; + + if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NAME_TBL_QUERY)) + return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + + buf = cfg_reply_alloc(TLV_SPACE(MAX_NAME_TBL_QUERY)); + if (!buf) + return NULL; + + rep_tlv = (struct tlv_desc *)buf->data; + printbuf_init(&b, TLV_DATA(rep_tlv), MAX_NAME_TBL_QUERY); + argv = (struct tipc_name_table_query *)TLV_DATA(req_tlv_area); + read_lock_bh(&nametbl_lock); + nametbl_list(&b, ntohl(argv->depth), ntohl(argv->type), + ntohl(argv->lowbound), ntohl(argv->upbound)); + read_unlock_bh(&nametbl_lock); + str_len = printbuf_validate(&b); + + skb_put(buf, TLV_SPACE(str_len)); + TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); + + return buf; +} + +void nametbl_dump(void) +{ + nametbl_list(CONS, 0, 0, 0, 0); +} + +int nametbl_init(void) +{ + int array_size = sizeof(struct hlist_head) * tipc_nametbl_size; + + table.types = (struct hlist_head *)kmalloc(array_size, GFP_ATOMIC); + if (!table.types) + return -ENOMEM; + + write_lock_bh(&nametbl_lock); + memset(table.types, 0, array_size); + table.local_publ_count = 0; + write_unlock_bh(&nametbl_lock); + return 0; +} + +void nametbl_stop(void) +{ + struct hlist_head *seq_head; + struct hlist_node *seq_node; + struct hlist_node *tmp; + struct name_seq *seq; + u32 i; + + if (!table.types) + return; + + write_lock_bh(&nametbl_lock); + for (i = 0; i < tipc_nametbl_size; i++) { + seq_head = &table.types[i]; + hlist_for_each_entry_safe(seq, seq_node, tmp, seq_head, ns_list) { + struct sub_seq *sseq = seq->sseqs; + + for (; sseq != &seq->sseqs[seq->first_free]; sseq++) { + struct publication *publ = sseq->zone_list; + assert(publ); + do { + struct publication *next = + publ->zone_list_next; + kfree(publ); + publ = next; + } + while (publ != sseq->zone_list); + } + } + } + kfree(table.types); + table.types = NULL; + write_unlock_bh(&nametbl_lock); +} diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h new file mode 100644 index 00000000000..5036b5bac36 --- /dev/null +++ b/net/tipc/name_table.h @@ -0,0 +1,105 @@ +/* + * net/tipc/name_table.h: Include file for TIPC name table code + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2004-2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _TIPC_NAME_TABLE_H +#define _TIPC_NAME_TABLE_H + +#include "node_subscr.h" + +struct subscription; +struct port_list; + +/* + * TIPC name types reserved for internal TIPC use (both current and planned) + */ + +#define TIPC_ZM_SRV 3 /* zone master service name type */ + + +/** + * struct publication - info about a published (name or) name sequence + * @type: name sequence type + * @lower: name sequence lower bound + * @upper: name sequence upper bound + * @scope: scope of publication + * @node: network address of publishing port's node + * @ref: publishing port + * @key: publication key + * @subscr: subscription to "node down" event (for off-node publications only) + * @local_list: adjacent entries in list of publications made by this node + * @pport_list: adjacent entries in list of publications made by this port + * @node_list: next matching name seq publication with >= node scope + * @cluster_list: next matching name seq publication with >= cluster scope + * @zone_list: next matching name seq publication with >= zone scope + * + * Note that the node list, cluster list, and zone list are circular lists. + */ + +struct publication { + u32 type; + u32 lower; + u32 upper; + u32 scope; + u32 node; + u32 ref; + u32 key; + struct node_subscr subscr; + struct list_head local_list; + struct list_head pport_list; + struct publication *node_list_next; + struct publication *cluster_list_next; + struct publication *zone_list_next; +}; + + +extern rwlock_t nametbl_lock; + +struct sk_buff *nametbl_get(const void *req_tlv_area, int req_tlv_space); +u32 nametbl_translate(u32 type, u32 instance, u32 *node); +int nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, + struct port_list *dports); +int nametbl_publish_rsv(u32 ref, unsigned int scope, + struct tipc_name_seq const *seq); +struct publication *nametbl_publish(u32 type, u32 lower, u32 upper, + u32 scope, u32 port_ref, u32 key); +int nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key); +struct publication *nametbl_insert_publ(u32 type, u32 lower, u32 upper, + u32 scope, u32 node, u32 ref, u32 key); +struct publication *nametbl_remove_publ(u32 type, u32 lower, + u32 node, u32 ref, u32 key); +void nametbl_subscribe(struct subscription *s); +void nametbl_unsubscribe(struct subscription *s); +int nametbl_init(void); +void nametbl_stop(void); + +#endif diff --git a/net/tipc/net.c b/net/tipc/net.c new file mode 100644 index 00000000000..eba88033b90 --- /dev/null +++ b/net/tipc/net.c @@ -0,0 +1,308 @@ +/* + * net/tipc/net.c: TIPC network routing code + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "core.h" +#include "bearer.h" +#include "net.h" +#include "zone.h" +#include "addr.h" +#include "name_table.h" +#include "name_distr.h" +#include "subscr.h" +#include "link.h" +#include "msg.h" +#include "port.h" +#include "bcast.h" +#include "discover.h" +#include "config.h" + +/* + * The TIPC locking policy is designed to ensure a very fine locking + * granularity, permitting complete parallel access to individual + * port and node/link instances. The code consists of three major + * locking domains, each protected with their own disjunct set of locks. + * + * 1: The routing hierarchy. + * Comprises the structures 'zone', 'cluster', 'node', 'link' + * and 'bearer'. The whole hierarchy is protected by a big + * read/write lock, net_lock, to enssure that nothing is added + * or removed while code is accessing any of these structures. + * This layer must not be called from the two others while they + * hold any of their own locks. + * Neither must it itself do any upcalls to the other two before + * it has released net_lock and other protective locks. + * + * Within the net_lock domain there are two sub-domains;'node' and + * 'bearer', where local write operations are permitted, + * provided that those are protected by individual spin_locks + * per instance. Code holding net_lock(read) and a node spin_lock + * is permitted to poke around in both the node itself and its + * subordinate links. I.e, it can update link counters and queues, + * change link state, send protocol messages, and alter the + * "active_links" array in the node; but it can _not_ remove a link + * or a node from the overall structure. + * Correspondingly, individual bearers may change status within a + * net_lock(read), protected by an individual spin_lock ber bearer + * instance, but it needs net_lock(write) to remove/add any bearers. + * + * + * 2: The transport level of the protocol. + * This consists of the structures port, (and its user level + * representations, such as user_port and tipc_sock), reference and + * tipc_user (port.c, reg.c, socket.c). + * + * This layer has four different locks: + * - The tipc_port spin_lock. This is protecting each port instance + * from parallel data access and removal. Since we can not place + * this lock in the port itself, it has been placed in the + * corresponding reference table entry, which has the same life + * cycle as the module. This entry is difficult to access from + * outside the TIPC core, however, so a pointer to the lock has + * been added in the port instance, -to be used for unlocking + * only. + * - A read/write lock to protect the reference table itself (teg.c). + * (Nobody is using read-only access to this, so it can just as + * well be changed to a spin_lock) + * - A spin lock to protect the registry of kernel/driver users (reg.c) + * - A global spin_lock (port_lock), which only task is to ensure + * consistency where more than one port is involved in an operation, + * i.e., whe a port is part of a linked list of ports. + * There are two such lists; 'port_list', which is used for management, + * and 'wait_list', which is used to queue ports during congestion. + * + * 3: The name table (name_table.c, name_distr.c, subscription.c) + * - There is one big read/write-lock (nametbl_lock) protecting the + * overall name table structure. Nothing must be added/removed to + * this structure without holding write access to it. + * - There is one local spin_lock per sub_sequence, which can be seen + * as a sub-domain to the nametbl_lock domain. It is used only + * for translation operations, and is needed because a translation + * steps the root of the 'publication' linked list between each lookup. + * This is always used within the scope of a nametbl_lock(read). + * - A local spin_lock protecting the queue of subscriber events. +*/ + +rwlock_t net_lock = RW_LOCK_UNLOCKED; +struct network net = { 0 }; + +struct node *net_select_remote_node(u32 addr, u32 ref) +{ + return zone_select_remote_node(net.zones[tipc_zone(addr)], addr, ref); +} + +u32 net_select_router(u32 addr, u32 ref) +{ + return zone_select_router(net.zones[tipc_zone(addr)], addr, ref); +} + + +u32 net_next_node(u32 a) +{ + if (net.zones[tipc_zone(a)]) + return zone_next_node(a); + return 0; +} + +void net_remove_as_router(u32 router) +{ + u32 z_num; + + for (z_num = 1; z_num <= tipc_max_zones; z_num++) { + if (!net.zones[z_num]) + continue; + zone_remove_as_router(net.zones[z_num], router); + } +} + +void net_send_external_routes(u32 dest) +{ + u32 z_num; + + for (z_num = 1; z_num <= tipc_max_zones; z_num++) { + if (net.zones[z_num]) + zone_send_external_routes(net.zones[z_num], dest); + } +} + +int net_init(void) +{ + u32 sz = sizeof(struct _zone *) * (tipc_max_zones + 1); + + memset(&net, 0, sizeof(net)); + net.zones = (struct _zone **)kmalloc(sz, GFP_ATOMIC); + if (!net.zones) { + return -ENOMEM; + } + memset(net.zones, 0, sz); + return TIPC_OK; +} + +void net_stop(void) +{ + u32 z_num; + + if (!net.zones) + return; + + for (z_num = 1; z_num <= tipc_max_zones; z_num++) { + zone_delete(net.zones[z_num]); + } + kfree(net.zones); + net.zones = 0; +} + +static void net_route_named_msg(struct sk_buff *buf) +{ + struct tipc_msg *msg = buf_msg(buf); + u32 dnode; + u32 dport; + + if (!msg_named(msg)) { + msg_dbg(msg, "net->drop_nam:"); + buf_discard(buf); + return; + } + + dnode = addr_domain(msg_lookup_scope(msg)); + dport = nametbl_translate(msg_nametype(msg), msg_nameinst(msg), &dnode); + dbg("net->lookup<%u,%u>-><%u,%x>\n", + msg_nametype(msg), msg_nameinst(msg), dport, dnode); + if (dport) { + msg_set_destnode(msg, dnode); + msg_set_destport(msg, dport); + net_route_msg(buf); + return; + } + msg_dbg(msg, "net->rej:NO NAME: "); + tipc_reject_msg(buf, TIPC_ERR_NO_NAME); +} + +void net_route_msg(struct sk_buff *buf) +{ + struct tipc_msg *msg; + u32 dnode; + + if (!buf) + return; + msg = buf_msg(buf); + + msg_incr_reroute_cnt(msg); + if (msg_reroute_cnt(msg) > 6) { + if (msg_errcode(msg)) { + msg_dbg(msg, "NET>DISC>:"); + buf_discard(buf); + } else { + msg_dbg(msg, "NET>REJ>:"); + tipc_reject_msg(buf, msg_destport(msg) ? + TIPC_ERR_NO_PORT : TIPC_ERR_NO_NAME); + } + return; + } + + msg_dbg(msg, "net->rout: "); + + /* Handle message for this node */ + dnode = msg_short(msg) ? tipc_own_addr : msg_destnode(msg); + if (in_scope(dnode, tipc_own_addr)) { + if (msg_isdata(msg)) { + if (msg_mcast(msg)) + port_recv_mcast(buf, NULL); + else if (msg_destport(msg)) + port_recv_msg(buf); + else + net_route_named_msg(buf); + return; + } + switch (msg_user(msg)) { + case ROUTE_DISTRIBUTOR: + cluster_recv_routing_table(buf); + break; + case NAME_DISTRIBUTOR: + named_recv(buf); + break; + case CONN_MANAGER: + port_recv_proto_msg(buf); + break; + default: + msg_dbg(msg,"DROP/NET/SEND>: "); + link_send(buf, dnode, msg_link_selector(msg)); +} + +int tipc_start_net(void) +{ + char addr_string[16]; + int res; + + if (tipc_mode != TIPC_NODE_MODE) + return -ENOPROTOOPT; + + tipc_mode = TIPC_NET_MODE; + named_reinit(); + port_reinit(); + + if ((res = bearer_init()) || + (res = net_init()) || + (res = cluster_init()) || + (res = bclink_init())) { + return res; + } + subscr_stop(); + cfg_stop(); + k_signal((Handler)subscr_start, 0); + k_signal((Handler)cfg_init, 0); + info("Started in network mode\n"); + info("Own node address %s, network identity %u\n", + addr_string_fill(addr_string, tipc_own_addr), tipc_net_id); + return TIPC_OK; +} + +void tipc_stop_net(void) +{ + if (tipc_mode != TIPC_NET_MODE) + return; + write_lock_bh(&net_lock); + bearer_stop(); + tipc_mode = TIPC_NODE_MODE; + bclink_stop(); + net_stop(); + write_unlock_bh(&net_lock); + info("Left network mode \n"); +} + diff --git a/net/tipc/net.h b/net/tipc/net.h new file mode 100644 index 00000000000..50098455a89 --- /dev/null +++ b/net/tipc/net.h @@ -0,0 +1,63 @@ +/* + * net/tipc/net.h: Include file for TIPC network routing code + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _TIPC_NET_H +#define _TIPC_NET_H + +struct _zone; + +/** + * struct network - TIPC network structure + * @zones: array of pointers to all zones within network + */ + +struct network { + struct _zone **zones; +}; + + +extern struct network net; +extern rwlock_t net_lock; + +int net_init(void); +void net_stop(void); +void net_remove_as_router(u32 router); +void net_send_external_routes(u32 dest); +void net_route_msg(struct sk_buff *buf); +struct node *net_select_remote_node(u32 addr, u32 ref); +u32 net_select_router(u32 addr, u32 ref); + +int tipc_start_net(void); +void tipc_stop_net(void); + +#endif diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c new file mode 100644 index 00000000000..35fbc793360 --- /dev/null +++ b/net/tipc/netlink.c @@ -0,0 +1,107 @@ +/* + * net/tipc/netlink.c: TIPC configuration handling + * + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "core.h" +#include "config.h" +#include + +static int handle_cmd(struct sk_buff *skb, struct genl_info *info) +{ + struct sk_buff *rep_buf; + struct nlmsghdr *rep_nlh; + struct nlmsghdr *req_nlh = info->nlhdr; + struct tipc_genlmsghdr *req_userhdr = info->userhdr; + int hdr_space = NLMSG_SPACE(0); + + if ((req_userhdr->cmd & 0xC000) && (!capable(CAP_NET_ADMIN))) + rep_buf = cfg_reply_error_string(TIPC_CFG_NOT_NET_ADMIN); + else + rep_buf = cfg_do_cmd(req_userhdr->dest, + req_userhdr->cmd, + NLMSG_DATA(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN, + NLMSG_PAYLOAD(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN), + hdr_space); + + if (rep_buf) { + skb_push(rep_buf, hdr_space); + rep_nlh = (struct nlmsghdr *)rep_buf->data; + memcpy(rep_nlh, req_nlh, hdr_space); + rep_nlh->nlmsg_len = rep_buf->len; + genlmsg_unicast(rep_buf, req_nlh->nlmsg_pid); + } + + return 0; +} + +static struct genl_family family = { + .id = TIPC_GENL_FAMILY, + .name = TIPC_GENL_NAME, + .version = TIPC_GENL_VERSION, + .hdrsize = TIPC_GENL_HDRLEN, + .maxattr = 0, + .owner = THIS_MODULE, +}; + +static struct genl_ops ops = { + .cmd = TIPC_GENL_CMD, + .doit = handle_cmd, +}; + +static int family_registered = 0; + +int netlink_start(void) +{ + if (genl_register_family(&family)) + goto err; + + family_registered = 1; + + if (genl_register_ops(&family, &ops)) + goto err_unregister; + + return 0; + + err_unregister: + genl_unregister_family(&family); + family_registered = 0; + err: + err("Failed to register netlink interface"); + return -EFAULT; +} + +void netlink_stop(void) +{ + if (family_registered) { + genl_unregister_family(&family); + family_registered = 0; + } +} diff --git a/net/tipc/node.c b/net/tipc/node.c new file mode 100644 index 00000000000..e311638b9b3 --- /dev/null +++ b/net/tipc/node.c @@ -0,0 +1,676 @@ +/* + * net/tipc/node.c: TIPC node management routines + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "core.h" +#include "config.h" +#include "node.h" +#include "cluster.h" +#include "net.h" +#include "addr.h" +#include "node_subscr.h" +#include "link.h" +#include "port.h" +#include "bearer.h" +#include "name_distr.h" +#include "net.h" + +void node_print(struct print_buf *buf, struct node *n_ptr, char *str); +static void node_lost_contact(struct node *n_ptr); +static void node_established_contact(struct node *n_ptr); + +struct node *nodes = NULL; /* sorted list of nodes within cluster */ + +u32 tipc_own_tag = 0; + +struct node *node_create(u32 addr) +{ + struct cluster *c_ptr; + struct node *n_ptr; + struct node **curr_node; + + n_ptr = kmalloc(sizeof(*n_ptr),GFP_ATOMIC); + if (n_ptr != NULL) { + memset(n_ptr, 0, sizeof(*n_ptr)); + n_ptr->addr = addr; + n_ptr->lock = SPIN_LOCK_UNLOCKED; + INIT_LIST_HEAD(&n_ptr->nsub); + + c_ptr = cluster_find(addr); + if (c_ptr == NULL) + c_ptr = cluster_create(addr); + if (c_ptr != NULL) { + n_ptr->owner = c_ptr; + cluster_attach_node(c_ptr, n_ptr); + n_ptr->last_router = -1; + + /* Insert node into ordered list */ + for (curr_node = &nodes; *curr_node; + curr_node = &(*curr_node)->next) { + if (addr < (*curr_node)->addr) { + n_ptr->next = *curr_node; + break; + } + } + (*curr_node) = n_ptr; + } else { + kfree(n_ptr); + n_ptr = NULL; + } + } + return n_ptr; +} + +void node_delete(struct node *n_ptr) +{ + if (!n_ptr) + return; + +#if 0 + /* Not needed because links are already deleted via bearer_stop() */ + + u32 l_num; + + for (l_num = 0; l_num < MAX_BEARERS; l_num++) { + link_delete(n_ptr->links[l_num]); + } +#endif + + dbg("node %x deleted\n", n_ptr->addr); + kfree(n_ptr); +} + + +/** + * node_link_up - handle addition of link + * + * Link becomes active (alone or shared) or standby, depending on its priority. + */ + +void node_link_up(struct node *n_ptr, struct link *l_ptr) +{ + struct link **active = &n_ptr->active_links[0]; + + info("Established link <%s> on network plane %c\n", + l_ptr->name, l_ptr->b_ptr->net_plane); + + if (!active[0]) { + dbg(" link %x into %x/%x\n", l_ptr, &active[0], &active[1]); + active[0] = active[1] = l_ptr; + node_established_contact(n_ptr); + return; + } + if (l_ptr->priority < active[0]->priority) { + info("Link is standby\n"); + return; + } + link_send_duplicate(active[0], l_ptr); + if (l_ptr->priority == active[0]->priority) { + active[0] = l_ptr; + return; + } + info("Link <%s> on network plane %c becomes standby\n", + active[0]->name, active[0]->b_ptr->net_plane); + active[0] = active[1] = l_ptr; +} + +/** + * node_select_active_links - select active link + */ + +static void node_select_active_links(struct node *n_ptr) +{ + struct link **active = &n_ptr->active_links[0]; + u32 i; + u32 highest_prio = 0; + + active[0] = active[1] = 0; + + for (i = 0; i < MAX_BEARERS; i++) { + struct link *l_ptr = n_ptr->links[i]; + + if (!l_ptr || !link_is_up(l_ptr) || + (l_ptr->priority < highest_prio)) + continue; + + if (l_ptr->priority > highest_prio) { + highest_prio = l_ptr->priority; + active[0] = active[1] = l_ptr; + } else { + active[1] = l_ptr; + } + } +} + +/** + * node_link_down - handle loss of link + */ + +void node_link_down(struct node *n_ptr, struct link *l_ptr) +{ + struct link **active; + + if (!link_is_active(l_ptr)) { + info("Lost standby link <%s> on network plane %c\n", + l_ptr->name, l_ptr->b_ptr->net_plane); + return; + } + info("Lost link <%s> on network plane %c\n", + l_ptr->name, l_ptr->b_ptr->net_plane); + + active = &n_ptr->active_links[0]; + if (active[0] == l_ptr) + active[0] = active[1]; + if (active[1] == l_ptr) + active[1] = active[0]; + if (active[0] == l_ptr) + node_select_active_links(n_ptr); + if (node_is_up(n_ptr)) + link_changeover(l_ptr); + else + node_lost_contact(n_ptr); +} + +int node_has_active_links(struct node *n_ptr) +{ + return (n_ptr && + ((n_ptr->active_links[0]) || (n_ptr->active_links[1]))); +} + +int node_has_redundant_links(struct node *n_ptr) +{ + return (node_has_active_links(n_ptr) && + (n_ptr->active_links[0] != n_ptr->active_links[1])); +} + +int node_has_active_routes(struct node *n_ptr) +{ + return (n_ptr && (n_ptr->last_router >= 0)); +} + +int node_is_up(struct node *n_ptr) +{ + return (node_has_active_links(n_ptr) || node_has_active_routes(n_ptr)); +} + +struct node *node_attach_link(struct link *l_ptr) +{ + struct node *n_ptr = node_find(l_ptr->addr); + + if (!n_ptr) + n_ptr = node_create(l_ptr->addr); + if (n_ptr) { + u32 bearer_id = l_ptr->b_ptr->identity; + char addr_string[16]; + + assert(bearer_id < MAX_BEARERS); + if (n_ptr->link_cnt >= 2) { + char addr_string[16]; + + err("Attempt to create third link to %s\n", + addr_string_fill(addr_string, n_ptr->addr)); + return 0; + } + + if (!n_ptr->links[bearer_id]) { + n_ptr->links[bearer_id] = l_ptr; + net.zones[tipc_zone(l_ptr->addr)]->links++; + n_ptr->link_cnt++; + return n_ptr; + } + err("Attempt to establish second link on <%s> to <%s> \n", + l_ptr->b_ptr->publ.name, + addr_string_fill(addr_string, l_ptr->addr)); + } + return 0; +} + +void node_detach_link(struct node *n_ptr, struct link *l_ptr) +{ + n_ptr->links[l_ptr->b_ptr->identity] = 0; + net.zones[tipc_zone(l_ptr->addr)]->links--; + n_ptr->link_cnt--; +} + +/* + * Routing table management - five cases to handle: + * + * 1: A link towards a zone/cluster external node comes up. + * => Send a multicast message updating routing tables of all + * system nodes within own cluster that the new destination + * can be reached via this node. + * (node.establishedContact()=>cluster.multicastNewRoute()) + * + * 2: A link towards a slave node comes up. + * => Send a multicast message updating routing tables of all + * system nodes within own cluster that the new destination + * can be reached via this node. + * (node.establishedContact()=>cluster.multicastNewRoute()) + * => Send a message to the slave node about existence + * of all system nodes within cluster: + * (node.establishedContact()=>cluster.sendLocalRoutes()) + * + * 3: A new cluster local system node becomes available. + * => Send message(s) to this particular node containing + * information about all cluster external and slave + * nodes which can be reached via this node. + * (node.establishedContact()==>network.sendExternalRoutes()) + * (node.establishedContact()==>network.sendSlaveRoutes()) + * => Send messages to all directly connected slave nodes + * containing information about the existence of the new node + * (node.establishedContact()=>cluster.multicastNewRoute()) + * + * 4: The link towards a zone/cluster external node or slave + * node goes down. + * => Send a multcast message updating routing tables of all + * nodes within cluster that the new destination can not any + * longer be reached via this node. + * (node.lostAllLinks()=>cluster.bcastLostRoute()) + * + * 5: A cluster local system node becomes unavailable. + * => Remove all references to this node from the local + * routing tables. Note: This is a completely node + * local operation. + * (node.lostAllLinks()=>network.removeAsRouter()) + * => Send messages to all directly connected slave nodes + * containing information about loss of the node + * (node.establishedContact()=>cluster.multicastLostRoute()) + * + */ + +static void node_established_contact(struct node *n_ptr) +{ + struct cluster *c_ptr; + + dbg("node_established_contact:-> %x\n", n_ptr->addr); + if (!node_has_active_routes(n_ptr)) { + k_signal((Handler)named_node_up, n_ptr->addr); + } + + /* Syncronize broadcast acks */ + n_ptr->bclink.acked = bclink_get_last_sent(); + + if (is_slave(tipc_own_addr)) + return; + if (!in_own_cluster(n_ptr->addr)) { + /* Usage case 1 (see above) */ + c_ptr = cluster_find(tipc_own_addr); + if (!c_ptr) + c_ptr = cluster_create(tipc_own_addr); + if (c_ptr) + cluster_bcast_new_route(c_ptr, n_ptr->addr, 1, + tipc_max_nodes); + return; + } + + c_ptr = n_ptr->owner; + if (is_slave(n_ptr->addr)) { + /* Usage case 2 (see above) */ + cluster_bcast_new_route(c_ptr, n_ptr->addr, 1, tipc_max_nodes); + cluster_send_local_routes(c_ptr, n_ptr->addr); + return; + } + + if (n_ptr->bclink.supported) { + nmap_add(&cluster_bcast_nodes, n_ptr->addr); + if (n_ptr->addr < tipc_own_addr) + tipc_own_tag++; + } + + /* Case 3 (see above) */ + net_send_external_routes(n_ptr->addr); + cluster_send_slave_routes(c_ptr, n_ptr->addr); + cluster_bcast_new_route(c_ptr, n_ptr->addr, LOWEST_SLAVE, + highest_allowed_slave); +} + +static void node_lost_contact(struct node *n_ptr) +{ + struct cluster *c_ptr; + struct node_subscr *ns, *tns; + char addr_string[16]; + u32 i; + + /* Clean up broadcast reception remains */ + n_ptr->bclink.gap_after = n_ptr->bclink.gap_to = 0; + while (n_ptr->bclink.deferred_head) { + struct sk_buff* buf = n_ptr->bclink.deferred_head; + n_ptr->bclink.deferred_head = buf->next; + buf_discard(buf); + } + if (n_ptr->bclink.defragm) { + buf_discard(n_ptr->bclink.defragm); + n_ptr->bclink.defragm = NULL; + } + if (in_own_cluster(n_ptr->addr) && n_ptr->bclink.supported) { + bclink_acknowledge(n_ptr, mod(n_ptr->bclink.acked + 10000)); + } + + /* Update routing tables */ + if (is_slave(tipc_own_addr)) { + net_remove_as_router(n_ptr->addr); + } else { + if (!in_own_cluster(n_ptr->addr)) { + /* Case 4 (see above) */ + c_ptr = cluster_find(tipc_own_addr); + cluster_bcast_lost_route(c_ptr, n_ptr->addr, 1, + tipc_max_nodes); + } else { + /* Case 5 (see above) */ + c_ptr = cluster_find(n_ptr->addr); + if (is_slave(n_ptr->addr)) { + cluster_bcast_lost_route(c_ptr, n_ptr->addr, 1, + tipc_max_nodes); + } else { + if (n_ptr->bclink.supported) { + nmap_remove(&cluster_bcast_nodes, + n_ptr->addr); + if (n_ptr->addr < tipc_own_addr) + tipc_own_tag--; + } + net_remove_as_router(n_ptr->addr); + cluster_bcast_lost_route(c_ptr, n_ptr->addr, + LOWEST_SLAVE, + highest_allowed_slave); + } + } + } + if (node_has_active_routes(n_ptr)) + return; + + info("Lost contact with %s\n", + addr_string_fill(addr_string, n_ptr->addr)); + + /* Abort link changeover */ + for (i = 0; i < MAX_BEARERS; i++) { + struct link *l_ptr = n_ptr->links[i]; + if (!l_ptr) + continue; + l_ptr->reset_checkpoint = l_ptr->next_in_no; + l_ptr->exp_msg_count = 0; + link_reset_fragments(l_ptr); + } + + /* Notify subscribers */ + list_for_each_entry_safe(ns, tns, &n_ptr->nsub, nodesub_list) { + ns->node = 0; + list_del_init(&ns->nodesub_list); + k_signal((Handler)ns->handle_node_down, + (unsigned long)ns->usr_handle); + } +} + +/** + * node_select_next_hop - find the next-hop node for a message + * + * Called by when cluster local lookup has failed. + */ + +struct node *node_select_next_hop(u32 addr, u32 selector) +{ + struct node *n_ptr; + u32 router_addr; + + if (!addr_domain_valid(addr)) + return 0; + + /* Look for direct link to destination processsor */ + n_ptr = node_find(addr); + if (n_ptr && node_has_active_links(n_ptr)) + return n_ptr; + + /* Cluster local system nodes *must* have direct links */ + if (!is_slave(addr) && in_own_cluster(addr)) + return 0; + + /* Look for cluster local router with direct link to node */ + router_addr = node_select_router(n_ptr, selector); + if (router_addr) + return node_select(router_addr, selector); + + /* Slave nodes can only be accessed within own cluster via a + known router with direct link -- if no router was found,give up */ + if (is_slave(addr)) + return 0; + + /* Inter zone/cluster -- find any direct link to remote cluster */ + addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0); + n_ptr = net_select_remote_node(addr, selector); + if (n_ptr && node_has_active_links(n_ptr)) + return n_ptr; + + /* Last resort -- look for any router to anywhere in remote zone */ + router_addr = net_select_router(addr, selector); + if (router_addr) + return node_select(router_addr, selector); + + return 0; +} + +/** + * node_select_router - select router to reach specified node + * + * Uses a deterministic and fair algorithm for selecting router node. + */ + +u32 node_select_router(struct node *n_ptr, u32 ref) +{ + u32 ulim; + u32 mask; + u32 start; + u32 r; + + if (!n_ptr) + return 0; + + if (n_ptr->last_router < 0) + return 0; + ulim = ((n_ptr->last_router + 1) * 32) - 1; + + /* Start entry must be random */ + mask = tipc_max_nodes; + while (mask > ulim) + mask >>= 1; + start = ref & mask; + r = start; + + /* Lookup upwards with wrap-around */ + do { + if (((n_ptr->routers[r / 32]) >> (r % 32)) & 1) + break; + } while (++r <= ulim); + if (r > ulim) { + r = 1; + do { + if (((n_ptr->routers[r / 32]) >> (r % 32)) & 1) + break; + } while (++r < start); + assert(r != start); + } + assert(r && (r <= ulim)); + return tipc_addr(own_zone(), own_cluster(), r); +} + +void node_add_router(struct node *n_ptr, u32 router) +{ + u32 r_num = tipc_node(router); + + n_ptr->routers[r_num / 32] = + ((1 << (r_num % 32)) | n_ptr->routers[r_num / 32]); + n_ptr->last_router = tipc_max_nodes / 32; + while ((--n_ptr->last_router >= 0) && + !n_ptr->routers[n_ptr->last_router]); +} + +void node_remove_router(struct node *n_ptr, u32 router) +{ + u32 r_num = tipc_node(router); + + if (n_ptr->last_router < 0) + return; /* No routes */ + + n_ptr->routers[r_num / 32] = + ((~(1 << (r_num % 32))) & (n_ptr->routers[r_num / 32])); + n_ptr->last_router = tipc_max_nodes / 32; + while ((--n_ptr->last_router >= 0) && + !n_ptr->routers[n_ptr->last_router]); + + if (!node_is_up(n_ptr)) + node_lost_contact(n_ptr); +} + +#if 0 +void node_print(struct print_buf *buf, struct node *n_ptr, char *str) +{ + u32 i; + + tipc_printf(buf, "\n\n%s", str); + for (i = 0; i < MAX_BEARERS; i++) { + if (!n_ptr->links[i]) + continue; + tipc_printf(buf, "Links[%u]: %x, ", i, n_ptr->links[i]); + } + tipc_printf(buf, "Active links: [%x,%x]\n", + n_ptr->active_links[0], n_ptr->active_links[1]); +} +#endif + +u32 tipc_available_nodes(const u32 domain) +{ + struct node *n_ptr; + u32 cnt = 0; + + for (n_ptr = nodes; n_ptr; n_ptr = n_ptr->next) { + if (!in_scope(domain, n_ptr->addr)) + continue; + if (node_is_up(n_ptr)) + cnt++; + } + return cnt; +} + +struct sk_buff *node_get_nodes(const void *req_tlv_area, int req_tlv_space) +{ + u32 domain; + struct sk_buff *buf; + struct node *n_ptr; + struct tipc_node_info node_info; + + if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) + return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + + domain = *(u32 *)TLV_DATA(req_tlv_area); + domain = ntohl(domain); + if (!addr_domain_valid(domain)) + return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE + " (network address)"); + + if (!nodes) + return cfg_reply_none(); + + /* For now, get space for all other nodes + (will need to modify this when slave nodes are supported */ + + buf = cfg_reply_alloc(TLV_SPACE(sizeof(node_info)) * + (tipc_max_nodes - 1)); + if (!buf) + return NULL; + + /* Add TLVs for all nodes in scope */ + + for (n_ptr = nodes; n_ptr; n_ptr = n_ptr->next) { + if (!in_scope(domain, n_ptr->addr)) + continue; + node_info.addr = htonl(n_ptr->addr); + node_info.up = htonl(node_is_up(n_ptr)); + cfg_append_tlv(buf, TIPC_TLV_NODE_INFO, + &node_info, sizeof(node_info)); + } + + return buf; +} + +struct sk_buff *node_get_links(const void *req_tlv_area, int req_tlv_space) +{ + u32 domain; + struct sk_buff *buf; + struct node *n_ptr; + struct tipc_link_info link_info; + + if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) + return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + + domain = *(u32 *)TLV_DATA(req_tlv_area); + domain = ntohl(domain); + if (!addr_domain_valid(domain)) + return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE + " (network address)"); + + if (!nodes) + return cfg_reply_none(); + + /* For now, get space for 2 links to all other nodes + bcast link + (will need to modify this when slave nodes are supported */ + + buf = cfg_reply_alloc(TLV_SPACE(sizeof(link_info)) * + (2 * (tipc_max_nodes - 1) + 1)); + if (!buf) + return NULL; + + /* Add TLV for broadcast link */ + + link_info.dest = tipc_own_addr & 0xfffff00; + link_info.dest = htonl(link_info.dest); + link_info.up = htonl(1); + sprintf(link_info.str, bc_link_name); + cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info)); + + /* Add TLVs for any other links in scope */ + + for (n_ptr = nodes; n_ptr; n_ptr = n_ptr->next) { + u32 i; + + if (!in_scope(domain, n_ptr->addr)) + continue; + for (i = 0; i < MAX_BEARERS; i++) { + if (!n_ptr->links[i]) + continue; + link_info.dest = htonl(n_ptr->addr); + link_info.up = htonl(link_is_up(n_ptr->links[i])); + strcpy(link_info.str, n_ptr->links[i]->name); + cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, + &link_info, sizeof(link_info)); + } + } + + return buf; +} diff --git a/net/tipc/node.h b/net/tipc/node.h new file mode 100644 index 00000000000..1f616873a72 --- /dev/null +++ b/net/tipc/node.h @@ -0,0 +1,141 @@ +/* + * net/tipc/node.h: Include file for TIPC node management routines + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _TIPC_NODE_H +#define _TIPC_NODE_H + +#include "node_subscr.h" +#include "addr.h" +#include "cluster.h" +#include "bearer.h" + +/** + * struct node - TIPC node structure + * @addr: network address of node + * @lock: spinlock governing access to structure + * @owner: pointer to cluster that node belongs to + * @next: pointer to next node in sorted list of cluster's nodes + * @nsub: list of "node down" subscriptions monitoring node + * @active_links: pointers to active links to node + * @links: pointers to all links to node + * @link_cnt: number of links to node + * @permit_changeover: non-zero if node has redundant links to this system + * @routers: bitmap (used for multicluster communication) + * @last_router: (used for multicluster communication) + * @bclink: broadcast-related info + * @supported: non-zero if node supports TIPC b'cast capability + * @acked: sequence # of last outbound b'cast message acknowledged by node + * @last_in: sequence # of last in-sequence b'cast message received from node + * @gap_after: sequence # of last message not requiring a NAK request + * @gap_to: sequence # of last message requiring a NAK request + * @nack_sync: counter that determines when NAK requests should be sent + * @deferred_head: oldest OOS b'cast message received from node + * @deferred_tail: newest OOS b'cast message received from node + * @defragm: list of partially reassembled b'cast message fragments from node + */ + +struct node { + u32 addr; + spinlock_t lock; + struct cluster *owner; + struct node *next; + struct list_head nsub; + struct link *active_links[2]; + struct link *links[MAX_BEARERS]; + int link_cnt; + int permit_changeover; + u32 routers[512/32]; + int last_router; + struct { + int supported; + u32 acked; + u32 last_in; + u32 gap_after; + u32 gap_to; + u32 nack_sync; + struct sk_buff *deferred_head; + struct sk_buff *deferred_tail; + struct sk_buff *defragm; + } bclink; +}; + +extern struct node *nodes; +extern u32 tipc_own_tag; + +struct node *node_create(u32 addr); +void node_delete(struct node *n_ptr); +struct node *node_attach_link(struct link *l_ptr); +void node_detach_link(struct node *n_ptr, struct link *l_ptr); +void node_link_down(struct node *n_ptr, struct link *l_ptr); +void node_link_up(struct node *n_ptr, struct link *l_ptr); +int node_has_active_links(struct node *n_ptr); +int node_has_redundant_links(struct node *n_ptr); +u32 node_select_router(struct node *n_ptr, u32 ref); +struct node *node_select_next_hop(u32 addr, u32 selector); +int node_is_up(struct node *n_ptr); +void node_add_router(struct node *n_ptr, u32 router); +void node_remove_router(struct node *n_ptr, u32 router); +struct sk_buff *node_get_links(const void *req_tlv_area, int req_tlv_space); +struct sk_buff *node_get_nodes(const void *req_tlv_area, int req_tlv_space); + +static inline struct node *node_find(u32 addr) +{ + if (likely(in_own_cluster(addr))) + return local_nodes[tipc_node(addr)]; + else if (addr_domain_valid(addr)) { + struct cluster *c_ptr = cluster_find(addr); + + if (c_ptr) + return c_ptr->nodes[tipc_node(addr)]; + } + return 0; +} + +static inline struct node *node_select(u32 addr, u32 selector) +{ + if (likely(in_own_cluster(addr))) + return local_nodes[tipc_node(addr)]; + return node_select_next_hop(addr, selector); +} + +static inline void node_lock(struct node *n_ptr) +{ + spin_lock_bh(&n_ptr->lock); +} + +static inline void node_unlock(struct node *n_ptr) +{ + spin_unlock_bh(&n_ptr->lock); +} + +#endif diff --git a/net/tipc/node_subscr.c b/net/tipc/node_subscr.c new file mode 100644 index 00000000000..c38a3b0e847 --- /dev/null +++ b/net/tipc/node_subscr.c @@ -0,0 +1,76 @@ +/* + * net/tipc/node_subscr.c: TIPC "node down" subscription handling + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "core.h" +#include "dbg.h" +#include "node_subscr.h" +#include "node.h" +#include "addr.h" + +/** + * nodesub_subscribe - create "node down" subscription for specified node + */ + +void nodesub_subscribe(struct node_subscr *node_sub, u32 addr, + void *usr_handle, net_ev_handler handle_down) +{ + node_sub->node = 0; + if (addr == tipc_own_addr) + return; + if (!addr_node_valid(addr)) { + warn("node_subscr with illegal %x\n", addr); + return; + } + + node_sub->handle_node_down = handle_down; + node_sub->usr_handle = usr_handle; + node_sub->node = node_find(addr); + assert(node_sub->node); + node_lock(node_sub->node); + list_add_tail(&node_sub->nodesub_list, &node_sub->node->nsub); + node_unlock(node_sub->node); +} + +/** + * nodesub_unsubscribe - cancel "node down" subscription (if any) + */ + +void nodesub_unsubscribe(struct node_subscr *node_sub) +{ + if (!node_sub->node) + return; + + node_lock(node_sub->node); + list_del_init(&node_sub->nodesub_list); + node_unlock(node_sub->node); +} diff --git a/net/tipc/node_subscr.h b/net/tipc/node_subscr.h new file mode 100644 index 00000000000..63ae92e0c82 --- /dev/null +++ b/net/tipc/node_subscr.h @@ -0,0 +1,60 @@ +/* + * net/tipc/node_subscr.h: Include file for TIPC "node down" subscription handling + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _TIPC_NODE_SUBSCR_H +#define _TIPC_NODE_SUBSCR_H + +#include "addr.h" + +typedef void (*net_ev_handler) (void *usr_handle); + +/** + * struct node_subscr - "node down" subscription entry + * @node: ptr to node structure of interest (or NULL, if none) + * @handle_node_down: routine to invoke when node fails + * @usr_handle: argument to pass to routine when node fails + * @nodesub_list: adjacent entries in list of subscriptions for the node + */ + +struct node_subscr { + struct node *node; + net_ev_handler handle_node_down; + void *usr_handle; + struct list_head nodesub_list; +}; + +void nodesub_subscribe(struct node_subscr *node_sub, u32 addr, + void *usr_handle, net_ev_handler handle_down); +void nodesub_unsubscribe(struct node_subscr *node_sub); + +#endif diff --git a/net/tipc/port.c b/net/tipc/port.c new file mode 100644 index 00000000000..f0f228c9589 --- /dev/null +++ b/net/tipc/port.c @@ -0,0 +1,1704 @@ +/* + * net/tipc/port.c: TIPC port code + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2004-2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "core.h" +#include "config.h" +#include "dbg.h" +#include "port.h" +#include "addr.h" +#include "link.h" +#include "node.h" +#include "port.h" +#include "name_table.h" +#include "user_reg.h" +#include "msg.h" +#include "bcast.h" + +/* Connection management: */ +#define PROBING_INTERVAL 3600000 /* [ms] => 1 h */ +#define CONFIRMED 0 +#define PROBING 1 + +#define MAX_REJECT_SIZE 1024 + +static struct sk_buff *msg_queue_head = 0; +static struct sk_buff *msg_queue_tail = 0; + +spinlock_t port_list_lock = SPIN_LOCK_UNLOCKED; +static spinlock_t queue_lock = SPIN_LOCK_UNLOCKED; + +LIST_HEAD(ports); +static void port_handle_node_down(unsigned long ref); +static struct sk_buff* port_build_self_abort_msg(struct port *,u32 err); +static struct sk_buff* port_build_peer_abort_msg(struct port *,u32 err); +static void port_timeout(unsigned long ref); + + +static inline u32 port_peernode(struct port *p_ptr) +{ + return msg_destnode(&p_ptr->publ.phdr); +} + +static inline u32 port_peerport(struct port *p_ptr) +{ + return msg_destport(&p_ptr->publ.phdr); +} + +static inline u32 port_out_seqno(struct port *p_ptr) +{ + return msg_transp_seqno(&p_ptr->publ.phdr); +} + +static inline void port_set_out_seqno(struct port *p_ptr, u32 seqno) +{ + msg_set_transp_seqno(&p_ptr->publ.phdr,seqno); +} + +static inline void port_incr_out_seqno(struct port *p_ptr) +{ + struct tipc_msg *m = &p_ptr->publ.phdr; + + if (likely(!msg_routed(m))) + return; + msg_set_transp_seqno(m, (msg_transp_seqno(m) + 1)); +} + +/** + * tipc_multicast - send a multicast message to local and remote destinations + */ + +int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, u32 domain, + u32 num_sect, struct iovec const *msg_sect) +{ + struct tipc_msg *hdr; + struct sk_buff *buf; + struct sk_buff *ibuf = NULL; + struct port_list dports = {0, NULL, }; + struct port *oport = port_deref(ref); + int ext_targets; + int res; + + if (unlikely(!oport)) + return -EINVAL; + + /* Create multicast message */ + + hdr = &oport->publ.phdr; + msg_set_type(hdr, TIPC_MCAST_MSG); + msg_set_nametype(hdr, seq->type); + msg_set_namelower(hdr, seq->lower); + msg_set_nameupper(hdr, seq->upper); + msg_set_hdr_sz(hdr, MCAST_H_SIZE); + res = msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE, + !oport->user_port, &buf); + if (unlikely(!buf)) + return res; + + /* Figure out where to send multicast message */ + + ext_targets = nametbl_mc_translate(seq->type, seq->lower, seq->upper, + TIPC_NODE_SCOPE, &dports); + + /* Send message to destinations (duplicate it only if necessary) */ + + if (ext_targets) { + if (dports.count != 0) { + ibuf = skb_copy(buf, GFP_ATOMIC); + if (ibuf == NULL) { + port_list_free(&dports); + buf_discard(buf); + return -ENOMEM; + } + } + res = bclink_send_msg(buf); + if ((res < 0) && (dports.count != 0)) { + buf_discard(ibuf); + } + } else { + ibuf = buf; + } + + if (res >= 0) { + if (ibuf) + port_recv_mcast(ibuf, &dports); + } else { + port_list_free(&dports); + } + return res; +} + +/** + * port_recv_mcast - deliver multicast message to all destination ports + * + * If there is no port list, perform a lookup to create one + */ + +void port_recv_mcast(struct sk_buff *buf, struct port_list *dp) +{ + struct tipc_msg* msg; + struct port_list dports = {0, NULL, }; + struct port_list *item = dp; + int cnt = 0; + + assert(buf); + msg = buf_msg(buf); + + /* Create destination port list, if one wasn't supplied */ + + if (dp == NULL) { + nametbl_mc_translate(msg_nametype(msg), + msg_namelower(msg), + msg_nameupper(msg), + TIPC_CLUSTER_SCOPE, + &dports); + item = dp = &dports; + } + + /* Deliver a copy of message to each destination port */ + + if (dp->count != 0) { + if (dp->count == 1) { + msg_set_destport(msg, dp->ports[0]); + port_recv_msg(buf); + port_list_free(dp); + return; + } + for (; cnt < dp->count; cnt++) { + int index = cnt % PLSIZE; + struct sk_buff *b = skb_clone(buf, GFP_ATOMIC); + + if (b == NULL) { + warn("Buffer allocation failure\n"); + msg_dbg(msg, "LOST:"); + goto exit; + } + if ((index == 0) && (cnt != 0)) { + item = item->next; + } + msg_set_destport(buf_msg(b),item->ports[index]); + port_recv_msg(b); + } + } +exit: + buf_discard(buf); + port_list_free(dp); +} + +/** + * tipc_createport_raw - create a native TIPC port + * + * Returns local port reference + */ + +u32 tipc_createport_raw(void *usr_handle, + u32 (*dispatcher)(struct tipc_port *, struct sk_buff *), + void (*wakeup)(struct tipc_port *), + const u32 importance) +{ + struct port *p_ptr; + struct tipc_msg *msg; + u32 ref; + + p_ptr = kmalloc(sizeof(*p_ptr), GFP_ATOMIC); + if (p_ptr == NULL) { + warn("Memory squeeze; failed to create port\n"); + return 0; + } + memset(p_ptr, 0, sizeof(*p_ptr)); + ref = ref_acquire(p_ptr, &p_ptr->publ.lock); + if (!ref) { + warn("Reference Table Exhausted\n"); + kfree(p_ptr); + return 0; + } + + port_lock(ref); + p_ptr->publ.ref = ref; + msg = &p_ptr->publ.phdr; + msg_init(msg, DATA_LOW, TIPC_NAMED_MSG, TIPC_OK, LONG_H_SIZE, 0); + msg_set_orignode(msg, tipc_own_addr); + msg_set_prevnode(msg, tipc_own_addr); + msg_set_origport(msg, ref); + msg_set_importance(msg,importance); + p_ptr->last_in_seqno = 41; + p_ptr->sent = 1; + p_ptr->publ.usr_handle = usr_handle; + INIT_LIST_HEAD(&p_ptr->wait_list); + INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list); + p_ptr->congested_link = 0; + p_ptr->max_pkt = MAX_PKT_DEFAULT; + p_ptr->dispatcher = dispatcher; + p_ptr->wakeup = wakeup; + p_ptr->user_port = 0; + k_init_timer(&p_ptr->timer, (Handler)port_timeout, ref); + spin_lock_bh(&port_list_lock); + INIT_LIST_HEAD(&p_ptr->publications); + INIT_LIST_HEAD(&p_ptr->port_list); + list_add_tail(&p_ptr->port_list, &ports); + spin_unlock_bh(&port_list_lock); + port_unlock(p_ptr); + return ref; +} + +int tipc_deleteport(u32 ref) +{ + struct port *p_ptr; + struct sk_buff *buf = 0; + + tipc_withdraw(ref, 0, 0); + p_ptr = port_lock(ref); + if (!p_ptr) + return -EINVAL; + + ref_discard(ref); + port_unlock(p_ptr); + + k_cancel_timer(&p_ptr->timer); + if (p_ptr->publ.connected) { + buf = port_build_peer_abort_msg(p_ptr, TIPC_ERR_NO_PORT); + nodesub_unsubscribe(&p_ptr->subscription); + } + if (p_ptr->user_port) { + reg_remove_port(p_ptr->user_port); + kfree(p_ptr->user_port); + } + + spin_lock_bh(&port_list_lock); + list_del(&p_ptr->port_list); + list_del(&p_ptr->wait_list); + spin_unlock_bh(&port_list_lock); + k_term_timer(&p_ptr->timer); + kfree(p_ptr); + dbg("Deleted port %u\n", ref); + net_route_msg(buf); + return TIPC_OK; +} + +/** + * tipc_get_port() - return port associated with 'ref' + * + * Note: Port is not locked. + */ + +struct tipc_port *tipc_get_port(const u32 ref) +{ + return (struct tipc_port *)ref_deref(ref); +} + +/** + * tipc_get_handle - return user handle associated to port 'ref' + */ + +void *tipc_get_handle(const u32 ref) +{ + struct port *p_ptr; + void * handle; + + p_ptr = port_lock(ref); + if (!p_ptr) + return 0; + handle = p_ptr->publ.usr_handle; + port_unlock(p_ptr); + return handle; +} + +static inline int port_unreliable(struct port *p_ptr) +{ + return msg_src_droppable(&p_ptr->publ.phdr); +} + +int tipc_portunreliable(u32 ref, unsigned int *isunreliable) +{ + struct port *p_ptr; + + p_ptr = port_lock(ref); + if (!p_ptr) + return -EINVAL; + *isunreliable = port_unreliable(p_ptr); + spin_unlock_bh(p_ptr->publ.lock); + return TIPC_OK; +} + +int tipc_set_portunreliable(u32 ref, unsigned int isunreliable) +{ + struct port *p_ptr; + + p_ptr = port_lock(ref); + if (!p_ptr) + return -EINVAL; + msg_set_src_droppable(&p_ptr->publ.phdr, (isunreliable != 0)); + port_unlock(p_ptr); + return TIPC_OK; +} + +static inline int port_unreturnable(struct port *p_ptr) +{ + return msg_dest_droppable(&p_ptr->publ.phdr); +} + +int tipc_portunreturnable(u32 ref, unsigned int *isunrejectable) +{ + struct port *p_ptr; + + p_ptr = port_lock(ref); + if (!p_ptr) + return -EINVAL; + *isunrejectable = port_unreturnable(p_ptr); + spin_unlock_bh(p_ptr->publ.lock); + return TIPC_OK; +} + +int tipc_set_portunreturnable(u32 ref, unsigned int isunrejectable) +{ + struct port *p_ptr; + + p_ptr = port_lock(ref); + if (!p_ptr) + return -EINVAL; + msg_set_dest_droppable(&p_ptr->publ.phdr, (isunrejectable != 0)); + port_unlock(p_ptr); + return TIPC_OK; +} + +/* + * port_build_proto_msg(): build a port level protocol + * or a connection abortion message. Called with + * tipc_port lock on. + */ +static struct sk_buff *port_build_proto_msg(u32 destport, u32 destnode, + u32 origport, u32 orignode, + u32 usr, u32 type, u32 err, + u32 seqno, u32 ack) +{ + struct sk_buff *buf; + struct tipc_msg *msg; + + buf = buf_acquire(LONG_H_SIZE); + if (buf) { + msg = buf_msg(buf); + msg_init(msg, usr, type, err, LONG_H_SIZE, destnode); + msg_set_destport(msg, destport); + msg_set_origport(msg, origport); + msg_set_destnode(msg, destnode); + msg_set_orignode(msg, orignode); + msg_set_transp_seqno(msg, seqno); + msg_set_msgcnt(msg, ack); + msg_dbg(msg, "PORT>SEND>:"); + } + return buf; +} + +int tipc_set_msg_option(struct tipc_port *tp_ptr, const char *opt, const u32 sz) +{ + msg_expand(&tp_ptr->phdr, msg_destnode(&tp_ptr->phdr)); + msg_set_options(&tp_ptr->phdr, opt, sz); + return TIPC_OK; +} + +int tipc_reject_msg(struct sk_buff *buf, u32 err) +{ + struct tipc_msg *msg = buf_msg(buf); + struct sk_buff *rbuf; + struct tipc_msg *rmsg; + int hdr_sz; + u32 imp = msg_importance(msg); + u32 data_sz = msg_data_sz(msg); + + if (data_sz > MAX_REJECT_SIZE) + data_sz = MAX_REJECT_SIZE; + if (msg_connected(msg) && (imp < TIPC_CRITICAL_IMPORTANCE)) + imp++; + msg_dbg(msg, "port->rej: "); + + /* discard rejected message if it shouldn't be returned to sender */ + if (msg_errcode(msg) || msg_dest_droppable(msg)) { + buf_discard(buf); + return data_sz; + } + + /* construct rejected message */ + if (msg_mcast(msg)) + hdr_sz = MCAST_H_SIZE; + else + hdr_sz = LONG_H_SIZE; + rbuf = buf_acquire(data_sz + hdr_sz); + if (rbuf == NULL) { + buf_discard(buf); + return data_sz; + } + rmsg = buf_msg(rbuf); + msg_init(rmsg, imp, msg_type(msg), err, hdr_sz, msg_orignode(msg)); + msg_set_destport(rmsg, msg_origport(msg)); + msg_set_prevnode(rmsg, tipc_own_addr); + msg_set_origport(rmsg, msg_destport(msg)); + if (msg_short(msg)) + msg_set_orignode(rmsg, tipc_own_addr); + else + msg_set_orignode(rmsg, msg_destnode(msg)); + msg_set_size(rmsg, data_sz + hdr_sz); + msg_set_nametype(rmsg, msg_nametype(msg)); + msg_set_nameinst(rmsg, msg_nameinst(msg)); + memcpy(rbuf->data + hdr_sz, msg_data(msg), data_sz); + + /* send self-abort message when rejecting on a connected port */ + if (msg_connected(msg)) { + struct sk_buff *abuf = 0; + struct port *p_ptr = port_lock(msg_destport(msg)); + + if (p_ptr) { + if (p_ptr->publ.connected) + abuf = port_build_self_abort_msg(p_ptr, err); + port_unlock(p_ptr); + } + net_route_msg(abuf); + } + + /* send rejected message */ + buf_discard(buf); + net_route_msg(rbuf); + return data_sz; +} + +int port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr, + struct iovec const *msg_sect, u32 num_sect, + int err) +{ + struct sk_buff *buf; + int res; + + res = msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE, + !p_ptr->user_port, &buf); + if (!buf) + return res; + + return tipc_reject_msg(buf, err); +} + +static void port_timeout(unsigned long ref) +{ + struct port *p_ptr = port_lock(ref); + struct sk_buff *buf = 0; + + if (!p_ptr || !p_ptr->publ.connected) + return; + + /* Last probe answered ? */ + if (p_ptr->probing_state == PROBING) { + buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_PORT); + } else { + buf = port_build_proto_msg(port_peerport(p_ptr), + port_peernode(p_ptr), + p_ptr->publ.ref, + tipc_own_addr, + CONN_MANAGER, + CONN_PROBE, + TIPC_OK, + port_out_seqno(p_ptr), + 0); + port_incr_out_seqno(p_ptr); + p_ptr->probing_state = PROBING; + k_start_timer(&p_ptr->timer, p_ptr->probing_interval); + } + port_unlock(p_ptr); + net_route_msg(buf); +} + + +static void port_handle_node_down(unsigned long ref) +{ + struct port *p_ptr = port_lock(ref); + struct sk_buff* buf = 0; + + if (!p_ptr) + return; + buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_NODE); + port_unlock(p_ptr); + net_route_msg(buf); +} + + +static struct sk_buff *port_build_self_abort_msg(struct port *p_ptr, u32 err) +{ + u32 imp = msg_importance(&p_ptr->publ.phdr); + + if (!p_ptr->publ.connected) + return 0; + if (imp < TIPC_CRITICAL_IMPORTANCE) + imp++; + return port_build_proto_msg(p_ptr->publ.ref, + tipc_own_addr, + port_peerport(p_ptr), + port_peernode(p_ptr), + imp, + TIPC_CONN_MSG, + err, + p_ptr->last_in_seqno + 1, + 0); +} + + +static struct sk_buff *port_build_peer_abort_msg(struct port *p_ptr, u32 err) +{ + u32 imp = msg_importance(&p_ptr->publ.phdr); + + if (!p_ptr->publ.connected) + return 0; + if (imp < TIPC_CRITICAL_IMPORTANCE) + imp++; + return port_build_proto_msg(port_peerport(p_ptr), + port_peernode(p_ptr), + p_ptr->publ.ref, + tipc_own_addr, + imp, + TIPC_CONN_MSG, + err, + port_out_seqno(p_ptr), + 0); +} + +void port_recv_proto_msg(struct sk_buff *buf) +{ + struct tipc_msg *msg = buf_msg(buf); + struct port *p_ptr = port_lock(msg_destport(msg)); + u32 err = TIPC_OK; + struct sk_buff *r_buf = 0; + struct sk_buff *abort_buf = 0; + + msg_dbg(msg, "PORTpubl.connected) { + if (port_peernode(p_ptr) != msg_orignode(msg)) + err = TIPC_ERR_NO_PORT; + if (port_peerport(p_ptr) != msg_origport(msg)) + err = TIPC_ERR_NO_PORT; + if (!err && msg_routed(msg)) { + u32 seqno = msg_transp_seqno(msg); + u32 myno = ++p_ptr->last_in_seqno; + if (seqno != myno) { + err = TIPC_ERR_NO_PORT; + abort_buf = port_build_self_abort_msg(p_ptr, err); + } + } + if (msg_type(msg) == CONN_ACK) { + int wakeup = port_congested(p_ptr) && + p_ptr->publ.congested && + p_ptr->wakeup; + p_ptr->acked += msg_msgcnt(msg); + if (port_congested(p_ptr)) + goto exit; + p_ptr->publ.congested = 0; + if (!wakeup) + goto exit; + p_ptr->wakeup(&p_ptr->publ); + goto exit; + } + } else if (p_ptr->publ.published) { + err = TIPC_ERR_NO_PORT; + } + if (err) { + r_buf = port_build_proto_msg(msg_origport(msg), + msg_orignode(msg), + msg_destport(msg), + tipc_own_addr, + DATA_HIGH, + TIPC_CONN_MSG, + err, + 0, + 0); + goto exit; + } + + /* All is fine */ + if (msg_type(msg) == CONN_PROBE) { + r_buf = port_build_proto_msg(msg_origport(msg), + msg_orignode(msg), + msg_destport(msg), + tipc_own_addr, + CONN_MANAGER, + CONN_PROBE_REPLY, + TIPC_OK, + port_out_seqno(p_ptr), + 0); + } + p_ptr->probing_state = CONFIRMED; + port_incr_out_seqno(p_ptr); +exit: + if (p_ptr) + port_unlock(p_ptr); + net_route_msg(r_buf); + net_route_msg(abort_buf); + buf_discard(buf); +} + +static void port_print(struct port *p_ptr, struct print_buf *buf, int full_id) +{ + struct publication *publ; + + if (full_id) + tipc_printf(buf, "<%u.%u.%u:%u>:", + tipc_zone(tipc_own_addr), tipc_cluster(tipc_own_addr), + tipc_node(tipc_own_addr), p_ptr->publ.ref); + else + tipc_printf(buf, "%-10u:", p_ptr->publ.ref); + + if (p_ptr->publ.connected) { + u32 dport = port_peerport(p_ptr); + u32 destnode = port_peernode(p_ptr); + + tipc_printf(buf, " connected to <%u.%u.%u:%u>", + tipc_zone(destnode), tipc_cluster(destnode), + tipc_node(destnode), dport); + if (p_ptr->publ.conn_type != 0) + tipc_printf(buf, " via {%u,%u}", + p_ptr->publ.conn_type, + p_ptr->publ.conn_instance); + } + else if (p_ptr->publ.published) { + tipc_printf(buf, " bound to"); + list_for_each_entry(publ, &p_ptr->publications, pport_list) { + if (publ->lower == publ->upper) + tipc_printf(buf, " {%u,%u}", publ->type, + publ->lower); + else + tipc_printf(buf, " {%u,%u,%u}", publ->type, + publ->lower, publ->upper); + } + } + tipc_printf(buf, "\n"); +} + +#define MAX_PORT_QUERY 32768 + +struct sk_buff *port_get_ports(void) +{ + struct sk_buff *buf; + struct tlv_desc *rep_tlv; + struct print_buf pb; + struct port *p_ptr; + int str_len; + + buf = cfg_reply_alloc(TLV_SPACE(MAX_PORT_QUERY)); + if (!buf) + return NULL; + rep_tlv = (struct tlv_desc *)buf->data; + + printbuf_init(&pb, TLV_DATA(rep_tlv), MAX_PORT_QUERY); + spin_lock_bh(&port_list_lock); + list_for_each_entry(p_ptr, &ports, port_list) { + spin_lock_bh(p_ptr->publ.lock); + port_print(p_ptr, &pb, 0); + spin_unlock_bh(p_ptr->publ.lock); + } + spin_unlock_bh(&port_list_lock); + str_len = printbuf_validate(&pb); + + skb_put(buf, TLV_SPACE(str_len)); + TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); + + return buf; +} + +#if 0 + +#define MAX_PORT_STATS 2000 + +struct sk_buff *port_show_stats(const void *req_tlv_area, int req_tlv_space) +{ + u32 ref; + struct port *p_ptr; + struct sk_buff *buf; + struct tlv_desc *rep_tlv; + struct print_buf pb; + int str_len; + + if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_PORT_REF)) + return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); + + ref = *(u32 *)TLV_DATA(req_tlv_area); + ref = ntohl(ref); + + p_ptr = port_lock(ref); + if (!p_ptr) + return cfg_reply_error_string("port not found"); + + buf = cfg_reply_alloc(TLV_SPACE(MAX_PORT_STATS)); + if (!buf) { + port_unlock(p_ptr); + return NULL; + } + rep_tlv = (struct tlv_desc *)buf->data; + + printbuf_init(&pb, TLV_DATA(rep_tlv), MAX_PORT_STATS); + port_print(p_ptr, &pb, 1); + /* NEED TO FILL IN ADDITIONAL PORT STATISTICS HERE */ + port_unlock(p_ptr); + str_len = printbuf_validate(&pb); + + skb_put(buf, TLV_SPACE(str_len)); + TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); + + return buf; +} + +#endif + +void port_reinit(void) +{ + struct port *p_ptr; + struct tipc_msg *msg; + + spin_lock_bh(&port_list_lock); + list_for_each_entry(p_ptr, &ports, port_list) { + msg = &p_ptr->publ.phdr; + if (msg_orignode(msg) == tipc_own_addr) + break; + msg_set_orignode(msg, tipc_own_addr); + } + spin_unlock_bh(&port_list_lock); +} + + +/* + * port_dispatcher_sigh(): Signal handler for messages destinated + * to the tipc_port interface. + */ + +static void port_dispatcher_sigh(void *dummy) +{ + struct sk_buff *buf; + + spin_lock_bh(&queue_lock); + buf = msg_queue_head; + msg_queue_head = 0; + spin_unlock_bh(&queue_lock); + + while (buf) { + struct port *p_ptr; + struct user_port *up_ptr; + struct tipc_portid orig; + struct tipc_name_seq dseq; + void *usr_handle; + int connected; + int published; + + struct sk_buff *next = buf->next; + struct tipc_msg *msg = buf_msg(buf); + u32 dref = msg_destport(msg); + + p_ptr = port_lock(dref); + if (!p_ptr) { + /* Port deleted while msg in queue */ + tipc_reject_msg(buf, TIPC_ERR_NO_PORT); + buf = next; + continue; + } + orig.ref = msg_origport(msg); + orig.node = msg_orignode(msg); + up_ptr = p_ptr->user_port; + usr_handle = up_ptr->usr_handle; + connected = p_ptr->publ.connected; + published = p_ptr->publ.published; + + if (unlikely(msg_errcode(msg))) + goto err; + + switch (msg_type(msg)) { + + case TIPC_CONN_MSG:{ + tipc_conn_msg_event cb = up_ptr->conn_msg_cb; + u32 peer_port = port_peerport(p_ptr); + u32 peer_node = port_peernode(p_ptr); + + spin_unlock_bh(p_ptr->publ.lock); + if (unlikely(!connected)) { + if (unlikely(published)) + goto reject; + tipc_connect2port(dref,&orig); + } + if (unlikely(msg_origport(msg) != peer_port)) + goto reject; + if (unlikely(msg_orignode(msg) != peer_node)) + goto reject; + if (unlikely(!cb)) + goto reject; + if (unlikely(++p_ptr->publ.conn_unacked >= + TIPC_FLOW_CONTROL_WIN)) + tipc_acknowledge(dref, + p_ptr->publ.conn_unacked); + skb_pull(buf, msg_hdr_sz(msg)); + cb(usr_handle, dref, &buf, msg_data(msg), + msg_data_sz(msg)); + break; + } + case TIPC_DIRECT_MSG:{ + tipc_msg_event cb = up_ptr->msg_cb; + + spin_unlock_bh(p_ptr->publ.lock); + if (unlikely(connected)) + goto reject; + if (unlikely(!cb)) + goto reject; + skb_pull(buf, msg_hdr_sz(msg)); + cb(usr_handle, dref, &buf, msg_data(msg), + msg_data_sz(msg), msg_importance(msg), + &orig); + break; + } + case TIPC_NAMED_MSG:{ + tipc_named_msg_event cb = up_ptr->named_msg_cb; + + spin_unlock_bh(p_ptr->publ.lock); + if (unlikely(connected)) + goto reject; + if (unlikely(!cb)) + goto reject; + if (unlikely(!published)) + goto reject; + dseq.type = msg_nametype(msg); + dseq.lower = msg_nameinst(msg); + dseq.upper = dseq.lower; + skb_pull(buf, msg_hdr_sz(msg)); + cb(usr_handle, dref, &buf, msg_data(msg), + msg_data_sz(msg), msg_importance(msg), + &orig, &dseq); + break; + } + } + if (buf) + buf_discard(buf); + buf = next; + continue; +err: + switch (msg_type(msg)) { + + case TIPC_CONN_MSG:{ + tipc_conn_shutdown_event cb = + up_ptr->conn_err_cb; + u32 peer_port = port_peerport(p_ptr); + u32 peer_node = port_peernode(p_ptr); + + spin_unlock_bh(p_ptr->publ.lock); + if (!connected || !cb) + break; + if (msg_origport(msg) != peer_port) + break; + if (msg_orignode(msg) != peer_node) + break; + tipc_disconnect(dref); + skb_pull(buf, msg_hdr_sz(msg)); + cb(usr_handle, dref, &buf, msg_data(msg), + msg_data_sz(msg), msg_errcode(msg)); + break; + } + case TIPC_DIRECT_MSG:{ + tipc_msg_err_event cb = up_ptr->err_cb; + + spin_unlock_bh(p_ptr->publ.lock); + if (connected || !cb) + break; + skb_pull(buf, msg_hdr_sz(msg)); + cb(usr_handle, dref, &buf, msg_data(msg), + msg_data_sz(msg), msg_errcode(msg), &orig); + break; + } + case TIPC_NAMED_MSG:{ + tipc_named_msg_err_event cb = + up_ptr->named_err_cb; + + spin_unlock_bh(p_ptr->publ.lock); + if (connected || !cb) + break; + dseq.type = msg_nametype(msg); + dseq.lower = msg_nameinst(msg); + dseq.upper = dseq.lower; + skb_pull(buf, msg_hdr_sz(msg)); + cb(usr_handle, dref, &buf, msg_data(msg), + msg_data_sz(msg), msg_errcode(msg), &dseq); + break; + } + } + if (buf) + buf_discard(buf); + buf = next; + continue; +reject: + tipc_reject_msg(buf, TIPC_ERR_NO_PORT); + buf = next; + } +} + +/* + * port_dispatcher(): Dispatcher for messages destinated + * to the tipc_port interface. Called with port locked. + */ + +static u32 port_dispatcher(struct tipc_port *dummy, struct sk_buff *buf) +{ + buf->next = NULL; + spin_lock_bh(&queue_lock); + if (msg_queue_head) { + msg_queue_tail->next = buf; + msg_queue_tail = buf; + } else { + msg_queue_tail = msg_queue_head = buf; + k_signal((Handler)port_dispatcher_sigh, 0); + } + spin_unlock_bh(&queue_lock); + return TIPC_OK; +} + +/* + * Wake up port after congestion: Called with port locked, + * + */ + +static void port_wakeup_sh(unsigned long ref) +{ + struct port *p_ptr; + struct user_port *up_ptr; + tipc_continue_event cb = 0; + void *uh = 0; + + p_ptr = port_lock(ref); + if (p_ptr) { + up_ptr = p_ptr->user_port; + if (up_ptr) { + cb = up_ptr->continue_event_cb; + uh = up_ptr->usr_handle; + } + port_unlock(p_ptr); + } + if (cb) + cb(uh, ref); +} + + +static void port_wakeup(struct tipc_port *p_ptr) +{ + k_signal((Handler)port_wakeup_sh, p_ptr->ref); +} + +void tipc_acknowledge(u32 ref, u32 ack) +{ + struct port *p_ptr; + struct sk_buff *buf = 0; + + p_ptr = port_lock(ref); + if (!p_ptr) + return; + if (p_ptr->publ.connected) { + p_ptr->publ.conn_unacked -= ack; + buf = port_build_proto_msg(port_peerport(p_ptr), + port_peernode(p_ptr), + ref, + tipc_own_addr, + CONN_MANAGER, + CONN_ACK, + TIPC_OK, + port_out_seqno(p_ptr), + ack); + } + port_unlock(p_ptr); + net_route_msg(buf); +} + +/* + * tipc_createport(): user level call. Will add port to + * registry if non-zero user_ref. + */ + +int tipc_createport(u32 user_ref, + void *usr_handle, + unsigned int importance, + tipc_msg_err_event error_cb, + tipc_named_msg_err_event named_error_cb, + tipc_conn_shutdown_event conn_error_cb, + tipc_msg_event msg_cb, + tipc_named_msg_event named_msg_cb, + tipc_conn_msg_event conn_msg_cb, + tipc_continue_event continue_event_cb,/* May be zero */ + u32 *portref) +{ + struct user_port *up_ptr; + struct port *p_ptr; + u32 ref; + + up_ptr = (struct user_port *)kmalloc(sizeof(*up_ptr), GFP_ATOMIC); + if (up_ptr == NULL) { + return -ENOMEM; + } + ref = tipc_createport_raw(0, port_dispatcher, port_wakeup, importance); + p_ptr = port_lock(ref); + if (!p_ptr) { + kfree(up_ptr); + return -ENOMEM; + } + + p_ptr->user_port = up_ptr; + up_ptr->user_ref = user_ref; + up_ptr->usr_handle = usr_handle; + up_ptr->ref = p_ptr->publ.ref; + up_ptr->err_cb = error_cb; + up_ptr->named_err_cb = named_error_cb; + up_ptr->conn_err_cb = conn_error_cb; + up_ptr->msg_cb = msg_cb; + up_ptr->named_msg_cb = named_msg_cb; + up_ptr->conn_msg_cb = conn_msg_cb; + up_ptr->continue_event_cb = continue_event_cb; + INIT_LIST_HEAD(&up_ptr->uport_list); + reg_add_port(up_ptr); + *portref = p_ptr->publ.ref; + dbg(" tipc_createport: %x with ref %u\n", p_ptr, p_ptr->publ.ref); + port_unlock(p_ptr); + return TIPC_OK; +} + +int tipc_ownidentity(u32 ref, struct tipc_portid *id) +{ + id->ref = ref; + id->node = tipc_own_addr; + return TIPC_OK; +} + +int tipc_portimportance(u32 ref, unsigned int *importance) +{ + struct port *p_ptr; + + p_ptr = port_lock(ref); + if (!p_ptr) + return -EINVAL; + *importance = (unsigned int)msg_importance(&p_ptr->publ.phdr); + spin_unlock_bh(p_ptr->publ.lock); + return TIPC_OK; +} + +int tipc_set_portimportance(u32 ref, unsigned int imp) +{ + struct port *p_ptr; + + if (imp > TIPC_CRITICAL_IMPORTANCE) + return -EINVAL; + + p_ptr = port_lock(ref); + if (!p_ptr) + return -EINVAL; + msg_set_importance(&p_ptr->publ.phdr, (u32)imp); + spin_unlock_bh(p_ptr->publ.lock); + return TIPC_OK; +} + + +int tipc_publish(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) +{ + struct port *p_ptr; + struct publication *publ; + u32 key; + int res = -EINVAL; + + p_ptr = port_lock(ref); + dbg("tipc_publ %u, p_ptr = %x, conn = %x, scope = %x, " + "lower = %u, upper = %u\n", + ref, p_ptr, p_ptr->publ.connected, scope, seq->lower, seq->upper); + if (!p_ptr) + return -EINVAL; + if (p_ptr->publ.connected) + goto exit; + if (seq->lower > seq->upper) + goto exit; + if ((scope < TIPC_ZONE_SCOPE) || (scope > TIPC_NODE_SCOPE)) + goto exit; + key = ref + p_ptr->pub_count + 1; + if (key == ref) { + res = -EADDRINUSE; + goto exit; + } + publ = nametbl_publish(seq->type, seq->lower, seq->upper, + scope, p_ptr->publ.ref, key); + if (publ) { + list_add(&publ->pport_list, &p_ptr->publications); + p_ptr->pub_count++; + p_ptr->publ.published = 1; + res = TIPC_OK; + } +exit: + port_unlock(p_ptr); + return res; +} + +int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) +{ + struct port *p_ptr; + struct publication *publ; + struct publication *tpubl; + int res = -EINVAL; + + p_ptr = port_lock(ref); + if (!p_ptr) + return -EINVAL; + if (!p_ptr->publ.published) + goto exit; + if (!seq) { + list_for_each_entry_safe(publ, tpubl, + &p_ptr->publications, pport_list) { + nametbl_withdraw(publ->type, publ->lower, + publ->ref, publ->key); + } + res = TIPC_OK; + } else { + list_for_each_entry_safe(publ, tpubl, + &p_ptr->publications, pport_list) { + if (publ->scope != scope) + continue; + if (publ->type != seq->type) + continue; + if (publ->lower != seq->lower) + continue; + if (publ->upper != seq->upper) + break; + nametbl_withdraw(publ->type, publ->lower, + publ->ref, publ->key); + res = TIPC_OK; + break; + } + } + if (list_empty(&p_ptr->publications)) + p_ptr->publ.published = 0; +exit: + port_unlock(p_ptr); + return res; +} + +int tipc_connect2port(u32 ref, struct tipc_portid const *peer) +{ + struct port *p_ptr; + struct tipc_msg *msg; + int res = -EINVAL; + + p_ptr = port_lock(ref); + if (!p_ptr) + return -EINVAL; + if (p_ptr->publ.published || p_ptr->publ.connected) + goto exit; + if (!peer->ref) + goto exit; + + msg = &p_ptr->publ.phdr; + msg_set_destnode(msg, peer->node); + msg_set_destport(msg, peer->ref); + msg_set_orignode(msg, tipc_own_addr); + msg_set_origport(msg, p_ptr->publ.ref); + msg_set_transp_seqno(msg, 42); + msg_set_type(msg, TIPC_CONN_MSG); + if (!may_route(peer->node)) + msg_set_hdr_sz(msg, SHORT_H_SIZE); + else + msg_set_hdr_sz(msg, LONG_H_SIZE); + + p_ptr->probing_interval = PROBING_INTERVAL; + p_ptr->probing_state = CONFIRMED; + p_ptr->publ.connected = 1; + k_start_timer(&p_ptr->timer, p_ptr->probing_interval); + + nodesub_subscribe(&p_ptr->subscription,peer->node, (void *)ref, + (net_ev_handler)port_handle_node_down); + res = TIPC_OK; +exit: + port_unlock(p_ptr); + p_ptr->max_pkt = link_get_max_pkt(peer->node, ref); + return res; +} + +/* + * tipc_disconnect(): Disconnect port form peer. + * This is a node local operation. + */ + +int tipc_disconnect(u32 ref) +{ + struct port *p_ptr; + int res = -ENOTCONN; + + p_ptr = port_lock(ref); + if (!p_ptr) + return -EINVAL; + if (p_ptr->publ.connected) { + p_ptr->publ.connected = 0; + /* let timer expire on it's own to avoid deadlock! */ + nodesub_unsubscribe(&p_ptr->subscription); + res = TIPC_OK; + } + port_unlock(p_ptr); + return res; +} + +/* + * tipc_shutdown(): Send a SHUTDOWN msg to peer and disconnect + */ +int tipc_shutdown(u32 ref) +{ + struct port *p_ptr; + struct sk_buff *buf = 0; + + p_ptr = port_lock(ref); + if (!p_ptr) + return -EINVAL; + + if (p_ptr->publ.connected) { + u32 imp = msg_importance(&p_ptr->publ.phdr); + if (imp < TIPC_CRITICAL_IMPORTANCE) + imp++; + buf = port_build_proto_msg(port_peerport(p_ptr), + port_peernode(p_ptr), + ref, + tipc_own_addr, + imp, + TIPC_CONN_MSG, + TIPC_CONN_SHUTDOWN, + port_out_seqno(p_ptr), + 0); + } + port_unlock(p_ptr); + net_route_msg(buf); + return tipc_disconnect(ref); +} + +int tipc_isconnected(u32 ref, int *isconnected) +{ + struct port *p_ptr; + + p_ptr = port_lock(ref); + if (!p_ptr) + return -EINVAL; + *isconnected = p_ptr->publ.connected; + port_unlock(p_ptr); + return TIPC_OK; +} + +int tipc_peer(u32 ref, struct tipc_portid *peer) +{ + struct port *p_ptr; + int res; + + p_ptr = port_lock(ref); + if (!p_ptr) + return -EINVAL; + if (p_ptr->publ.connected) { + peer->ref = port_peerport(p_ptr); + peer->node = port_peernode(p_ptr); + res = TIPC_OK; + } else + res = -ENOTCONN; + port_unlock(p_ptr); + return res; +} + +int tipc_ref_valid(u32 ref) +{ + /* Works irrespective of type */ + return !!ref_deref(ref); +} + + +/* + * port_recv_sections(): Concatenate and deliver sectioned + * message for this node. + */ + +int port_recv_sections(struct port *sender, unsigned int num_sect, + struct iovec const *msg_sect) +{ + struct sk_buff *buf; + int res; + + res = msg_build(&sender->publ.phdr, msg_sect, num_sect, + MAX_MSG_SIZE, !sender->user_port, &buf); + if (likely(buf)) + port_recv_msg(buf); + return res; +} + +/** + * tipc_send - send message sections on connection + */ + +int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect) +{ + struct port *p_ptr; + u32 destnode; + int res; + + p_ptr = port_deref(ref); + if (!p_ptr || !p_ptr->publ.connected) + return -EINVAL; + + p_ptr->publ.congested = 1; + if (!port_congested(p_ptr)) { + destnode = port_peernode(p_ptr); + if (likely(destnode != tipc_own_addr)) + res = link_send_sections_fast(p_ptr, msg_sect, num_sect, + destnode); + else + res = port_recv_sections(p_ptr, num_sect, msg_sect); + + if (likely(res != -ELINKCONG)) { + port_incr_out_seqno(p_ptr); + p_ptr->publ.congested = 0; + p_ptr->sent++; + return res; + } + } + if (port_unreliable(p_ptr)) { + p_ptr->publ.congested = 0; + /* Just calculate msg length and return */ + return msg_calc_data_size(msg_sect, num_sect); + } + return -ELINKCONG; +} + +/** + * tipc_send_buf - send message buffer on connection + */ + +int tipc_send_buf(u32 ref, struct sk_buff *buf, unsigned int dsz) +{ + struct port *p_ptr; + struct tipc_msg *msg; + u32 destnode; + u32 hsz; + u32 sz; + u32 res; + + p_ptr = port_deref(ref); + if (!p_ptr || !p_ptr->publ.connected) + return -EINVAL; + + msg = &p_ptr->publ.phdr; + hsz = msg_hdr_sz(msg); + sz = hsz + dsz; + msg_set_size(msg, sz); + if (skb_cow(buf, hsz)) + return -ENOMEM; + + skb_push(buf, hsz); + memcpy(buf->data, (unchar *)msg, hsz); + destnode = msg_destnode(msg); + p_ptr->publ.congested = 1; + if (!port_congested(p_ptr)) { + if (likely(destnode != tipc_own_addr)) + res = tipc_send_buf_fast(buf, destnode); + else { + port_recv_msg(buf); + res = sz; + } + if (likely(res != -ELINKCONG)) { + port_incr_out_seqno(p_ptr); + p_ptr->sent++; + p_ptr->publ.congested = 0; + return res; + } + } + if (port_unreliable(p_ptr)) { + p_ptr->publ.congested = 0; + return dsz; + } + return -ELINKCONG; +} + +/** + * tipc_forward2name - forward message sections to port name + */ + +int tipc_forward2name(u32 ref, + struct tipc_name const *name, + u32 domain, + u32 num_sect, + struct iovec const *msg_sect, + struct tipc_portid const *orig, + unsigned int importance) +{ + struct port *p_ptr; + struct tipc_msg *msg; + u32 destnode = domain; + u32 destport = 0; + int res; + + p_ptr = port_deref(ref); + if (!p_ptr || p_ptr->publ.connected) + return -EINVAL; + + msg = &p_ptr->publ.phdr; + msg_set_type(msg, TIPC_NAMED_MSG); + msg_set_orignode(msg, orig->node); + msg_set_origport(msg, orig->ref); + msg_set_hdr_sz(msg, LONG_H_SIZE); + msg_set_nametype(msg, name->type); + msg_set_nameinst(msg, name->instance); + msg_set_lookup_scope(msg, addr_scope(domain)); + if (importance <= TIPC_CRITICAL_IMPORTANCE) + msg_set_importance(msg,importance); + destport = nametbl_translate(name->type, name->instance, &destnode); + msg_set_destnode(msg, destnode); + msg_set_destport(msg, destport); + + if (likely(destport || destnode)) { + p_ptr->sent++; + if (likely(destnode == tipc_own_addr)) + return port_recv_sections(p_ptr, num_sect, msg_sect); + res = link_send_sections_fast(p_ptr, msg_sect, num_sect, + destnode); + if (likely(res != -ELINKCONG)) + return res; + if (port_unreliable(p_ptr)) { + /* Just calculate msg length and return */ + return msg_calc_data_size(msg_sect, num_sect); + } + return -ELINKCONG; + } + return port_reject_sections(p_ptr, msg, msg_sect, num_sect, + TIPC_ERR_NO_NAME); +} + +/** + * tipc_send2name - send message sections to port name + */ + +int tipc_send2name(u32 ref, + struct tipc_name const *name, + unsigned int domain, + unsigned int num_sect, + struct iovec const *msg_sect) +{ + struct tipc_portid orig; + + orig.ref = ref; + orig.node = tipc_own_addr; + return tipc_forward2name(ref, name, domain, num_sect, msg_sect, &orig, + TIPC_PORT_IMPORTANCE); +} + +/** + * tipc_forward_buf2name - forward message buffer to port name + */ + +int tipc_forward_buf2name(u32 ref, + struct tipc_name const *name, + u32 domain, + struct sk_buff *buf, + unsigned int dsz, + struct tipc_portid const *orig, + unsigned int importance) +{ + struct port *p_ptr; + struct tipc_msg *msg; + u32 destnode = domain; + u32 destport = 0; + int res; + + p_ptr = (struct port *)ref_deref(ref); + if (!p_ptr || p_ptr->publ.connected) + return -EINVAL; + + msg = &p_ptr->publ.phdr; + if (importance <= TIPC_CRITICAL_IMPORTANCE) + msg_set_importance(msg, importance); + msg_set_type(msg, TIPC_NAMED_MSG); + msg_set_orignode(msg, orig->node); + msg_set_origport(msg, orig->ref); + msg_set_nametype(msg, name->type); + msg_set_nameinst(msg, name->instance); + msg_set_lookup_scope(msg, addr_scope(domain)); + msg_set_hdr_sz(msg, LONG_H_SIZE); + msg_set_size(msg, LONG_H_SIZE + dsz); + destport = nametbl_translate(name->type, name->instance, &destnode); + msg_set_destnode(msg, destnode); + msg_set_destport(msg, destport); + msg_dbg(msg, "forw2name ==> "); + if (skb_cow(buf, LONG_H_SIZE)) + return -ENOMEM; + skb_push(buf, LONG_H_SIZE); + memcpy(buf->data, (unchar *)msg, LONG_H_SIZE); + msg_dbg(buf_msg(buf),"PREP:"); + if (likely(destport || destnode)) { + p_ptr->sent++; + if (destnode == tipc_own_addr) + return port_recv_msg(buf); + res = tipc_send_buf_fast(buf, destnode); + if (likely(res != -ELINKCONG)) + return res; + if (port_unreliable(p_ptr)) + return dsz; + return -ELINKCONG; + } + return tipc_reject_msg(buf, TIPC_ERR_NO_NAME); +} + +/** + * tipc_send_buf2name - send message buffer to port name + */ + +int tipc_send_buf2name(u32 ref, + struct tipc_name const *dest, + u32 domain, + struct sk_buff *buf, + unsigned int dsz) +{ + struct tipc_portid orig; + + orig.ref = ref; + orig.node = tipc_own_addr; + return tipc_forward_buf2name(ref, dest, domain, buf, dsz, &orig, + TIPC_PORT_IMPORTANCE); +} + +/** + * tipc_forward2port - forward message sections to port identity + */ + +int tipc_forward2port(u32 ref, + struct tipc_portid const *dest, + unsigned int num_sect, + struct iovec const *msg_sect, + struct tipc_portid const *orig, + unsigned int importance) +{ + struct port *p_ptr; + struct tipc_msg *msg; + int res; + + p_ptr = port_deref(ref); + if (!p_ptr || p_ptr->publ.connected) + return -EINVAL; + + msg = &p_ptr->publ.phdr; + msg_set_type(msg, TIPC_DIRECT_MSG); + msg_set_orignode(msg, orig->node); + msg_set_origport(msg, orig->ref); + msg_set_destnode(msg, dest->node); + msg_set_destport(msg, dest->ref); + msg_set_hdr_sz(msg, DIR_MSG_H_SIZE); + if (importance <= TIPC_CRITICAL_IMPORTANCE) + msg_set_importance(msg, importance); + p_ptr->sent++; + if (dest->node == tipc_own_addr) + return port_recv_sections(p_ptr, num_sect, msg_sect); + res = link_send_sections_fast(p_ptr, msg_sect, num_sect, dest->node); + if (likely(res != -ELINKCONG)) + return res; + if (port_unreliable(p_ptr)) { + /* Just calculate msg length and return */ + return msg_calc_data_size(msg_sect, num_sect); + } + return -ELINKCONG; +} + +/** + * tipc_send2port - send message sections to port identity + */ + +int tipc_send2port(u32 ref, + struct tipc_portid const *dest, + unsigned int num_sect, + struct iovec const *msg_sect) +{ + struct tipc_portid orig; + + orig.ref = ref; + orig.node = tipc_own_addr; + return tipc_forward2port(ref, dest, num_sect, msg_sect, &orig, + TIPC_PORT_IMPORTANCE); +} + +/** + * tipc_forward_buf2port - forward message buffer to port identity + */ +int tipc_forward_buf2port(u32 ref, + struct tipc_portid const *dest, + struct sk_buff *buf, + unsigned int dsz, + struct tipc_portid const *orig, + unsigned int importance) +{ + struct port *p_ptr; + struct tipc_msg *msg; + int res; + + p_ptr = (struct port *)ref_deref(ref); + if (!p_ptr || p_ptr->publ.connected) + return -EINVAL; + + msg = &p_ptr->publ.phdr; + msg_set_type(msg, TIPC_DIRECT_MSG); + msg_set_orignode(msg, orig->node); + msg_set_origport(msg, orig->ref); + msg_set_destnode(msg, dest->node); + msg_set_destport(msg, dest->ref); + msg_set_hdr_sz(msg, DIR_MSG_H_SIZE); + if (importance <= TIPC_CRITICAL_IMPORTANCE) + msg_set_importance(msg, importance); + msg_set_size(msg, DIR_MSG_H_SIZE + dsz); + if (skb_cow(buf, DIR_MSG_H_SIZE)) + return -ENOMEM; + + skb_push(buf, DIR_MSG_H_SIZE); + memcpy(buf->data, (unchar *)msg, DIR_MSG_H_SIZE); + msg_dbg(msg, "buf2port: "); + p_ptr->sent++; + if (dest->node == tipc_own_addr) + return port_recv_msg(buf); + res = tipc_send_buf_fast(buf, dest->node); + if (likely(res != -ELINKCONG)) + return res; + if (port_unreliable(p_ptr)) + return dsz; + return -ELINKCONG; +} + +/** + * tipc_send_buf2port - send message buffer to port identity + */ + +int tipc_send_buf2port(u32 ref, + struct tipc_portid const *dest, + struct sk_buff *buf, + unsigned int dsz) +{ + struct tipc_portid orig; + + orig.ref = ref; + orig.node = tipc_own_addr; + return tipc_forward_buf2port(ref, dest, buf, dsz, &orig, + TIPC_PORT_IMPORTANCE); +} + diff --git a/net/tipc/port.h b/net/tipc/port.h new file mode 100644 index 00000000000..e40235ef92f --- /dev/null +++ b/net/tipc/port.h @@ -0,0 +1,206 @@ +/* + * net/tipc/port.h: Include file for TIPC port code + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2004-2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _TIPC_PORT_H +#define _TIPC_PORT_H + +#include +#include "ref.h" +#include "net.h" +#include "msg.h" +#include "dbg.h" +#include "node_subscr.h" + +/** + * struct user_port - TIPC user port (used with native API) + * @user_ref: id of user who created user port + * @usr_handle: user-specified field + * @ref: object reference to associated TIPC port + * + * @uport_list: adjacent user ports in list of ports held by user + */ + +struct user_port { + u32 user_ref; + void *usr_handle; + u32 ref; + tipc_msg_err_event err_cb; + tipc_named_msg_err_event named_err_cb; + tipc_conn_shutdown_event conn_err_cb; + tipc_msg_event msg_cb; + tipc_named_msg_event named_msg_cb; + tipc_conn_msg_event conn_msg_cb; + tipc_continue_event continue_event_cb; + struct list_head uport_list; +}; + +/** + * struct port - TIPC port structure + * @publ: TIPC port info available to privileged users + * @port_list: adjacent ports in TIPC's global list of ports + * @dispatcher: ptr to routine which handles received messages + * @wakeup: ptr to routine to call when port is no longer congested + * @user_port: ptr to user port associated with port (if any) + * @wait_list: adjacent ports in list of ports waiting on link congestion + * @congested_link: ptr to congested link port is waiting on + * @waiting_pkts: + * @sent: + * @acked: + * @publications: list of publications for port + * @pub_count: total # of publications port has made during its lifetime + * @max_pkt: maximum packet size "hint" used when building messages sent by port + * @probing_state: + * @probing_interval: + * @last_in_seqno: + * @timer_ref: + * @subscription: "node down" subscription used to terminate failed connections + */ + +struct port { + struct tipc_port publ; + struct list_head port_list; + u32 (*dispatcher)(struct tipc_port *, struct sk_buff *); + void (*wakeup)(struct tipc_port *); + struct user_port *user_port; + struct list_head wait_list; + struct link *congested_link; + u32 waiting_pkts; + u32 sent; + u32 acked; + struct list_head publications; + u32 pub_count; + u32 max_pkt; + u32 probing_state; + u32 probing_interval; + u32 last_in_seqno; + struct timer_list timer; + struct node_subscr subscription; +}; + +extern spinlock_t port_list_lock; +struct port_list; + +int port_recv_sections(struct port *p_ptr, u32 num_sect, + struct iovec const *msg_sect); +int port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr, + struct iovec const *msg_sect, u32 num_sect, + int err); +struct sk_buff *port_get_ports(void); +struct sk_buff *port_show_stats(const void *req_tlv_area, int req_tlv_space); +void port_recv_proto_msg(struct sk_buff *buf); +void port_recv_mcast(struct sk_buff *buf, struct port_list *dp); +void port_reinit(void); + +/** + * port_lock - lock port instance referred to and return its pointer + */ + +static inline struct port *port_lock(u32 ref) +{ + return (struct port *)ref_lock(ref); +} + +/** + * port_unlock - unlock a port instance + * + * Can use pointer instead of ref_unlock() since port is already locked. + */ + +static inline void port_unlock(struct port *p_ptr) +{ + spin_unlock_bh(p_ptr->publ.lock); +} + +static inline struct port* port_deref(u32 ref) +{ + return (struct port *)ref_deref(ref); +} + +static inline u32 peer_port(struct port *p_ptr) +{ + return msg_destport(&p_ptr->publ.phdr); +} + +static inline u32 peer_node(struct port *p_ptr) +{ + return msg_destnode(&p_ptr->publ.phdr); +} + +static inline int port_congested(struct port *p_ptr) +{ + return((p_ptr->sent - p_ptr->acked) >= (TIPC_FLOW_CONTROL_WIN * 2)); +} + +/** + * port_recv_msg - receive message from lower layer and deliver to port user + */ + +static inline int port_recv_msg(struct sk_buff *buf) +{ + struct port *p_ptr; + struct tipc_msg *msg = buf_msg(buf); + u32 destport = msg_destport(msg); + u32 dsz = msg_data_sz(msg); + u32 err; + + /* forward unresolved named message */ + if (unlikely(!destport)) { + net_route_msg(buf); + return dsz; + } + + /* validate destination & pass to port, otherwise reject message */ + p_ptr = port_lock(destport); + if (likely(p_ptr)) { + if (likely(p_ptr->publ.connected)) { + if ((unlikely(msg_origport(msg) != peer_port(p_ptr))) || + (unlikely(msg_orignode(msg) != peer_node(p_ptr))) || + (unlikely(!msg_connected(msg)))) { + err = TIPC_ERR_NO_PORT; + port_unlock(p_ptr); + goto reject; + } + } + err = p_ptr->dispatcher(&p_ptr->publ, buf); + port_unlock(p_ptr); + if (likely(!err)) + return dsz; + } else { + err = TIPC_ERR_NO_PORT; + } +reject: + dbg("port->rejecting, err = %x..\n",err); + return tipc_reject_msg(buf, err); +} + +#endif diff --git a/net/tipc/ref.c b/net/tipc/ref.c new file mode 100644 index 00000000000..aee48c797b1 --- /dev/null +++ b/net/tipc/ref.c @@ -0,0 +1,186 @@ +/* + * net/tipc/ref.c: TIPC object registry code + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2004-2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "core.h" +#include "ref.h" +#include "port.h" +#include "subscr.h" +#include "name_distr.h" +#include "name_table.h" +#include "config.h" +#include "discover.h" +#include "bearer.h" +#include "node.h" +#include "bcast.h" + +/* + * Object reference table consists of 2**N entries. + * + * A used entry has object ptr != 0, reference == XXXX|own index + * (XXXX changes each time entry is acquired) + * A free entry has object ptr == 0, reference == YYYY|next free index + * (YYYY is one more than last used XXXX) + * + * Free list is initially chained from entry (2**N)-1 to entry 1. + * Entry 0 is not used to allow index 0 to indicate the end of the free list. + * + * Note: Any accidental reference of the form XXXX|0--0 won't match entry 0 + * because entry 0's reference field has the form XXXX|1--1. + */ + +struct ref_table ref_table = { 0 }; + +rwlock_t reftbl_lock = RW_LOCK_UNLOCKED; + +/** + * ref_table_init - create reference table for objects + */ + +int ref_table_init(u32 requested_size, u32 start) +{ + struct reference *table; + u32 sz = 1 << 4; + u32 index_mask; + int i; + + while (sz < requested_size) { + sz <<= 1; + } + table = (struct reference *)vmalloc(sz * sizeof(struct reference)); + if (table == NULL) + return -ENOMEM; + + write_lock_bh(&reftbl_lock); + index_mask = sz - 1; + for (i = sz - 1; i >= 0; i--) { + table[i].object = 0; + table[i].lock = SPIN_LOCK_UNLOCKED; + table[i].data.next_plus_upper = (start & ~index_mask) + i - 1; + } + ref_table.entries = table; + ref_table.index_mask = index_mask; + ref_table.first_free = sz - 1; + ref_table.last_free = 1; + write_unlock_bh(&reftbl_lock); + return TIPC_OK; +} + +/** + * ref_table_stop - destroy reference table for objects + */ + +void ref_table_stop(void) +{ + if (!ref_table.entries) + return; + + vfree(ref_table.entries); + ref_table.entries = 0; +} + +/** + * ref_acquire - create reference to an object + * + * Return a unique reference value which can be translated back to the pointer + * 'object' at a later time. Also, pass back a pointer to the lock protecting + * the object, but without locking it. + */ + +u32 ref_acquire(void *object, spinlock_t **lock) +{ + struct reference *entry; + u32 index; + u32 index_mask; + u32 next_plus_upper; + u32 reference = 0; + + assert(ref_table.entries && object); + + write_lock_bh(&reftbl_lock); + if (ref_table.first_free) { + index = ref_table.first_free; + entry = &(ref_table.entries[index]); + index_mask = ref_table.index_mask; + /* take lock in case a previous user of entry still holds it */ + spin_lock_bh(&entry->lock); + next_plus_upper = entry->data.next_plus_upper; + ref_table.first_free = next_plus_upper & index_mask; + reference = (next_plus_upper & ~index_mask) + index; + entry->data.reference = reference; + entry->object = object; + if (lock != 0) + *lock = &entry->lock; + spin_unlock_bh(&entry->lock); + } + write_unlock_bh(&reftbl_lock); + return reference; +} + +/** + * ref_discard - invalidate references to an object + * + * Disallow future references to an object and free up the entry for re-use. + * Note: The entry's spin_lock may still be busy after discard + */ + +void ref_discard(u32 ref) +{ + struct reference *entry; + u32 index; + u32 index_mask; + + assert(ref_table.entries); + assert(ref != 0); + + write_lock_bh(&reftbl_lock); + index_mask = ref_table.index_mask; + index = ref & index_mask; + entry = &(ref_table.entries[index]); + assert(entry->object != 0); + assert(entry->data.reference == ref); + + /* mark entry as unused */ + entry->object = 0; + if (ref_table.first_free == 0) + ref_table.first_free = index; + else + /* next_plus_upper is always XXXX|0--0 for last free entry */ + ref_table.entries[ref_table.last_free].data.next_plus_upper + |= index; + ref_table.last_free = index; + + /* increment upper bits of entry to invalidate subsequent references */ + entry->data.next_plus_upper = (ref & ~index_mask) + (index_mask + 1); + write_unlock_bh(&reftbl_lock); +} + diff --git a/net/tipc/ref.h b/net/tipc/ref.h new file mode 100644 index 00000000000..e6cd5bb3dc2 --- /dev/null +++ b/net/tipc/ref.h @@ -0,0 +1,128 @@ +/* + * net/tipc/ref.h: Include file for TIPC object registry code + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _TIPC_REF_H +#define _TIPC_REF_H + +/** + * struct reference - TIPC object reference entry + * @object: pointer to object associated with reference entry + * @lock: spinlock controlling access to object + * @data: reference value associated with object (or link to next unused entry) + */ + +struct reference { + void *object; + spinlock_t lock; + union { + u32 next_plus_upper; + u32 reference; + } data; +}; + +/** + * struct ref_table - table of TIPC object reference entries + * @entries: pointer to array of reference entries + * @index_mask: bitmask for array index portion of reference values + * @first_free: array index of first unused object reference entry + * @last_free: array index of last unused object reference entry + */ + +struct ref_table { + struct reference *entries; + u32 index_mask; + u32 first_free; + u32 last_free; +}; + +extern struct ref_table ref_table; + +int ref_table_init(u32 requested_size, u32 start); +void ref_table_stop(void); + +u32 ref_acquire(void *object, spinlock_t **lock); +void ref_discard(u32 ref); + + +/** + * ref_lock - lock referenced object and return pointer to it + */ + +static inline void *ref_lock(u32 ref) +{ + if (likely(ref_table.entries)) { + struct reference *r = + &ref_table.entries[ref & ref_table.index_mask]; + + spin_lock_bh(&r->lock); + if (likely(r->data.reference == ref)) + return r->object; + spin_unlock_bh(&r->lock); + } + return 0; +} + +/** + * ref_unlock - unlock referenced object + */ + +static inline void ref_unlock(u32 ref) +{ + if (likely(ref_table.entries)) { + struct reference *r = + &ref_table.entries[ref & ref_table.index_mask]; + + if (likely(r->data.reference == ref)) + spin_unlock_bh(&r->lock); + else + err("ref_unlock() invoked using obsolete reference\n"); + } +} + +/** + * ref_deref - return pointer referenced object (without locking it) + */ + +static inline void *ref_deref(u32 ref) +{ + if (likely(ref_table.entries)) { + struct reference *r = + &ref_table.entries[ref & ref_table.index_mask]; + + if (likely(r->data.reference == ref)) + return r->object; + } + return 0; +} + +#endif diff --git a/net/tipc/socket.c b/net/tipc/socket.c new file mode 100644 index 00000000000..22dcb724e76 --- /dev/null +++ b/net/tipc/socket.c @@ -0,0 +1,1722 @@ +/* + * net/tipc/socket.c: TIPC socket API + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2004-2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "core.h" + +#define SS_LISTENING -1 /* socket is listening */ +#define SS_READY -2 /* socket is connectionless */ + +#define OVERLOAD_LIMIT_BASE 5000 + +struct tipc_sock { + struct sock sk; + struct tipc_port *p; + struct semaphore sem; +}; + +#define tipc_sk(sk) ((struct tipc_sock*)sk) + +static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf); +static void wakeupdispatch(struct tipc_port *tport); + +static struct proto_ops packet_ops; +static struct proto_ops stream_ops; +static struct proto_ops msg_ops; + +static struct proto tipc_proto; + +static int sockets_enabled = 0; + +static atomic_t tipc_queue_size = ATOMIC_INIT(0); + + +/* + * sock_lock(): Lock a port/socket pair. lock_sock() can + * not be used here, since the same lock must protect ports + * with non-socket interfaces. + * See net.c for description of locking policy. + */ +static inline void sock_lock(struct tipc_sock* tsock) +{ + spin_lock_bh(tsock->p->lock); +} + +/* + * sock_unlock(): Unlock a port/socket pair + */ +static inline void sock_unlock(struct tipc_sock* tsock) +{ + spin_unlock_bh(tsock->p->lock); +} + +/** + * pollmask - determine the current set of poll() events for a socket + * @sock: socket structure + * + * TIPC sets the returned events as follows: + * a) POLLRDNORM and POLLIN are set if the socket's receive queue is non-empty + * or if a connection-oriented socket is does not have an active connection + * (i.e. a read operation will not block). + * b) POLLOUT is set except when a socket's connection has been terminated + * (i.e. a write operation will not block). + * c) POLLHUP is set when a socket's connection has been terminated. + * + * IMPORTANT: The fact that a read or write operation will not block does NOT + * imply that the operation will succeed! + * + * Returns pollmask value + */ + +static inline u32 pollmask(struct socket *sock) +{ + u32 mask; + + if ((skb_queue_len(&sock->sk->sk_receive_queue) != 0) || + (sock->state == SS_UNCONNECTED) || + (sock->state == SS_DISCONNECTING)) + mask = (POLLRDNORM | POLLIN); + else + mask = 0; + + if (sock->state == SS_DISCONNECTING) + mask |= POLLHUP; + else + mask |= POLLOUT; + + return mask; +} + + +/** + * advance_queue - discard first buffer in queue + * @tsock: TIPC socket + */ + +static inline void advance_queue(struct tipc_sock *tsock) +{ + sock_lock(tsock); + buf_discard(skb_dequeue(&tsock->sk.sk_receive_queue)); + sock_unlock(tsock); + atomic_dec(&tipc_queue_size); +} + +/** + * tipc_create - create a TIPC socket + * @sock: pre-allocated socket structure + * @protocol: protocol indicator (must be 0) + * + * This routine creates and attaches a 'struct sock' to the 'struct socket', + * then create and attaches a TIPC port to the 'struct sock' part. + * + * Returns 0 on success, errno otherwise + */ +static int tipc_create(struct socket *sock, int protocol) +{ + struct tipc_sock *tsock; + struct tipc_port *port; + struct sock *sk; + u32 ref; + + if ((sock->type != SOCK_STREAM) && + (sock->type != SOCK_SEQPACKET) && + (sock->type != SOCK_DGRAM) && + (sock->type != SOCK_RDM)) + return -EPROTOTYPE; + + if (unlikely(protocol != 0)) + return -EPROTONOSUPPORT; + + ref = tipc_createport_raw(0, &dispatch, &wakeupdispatch, TIPC_LOW_IMPORTANCE); + if (unlikely(!ref)) + return -ENOMEM; + + sock->state = SS_UNCONNECTED; + + switch (sock->type) { + case SOCK_STREAM: + sock->ops = &stream_ops; + break; + case SOCK_SEQPACKET: + sock->ops = &packet_ops; + break; + case SOCK_DGRAM: + tipc_set_portunreliable(ref, 1); + /* fall through */ + case SOCK_RDM: + tipc_set_portunreturnable(ref, 1); + sock->ops = &msg_ops; + sock->state = SS_READY; + break; + } + + sk = sk_alloc(AF_TIPC, GFP_KERNEL, &tipc_proto, 1); + if (!sk) { + tipc_deleteport(ref); + return -ENOMEM; + } + + sock_init_data(sock, sk); + init_waitqueue_head(sk->sk_sleep); + sk->sk_rcvtimeo = 8 * HZ; /* default connect timeout = 8s */ + + tsock = tipc_sk(sk); + port = tipc_get_port(ref); + + tsock->p = port; + port->usr_handle = tsock; + + init_MUTEX(&tsock->sem); + + dbg("sock_create: %x\n",tsock); + + atomic_inc(&tipc_user_count); + + return 0; +} + +/** + * release - destroy a TIPC socket + * @sock: socket to destroy + * + * This routine cleans up any messages that are still queued on the socket. + * For DGRAM and RDM socket types, all queued messages are rejected. + * For SEQPACKET and STREAM socket types, the first message is rejected + * and any others are discarded. (If the first message on a STREAM socket + * is partially-read, it is discarded and the next one is rejected instead.) + * + * NOTE: Rejected messages are not necessarily returned to the sender! They + * are returned or discarded according to the "destination droppable" setting + * specified for the message by the sender. + * + * Returns 0 on success, errno otherwise + */ + +static int release(struct socket *sock) +{ + struct tipc_sock *tsock = tipc_sk(sock->sk); + struct sock *sk = sock->sk; + int res = TIPC_OK; + struct sk_buff *buf; + + dbg("sock_delete: %x\n",tsock); + if (!tsock) + return 0; + down_interruptible(&tsock->sem); + if (!sock->sk) { + up(&tsock->sem); + return 0; + } + + /* Reject unreceived messages, unless no longer connected */ + + while (sock->state != SS_DISCONNECTING) { + sock_lock(tsock); + buf = skb_dequeue(&sk->sk_receive_queue); + if (!buf) + tsock->p->usr_handle = 0; + sock_unlock(tsock); + if (!buf) + break; + if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf))) + buf_discard(buf); + else + tipc_reject_msg(buf, TIPC_ERR_NO_PORT); + atomic_dec(&tipc_queue_size); + } + + /* Delete TIPC port */ + + res = tipc_deleteport(tsock->p->ref); + sock->sk = NULL; + + /* Discard any remaining messages */ + + while ((buf = skb_dequeue(&sk->sk_receive_queue))) { + buf_discard(buf); + atomic_dec(&tipc_queue_size); + } + + up(&tsock->sem); + + sock_put(sk); + + atomic_dec(&tipc_user_count); + return res; +} + +/** + * bind - associate or disassocate TIPC name(s) with a socket + * @sock: socket structure + * @uaddr: socket address describing name(s) and desired operation + * @uaddr_len: size of socket address data structure + * + * Name and name sequence binding is indicated using a positive scope value; + * a negative scope value unbinds the specified name. Specifying no name + * (i.e. a socket address length of 0) unbinds all names from the socket. + * + * Returns 0 on success, errno otherwise + */ + +static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len) +{ + struct tipc_sock *tsock = tipc_sk(sock->sk); + struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr; + int res; + + if (down_interruptible(&tsock->sem)) + return -ERESTARTSYS; + + if (unlikely(!uaddr_len)) { + res = tipc_withdraw(tsock->p->ref, 0, 0); + goto exit; + } + + if (uaddr_len < sizeof(struct sockaddr_tipc)) { + res = -EINVAL; + goto exit; + } + + if (addr->family != AF_TIPC) { + res = -EAFNOSUPPORT; + goto exit; + } + if (addr->addrtype == TIPC_ADDR_NAME) + addr->addr.nameseq.upper = addr->addr.nameseq.lower; + else if (addr->addrtype != TIPC_ADDR_NAMESEQ) { + res = -EAFNOSUPPORT; + goto exit; + } + + if (addr->scope > 0) + res = tipc_publish(tsock->p->ref, addr->scope, + &addr->addr.nameseq); + else + res = tipc_withdraw(tsock->p->ref, -addr->scope, + &addr->addr.nameseq); +exit: + up(&tsock->sem); + return res; +} + +/** + * get_name - get port ID of socket or peer socket + * @sock: socket structure + * @uaddr: area for returned socket address + * @uaddr_len: area for returned length of socket address + * @peer: 0 to obtain socket name, 1 to obtain peer socket name + * + * Returns 0 on success, errno otherwise + */ + +static int get_name(struct socket *sock, struct sockaddr *uaddr, + int *uaddr_len, int peer) +{ + struct tipc_sock *tsock = tipc_sk(sock->sk); + struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr; + u32 res; + + if (down_interruptible(&tsock->sem)) + return -ERESTARTSYS; + + *uaddr_len = sizeof(*addr); + addr->addrtype = TIPC_ADDR_ID; + addr->family = AF_TIPC; + addr->scope = 0; + if (peer) + res = tipc_peer(tsock->p->ref, &addr->addr.id); + else + res = tipc_ownidentity(tsock->p->ref, &addr->addr.id); + addr->addr.name.domain = 0; + + up(&tsock->sem); + return res; +} + +/** + * poll - read and possibly block on pollmask + * @file: file structure associated with the socket + * @sock: socket for which to calculate the poll bits + * @wait: ??? + * + * Returns the pollmask + */ + +static unsigned int poll(struct file *file, struct socket *sock, + poll_table *wait) +{ + poll_wait(file, sock->sk->sk_sleep, wait); + /* NEED LOCK HERE? */ + return pollmask(sock); +} + +/** + * dest_name_check - verify user is permitted to send to specified port name + * @dest: destination address + * @m: descriptor for message to be sent + * + * Prevents restricted configuration commands from being issued by + * unauthorized users. + * + * Returns 0 if permission is granted, otherwise errno + */ + +static inline int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m) +{ + struct tipc_cfg_msg_hdr hdr; + + if (likely(dest->addr.name.name.type >= TIPC_RESERVED_TYPES)) + return 0; + if (likely(dest->addr.name.name.type == TIPC_TOP_SRV)) + return 0; + + if (likely(dest->addr.name.name.type != TIPC_CFG_SRV)) + return -EACCES; + + if (copy_from_user(&hdr, m->msg_iov[0].iov_base, sizeof(hdr))) + return -EFAULT; + if ((ntohs(hdr.tcm_type) & 0xC000) & (!capable(CAP_NET_ADMIN))) + return -EACCES; + + return 0; +} + +/** + * send_msg - send message in connectionless manner + * @iocb: (unused) + * @sock: socket structure + * @m: message to send + * @total_len: (unused) + * + * Message must have an destination specified explicitly. + * Used for SOCK_RDM and SOCK_DGRAM messages, + * and for 'SYN' messages on SOCK_SEQPACKET and SOCK_STREAM connections. + * (Note: 'SYN+' is prohibited on SOCK_STREAM.) + * + * Returns the number of bytes sent on success, or errno otherwise + */ + +static int send_msg(struct kiocb *iocb, struct socket *sock, + struct msghdr *m, size_t total_len) +{ + struct tipc_sock *tsock = tipc_sk(sock->sk); + struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name; + struct sk_buff *buf; + int needs_conn; + int res = -EINVAL; + + if (unlikely(!dest)) + return -EDESTADDRREQ; + if (unlikely(dest->family != AF_TIPC)) + return -EINVAL; + + needs_conn = (sock->state != SS_READY); + if (unlikely(needs_conn)) { + if (sock->state == SS_LISTENING) + return -EPIPE; + if (sock->state != SS_UNCONNECTED) + return -EISCONN; + if ((tsock->p->published) || + ((sock->type == SOCK_STREAM) && (total_len != 0))) + return -EOPNOTSUPP; + } + + if (down_interruptible(&tsock->sem)) + return -ERESTARTSYS; + + if (needs_conn) { + + /* Abort any pending connection attempts (very unlikely) */ + + while ((buf = skb_dequeue(&sock->sk->sk_receive_queue))) { + tipc_reject_msg(buf, TIPC_ERR_NO_PORT); + atomic_dec(&tipc_queue_size); + } + + sock->state = SS_CONNECTING; + } + + do { + if (dest->addrtype == TIPC_ADDR_NAME) { + if ((res = dest_name_check(dest, m))) + goto exit; + res = tipc_send2name(tsock->p->ref, + &dest->addr.name.name, + dest->addr.name.domain, + m->msg_iovlen, + m->msg_iov); + } + else if (dest->addrtype == TIPC_ADDR_ID) { + res = tipc_send2port(tsock->p->ref, + &dest->addr.id, + m->msg_iovlen, + m->msg_iov); + } + else if (dest->addrtype == TIPC_ADDR_MCAST) { + if (needs_conn) { + res = -EOPNOTSUPP; + goto exit; + } + if ((res = dest_name_check(dest, m))) + goto exit; + res = tipc_multicast(tsock->p->ref, + &dest->addr.nameseq, + 0, + m->msg_iovlen, + m->msg_iov); + } + if (likely(res != -ELINKCONG)) { +exit: + up(&tsock->sem); + return res; + } + if (m->msg_flags & MSG_DONTWAIT) { + res = -EWOULDBLOCK; + goto exit; + } + if (wait_event_interruptible(*sock->sk->sk_sleep, + !tsock->p->congested)) { + res = -ERESTARTSYS; + goto exit; + } + } while (1); +} + +/** + * send_packet - send a connection-oriented message + * @iocb: (unused) + * @sock: socket structure + * @m: message to send + * @total_len: (unused) + * + * Used for SOCK_SEQPACKET messages and SOCK_STREAM data. + * + * Returns the number of bytes sent on success, or errno otherwise + */ + +static int send_packet(struct kiocb *iocb, struct socket *sock, + struct msghdr *m, size_t total_len) +{ + struct tipc_sock *tsock = tipc_sk(sock->sk); + struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name; + int res; + + /* Handle implied connection establishment */ + + if (unlikely(dest)) + return send_msg(iocb, sock, m, total_len); + + if (down_interruptible(&tsock->sem)) { + return -ERESTARTSYS; + } + + if (unlikely(sock->state != SS_CONNECTED)) { + if (sock->state == SS_DISCONNECTING) + res = -EPIPE; + else + res = -ENOTCONN; + goto exit; + } + + do { + res = tipc_send(tsock->p->ref, m->msg_iovlen, m->msg_iov); + if (likely(res != -ELINKCONG)) { +exit: + up(&tsock->sem); + return res; + } + if (m->msg_flags & MSG_DONTWAIT) { + res = -EWOULDBLOCK; + goto exit; + } + if (wait_event_interruptible(*sock->sk->sk_sleep, + !tsock->p->congested)) { + res = -ERESTARTSYS; + goto exit; + } + } while (1); +} + +/** + * send_stream - send stream-oriented data + * @iocb: (unused) + * @sock: socket structure + * @m: data to send + * @total_len: total length of data to be sent + * + * Used for SOCK_STREAM data. + * + * Returns the number of bytes sent on success, or errno otherwise + */ + + +static int send_stream(struct kiocb *iocb, struct socket *sock, + struct msghdr *m, size_t total_len) +{ + struct msghdr my_msg; + struct iovec my_iov; + struct iovec *curr_iov; + int curr_iovlen; + char __user *curr_start; + int curr_left; + int bytes_to_send; + int res; + + if (likely(total_len <= TIPC_MAX_USER_MSG_SIZE)) + return send_packet(iocb, sock, m, total_len); + + /* Can only send large data streams if already connected */ + + if (unlikely(sock->state != SS_CONNECTED)) { + if (sock->state == SS_DISCONNECTING) + return -EPIPE; + else + return -ENOTCONN; + } + + /* + * Send each iovec entry using one or more messages + * + * Note: This algorithm is good for the most likely case + * (i.e. one large iovec entry), but could be improved to pass sets + * of small iovec entries into send_packet(). + */ + + my_msg = *m; + curr_iov = my_msg.msg_iov; + curr_iovlen = my_msg.msg_iovlen; + my_msg.msg_iov = &my_iov; + my_msg.msg_iovlen = 1; + + while (curr_iovlen--) { + curr_start = curr_iov->iov_base; + curr_left = curr_iov->iov_len; + + while (curr_left) { + bytes_to_send = (curr_left < TIPC_MAX_USER_MSG_SIZE) + ? curr_left : TIPC_MAX_USER_MSG_SIZE; + my_iov.iov_base = curr_start; + my_iov.iov_len = bytes_to_send; + if ((res = send_packet(iocb, sock, &my_msg, 0)) < 0) + return res; + curr_left -= bytes_to_send; + curr_start += bytes_to_send; + } + + curr_iov++; + } + + return total_len; +} + +/** + * auto_connect - complete connection setup to a remote port + * @sock: socket structure + * @tsock: TIPC-specific socket structure + * @msg: peer's response message + * + * Returns 0 on success, errno otherwise + */ + +static int auto_connect(struct socket *sock, struct tipc_sock *tsock, + struct tipc_msg *msg) +{ + struct tipc_portid peer; + + if (msg_errcode(msg)) { + sock->state = SS_DISCONNECTING; + return -ECONNREFUSED; + } + + peer.ref = msg_origport(msg); + peer.node = msg_orignode(msg); + tipc_connect2port(tsock->p->ref, &peer); + tipc_set_portimportance(tsock->p->ref, msg_importance(msg)); + sock->state = SS_CONNECTED; + return 0; +} + +/** + * set_orig_addr - capture sender's address for received message + * @m: descriptor for message info + * @msg: received message header + * + * Note: Address is not captured if not requested by receiver. + */ + +static inline void set_orig_addr(struct msghdr *m, struct tipc_msg *msg) +{ + struct sockaddr_tipc *addr = (struct sockaddr_tipc *)m->msg_name; + + if (addr) { + addr->family = AF_TIPC; + addr->addrtype = TIPC_ADDR_ID; + addr->addr.id.ref = msg_origport(msg); + addr->addr.id.node = msg_orignode(msg); + addr->addr.name.domain = 0; /* could leave uninitialized */ + addr->scope = 0; /* could leave uninitialized */ + m->msg_namelen = sizeof(struct sockaddr_tipc); + } +} + +/** + * anc_data_recv - optionally capture ancillary data for received message + * @m: descriptor for message info + * @msg: received message header + * @tport: TIPC port associated with message + * + * Note: Ancillary data is not captured if not requested by receiver. + * + * Returns 0 if successful, otherwise errno + */ + +static inline int anc_data_recv(struct msghdr *m, struct tipc_msg *msg, + struct tipc_port *tport) +{ + u32 anc_data[3]; + u32 err; + u32 dest_type; + int res; + + if (likely(m->msg_controllen == 0)) + return 0; + + /* Optionally capture errored message object(s) */ + + err = msg ? msg_errcode(msg) : 0; + if (unlikely(err)) { + anc_data[0] = err; + anc_data[1] = msg_data_sz(msg); + if ((res = put_cmsg(m, SOL_SOCKET, TIPC_ERRINFO, 8, anc_data))) + return res; + if (anc_data[1] && + (res = put_cmsg(m, SOL_SOCKET, TIPC_RETDATA, anc_data[1], + msg_data(msg)))) + return res; + } + + /* Optionally capture message destination object */ + + dest_type = msg ? msg_type(msg) : TIPC_DIRECT_MSG; + switch (dest_type) { + case TIPC_NAMED_MSG: + anc_data[0] = msg_nametype(msg); + anc_data[1] = msg_namelower(msg); + anc_data[2] = msg_namelower(msg); + break; + case TIPC_MCAST_MSG: + anc_data[0] = msg_nametype(msg); + anc_data[1] = msg_namelower(msg); + anc_data[2] = msg_nameupper(msg); + break; + case TIPC_CONN_MSG: + anc_data[0] = tport->conn_type; + anc_data[1] = tport->conn_instance; + anc_data[2] = tport->conn_instance; + break; + default: + anc_data[0] = 0; + } + if (anc_data[0] && + (res = put_cmsg(m, SOL_SOCKET, TIPC_DESTNAME, 12, anc_data))) + return res; + + return 0; +} + +/** + * recv_msg - receive packet-oriented message + * @iocb: (unused) + * @m: descriptor for message info + * @buf_len: total size of user buffer area + * @flags: receive flags + * + * Used for SOCK_DGRAM, SOCK_RDM, and SOCK_SEQPACKET messages. + * If the complete message doesn't fit in user area, truncate it. + * + * Returns size of returned message data, errno otherwise + */ + +static int recv_msg(struct kiocb *iocb, struct socket *sock, + struct msghdr *m, size_t buf_len, int flags) +{ + struct tipc_sock *tsock = tipc_sk(sock->sk); + struct sk_buff *buf; + struct tipc_msg *msg; + unsigned int q_len; + unsigned int sz; + u32 err; + int res; + + /* Currently doesn't support receiving into multiple iovec entries */ + + if (m->msg_iovlen != 1) + return -EOPNOTSUPP; + + /* Catch invalid receive attempts */ + + if (unlikely(!buf_len)) + return -EINVAL; + + if (sock->type == SOCK_SEQPACKET) { + if (unlikely(sock->state == SS_UNCONNECTED)) + return -ENOTCONN; + if (unlikely((sock->state == SS_DISCONNECTING) && + (skb_queue_len(&sock->sk->sk_receive_queue) == 0))) + return -ENOTCONN; + } + + /* Look for a message in receive queue; wait if necessary */ + + if (unlikely(down_interruptible(&tsock->sem))) + return -ERESTARTSYS; + +restart: + if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) && + (flags & MSG_DONTWAIT))) { + res = -EWOULDBLOCK; + goto exit; + } + + if ((res = wait_event_interruptible( + *sock->sk->sk_sleep, + ((q_len = skb_queue_len(&sock->sk->sk_receive_queue)) || + (sock->state == SS_DISCONNECTING))) )) { + goto exit; + } + + /* Catch attempt to receive on an already terminated connection */ + /* [THIS CHECK MAY OVERLAP WITH AN EARLIER CHECK] */ + + if (!q_len) { + res = -ENOTCONN; + goto exit; + } + + /* Get access to first message in receive queue */ + + buf = skb_peek(&sock->sk->sk_receive_queue); + msg = buf_msg(buf); + sz = msg_data_sz(msg); + err = msg_errcode(msg); + + /* Complete connection setup for an implied connect */ + + if (unlikely(sock->state == SS_CONNECTING)) { + if ((res = auto_connect(sock, tsock, msg))) + goto exit; + } + + /* Discard an empty non-errored message & try again */ + + if ((!sz) && (!err)) { + advance_queue(tsock); + goto restart; + } + + /* Capture sender's address (optional) */ + + set_orig_addr(m, msg); + + /* Capture ancillary data (optional) */ + + if ((res = anc_data_recv(m, msg, tsock->p))) + goto exit; + + /* Capture message data (if valid) & compute return value (always) */ + + if (!err) { + if (unlikely(buf_len < sz)) { + sz = buf_len; + m->msg_flags |= MSG_TRUNC; + } + if (unlikely(copy_to_user(m->msg_iov->iov_base, msg_data(msg), + sz))) { + res = -EFAULT; + goto exit; + } + res = sz; + } else { + if ((sock->state == SS_READY) || + ((err == TIPC_CONN_SHUTDOWN) || m->msg_control)) + res = 0; + else + res = -ECONNRESET; + } + + /* Consume received message (optional) */ + + if (likely(!(flags & MSG_PEEK))) { + if (unlikely(++tsock->p->conn_unacked >= TIPC_FLOW_CONTROL_WIN)) + tipc_acknowledge(tsock->p->ref, tsock->p->conn_unacked); + advance_queue(tsock); + } +exit: + up(&tsock->sem); + return res; +} + +/** + * recv_stream - receive stream-oriented data + * @iocb: (unused) + * @m: descriptor for message info + * @buf_len: total size of user buffer area + * @flags: receive flags + * + * Used for SOCK_STREAM messages only. If not enough data is available + * will optionally wait for more; never truncates data. + * + * Returns size of returned message data, errno otherwise + */ + +static int recv_stream(struct kiocb *iocb, struct socket *sock, + struct msghdr *m, size_t buf_len, int flags) +{ + struct tipc_sock *tsock = tipc_sk(sock->sk); + struct sk_buff *buf; + struct tipc_msg *msg; + unsigned int q_len; + unsigned int sz; + int sz_to_copy; + int sz_copied = 0; + int needed; + char *crs = m->msg_iov->iov_base; + unsigned char *buf_crs; + u32 err; + int res; + + /* Currently doesn't support receiving into multiple iovec entries */ + + if (m->msg_iovlen != 1) + return -EOPNOTSUPP; + + /* Catch invalid receive attempts */ + + if (unlikely(!buf_len)) + return -EINVAL; + + if (unlikely(sock->state == SS_DISCONNECTING)) { + if (skb_queue_len(&sock->sk->sk_receive_queue) == 0) + return -ENOTCONN; + } else if (unlikely(sock->state != SS_CONNECTED)) + return -ENOTCONN; + + /* Look for a message in receive queue; wait if necessary */ + + if (unlikely(down_interruptible(&tsock->sem))) + return -ERESTARTSYS; + +restart: + if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) && + (flags & MSG_DONTWAIT))) { + res = (sz_copied == 0) ? -EWOULDBLOCK : 0; + goto exit; + } + + if ((res = wait_event_interruptible( + *sock->sk->sk_sleep, + ((q_len = skb_queue_len(&sock->sk->sk_receive_queue)) || + (sock->state == SS_DISCONNECTING))) )) { + goto exit; + } + + /* Catch attempt to receive on an already terminated connection */ + /* [THIS CHECK MAY OVERLAP WITH AN EARLIER CHECK] */ + + if (!q_len) { + res = -ENOTCONN; + goto exit; + } + + /* Get access to first message in receive queue */ + + buf = skb_peek(&sock->sk->sk_receive_queue); + msg = buf_msg(buf); + sz = msg_data_sz(msg); + err = msg_errcode(msg); + + /* Discard an empty non-errored message & try again */ + + if ((!sz) && (!err)) { + advance_queue(tsock); + goto restart; + } + + /* Optionally capture sender's address & ancillary data of first msg */ + + if (sz_copied == 0) { + set_orig_addr(m, msg); + if ((res = anc_data_recv(m, msg, tsock->p))) + goto exit; + } + + /* Capture message data (if valid) & compute return value (always) */ + + if (!err) { + buf_crs = (unsigned char *)(TIPC_SKB_CB(buf)->handle); + sz = buf->tail - buf_crs; + + needed = (buf_len - sz_copied); + sz_to_copy = (sz <= needed) ? sz : needed; + if (unlikely(copy_to_user(crs, buf_crs, sz_to_copy))) { + res = -EFAULT; + goto exit; + } + sz_copied += sz_to_copy; + + if (sz_to_copy < sz) { + if (!(flags & MSG_PEEK)) + TIPC_SKB_CB(buf)->handle = buf_crs + sz_to_copy; + goto exit; + } + + crs += sz_to_copy; + } else { + if (sz_copied != 0) + goto exit; /* can't add error msg to valid data */ + + if ((err == TIPC_CONN_SHUTDOWN) || m->msg_control) + res = 0; + else + res = -ECONNRESET; + } + + /* Consume received message (optional) */ + + if (likely(!(flags & MSG_PEEK))) { + if (unlikely(++tsock->p->conn_unacked >= TIPC_FLOW_CONTROL_WIN)) + tipc_acknowledge(tsock->p->ref, tsock->p->conn_unacked); + advance_queue(tsock); + } + + /* Loop around if more data is required */ + + if ((sz_copied < buf_len) /* didn't get all requested data */ + && (flags & MSG_WAITALL) /* ... and need to wait for more */ + && (!(flags & MSG_PEEK)) /* ... and aren't just peeking at data */ + && (!err) /* ... and haven't reached a FIN */ + ) + goto restart; + +exit: + up(&tsock->sem); + return res ? res : sz_copied; +} + +/** + * queue_overloaded - test if queue overload condition exists + * @queue_size: current size of queue + * @base: nominal maximum size of queue + * @msg: message to be added to queue + * + * Returns 1 if queue is currently overloaded, 0 otherwise + */ + +static int queue_overloaded(u32 queue_size, u32 base, struct tipc_msg *msg) +{ + u32 threshold; + u32 imp = msg_importance(msg); + + if (imp == TIPC_LOW_IMPORTANCE) + threshold = base; + else if (imp == TIPC_MEDIUM_IMPORTANCE) + threshold = base * 2; + else if (imp == TIPC_HIGH_IMPORTANCE) + threshold = base * 100; + else + return 0; + + if (msg_connected(msg)) + threshold *= 4; + + return (queue_size > threshold); +} + +/** + * async_disconnect - wrapper function used to disconnect port + * @portref: TIPC port reference (passed as pointer-sized value) + */ + +static void async_disconnect(unsigned long portref) +{ + tipc_disconnect((u32)portref); +} + +/** + * dispatch - handle arriving message + * @tport: TIPC port that received message + * @buf: message + * + * Called with port locked. Must not take socket lock to avoid deadlock risk. + * + * Returns TIPC error status code (TIPC_OK if message is not to be rejected) + */ + +static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf) +{ + struct tipc_msg *msg = buf_msg(buf); + struct tipc_sock *tsock = (struct tipc_sock *)tport->usr_handle; + struct socket *sock; + u32 recv_q_len; + + /* Reject message if socket is closing */ + + if (!tsock) + return TIPC_ERR_NO_PORT; + + /* Reject message if it is wrong sort of message for socket */ + + /* + * WOULD IT BE BETTER TO JUST DISCARD THESE MESSAGES INSTEAD? + * "NO PORT" ISN'T REALLY THE RIGHT ERROR CODE, AND THERE MAY + * BE SECURITY IMPLICATIONS INHERENT IN REJECTING INVALID TRAFFIC + */ + sock = tsock->sk.sk_socket; + if (sock->state == SS_READY) { + if (msg_connected(msg)) { + msg_dbg(msg, "dispatch filter 1\n"); + return TIPC_ERR_NO_PORT; + } + } else { + if (msg_mcast(msg)) { + msg_dbg(msg, "dispatch filter 2\n"); + return TIPC_ERR_NO_PORT; + } + if (sock->state == SS_CONNECTED) { + if (!msg_connected(msg)) { + msg_dbg(msg, "dispatch filter 3\n"); + return TIPC_ERR_NO_PORT; + } + } + else if (sock->state == SS_CONNECTING) { + if (!msg_connected(msg) && (msg_errcode(msg) == 0)) { + msg_dbg(msg, "dispatch filter 4\n"); + return TIPC_ERR_NO_PORT; + } + } + else if (sock->state == SS_LISTENING) { + if (msg_connected(msg) || msg_errcode(msg)) { + msg_dbg(msg, "dispatch filter 5\n"); + return TIPC_ERR_NO_PORT; + } + } + else if (sock->state == SS_DISCONNECTING) { + msg_dbg(msg, "dispatch filter 6\n"); + return TIPC_ERR_NO_PORT; + } + else /* (sock->state == SS_UNCONNECTED) */ { + if (msg_connected(msg) || msg_errcode(msg)) { + msg_dbg(msg, "dispatch filter 7\n"); + return TIPC_ERR_NO_PORT; + } + } + } + + /* Reject message if there isn't room to queue it */ + + if (unlikely((u32)atomic_read(&tipc_queue_size) > + OVERLOAD_LIMIT_BASE)) { + if (queue_overloaded(atomic_read(&tipc_queue_size), + OVERLOAD_LIMIT_BASE, msg)) + return TIPC_ERR_OVERLOAD; + } + recv_q_len = skb_queue_len(&tsock->sk.sk_receive_queue); + if (unlikely(recv_q_len > (OVERLOAD_LIMIT_BASE / 2))) { + if (queue_overloaded(recv_q_len, + OVERLOAD_LIMIT_BASE / 2, msg)) + return TIPC_ERR_OVERLOAD; + } + + /* Initiate connection termination for an incoming 'FIN' */ + + if (unlikely(msg_errcode(msg) && (sock->state == SS_CONNECTED))) { + sock->state = SS_DISCONNECTING; + /* Note: Use signal since port lock is already taken! */ + k_signal((Handler)async_disconnect, tport->ref); + } + + /* Enqueue message (finally!) */ + + msg_dbg(msg,"handle = msg_data(msg); + atomic_inc(&tipc_queue_size); + skb_queue_tail(&sock->sk->sk_receive_queue, buf); + + wake_up_interruptible(sock->sk->sk_sleep); + return TIPC_OK; +} + +/** + * wakeupdispatch - wake up port after congestion + * @tport: port to wakeup + * + * Called with port lock on. + */ + +static void wakeupdispatch(struct tipc_port *tport) +{ + struct tipc_sock *tsock = (struct tipc_sock *)tport->usr_handle; + + wake_up_interruptible(tsock->sk.sk_sleep); +} + +/** + * connect - establish a connection to another TIPC port + * @sock: socket structure + * @dest: socket address for destination port + * @destlen: size of socket address data structure + * @flags: (unused) + * + * Returns 0 on success, errno otherwise + */ + +static int connect(struct socket *sock, struct sockaddr *dest, int destlen, + int flags) +{ + struct tipc_sock *tsock = tipc_sk(sock->sk); + struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest; + struct msghdr m = {0,}; + struct sk_buff *buf; + struct tipc_msg *msg; + int res; + + /* For now, TIPC does not allow use of connect() with DGRAM or RDM types */ + + if (sock->state == SS_READY) + return -EOPNOTSUPP; + + /* MOVE THE REST OF THIS ERROR CHECKING TO send_msg()? */ + if (sock->state == SS_LISTENING) + return -EOPNOTSUPP; + if (sock->state == SS_CONNECTING) + return -EALREADY; + if (sock->state != SS_UNCONNECTED) + return -EISCONN; + + if ((dst->family != AF_TIPC) || + ((dst->addrtype != TIPC_ADDR_NAME) && (dst->addrtype != TIPC_ADDR_ID))) + return -EINVAL; + + /* Send a 'SYN-' to destination */ + + m.msg_name = dest; + if ((res = send_msg(0, sock, &m, 0)) < 0) { + sock->state = SS_DISCONNECTING; + return res; + } + + if (down_interruptible(&tsock->sem)) + return -ERESTARTSYS; + + /* Wait for destination's 'ACK' response */ + + res = wait_event_interruptible_timeout(*sock->sk->sk_sleep, + skb_queue_len(&sock->sk->sk_receive_queue), + sock->sk->sk_rcvtimeo); + buf = skb_peek(&sock->sk->sk_receive_queue); + if (res > 0) { + msg = buf_msg(buf); + res = auto_connect(sock, tsock, msg); + if (!res) { + if (dst->addrtype == TIPC_ADDR_NAME) { + tsock->p->conn_type = dst->addr.name.name.type; + tsock->p->conn_instance = dst->addr.name.name.instance; + } + if (!msg_data_sz(msg)) + advance_queue(tsock); + } + } else { + if (res == 0) { + res = -ETIMEDOUT; + } else + { /* leave "res" unchanged */ } + sock->state = SS_DISCONNECTING; + } + + up(&tsock->sem); + return res; +} + +/** + * listen - allow socket to listen for incoming connections + * @sock: socket structure + * @len: (unused) + * + * Returns 0 on success, errno otherwise + */ + +static int listen(struct socket *sock, int len) +{ + /* REQUIRES SOCKET LOCKING OF SOME SORT? */ + + if (sock->state == SS_READY) + return -EOPNOTSUPP; + if (sock->state != SS_UNCONNECTED) + return -EINVAL; + sock->state = SS_LISTENING; + return 0; +} + +/** + * accept - wait for connection request + * @sock: listening socket + * @newsock: new socket that is to be connected + * @flags: file-related flags associated with socket + * + * Returns 0 on success, errno otherwise + */ + +static int accept(struct socket *sock, struct socket *newsock, int flags) +{ + struct tipc_sock *tsock = tipc_sk(sock->sk); + struct sk_buff *buf; + int res = -EFAULT; + + if (sock->state == SS_READY) + return -EOPNOTSUPP; + if (sock->state != SS_LISTENING) + return -EINVAL; + + if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) && + (flags & O_NONBLOCK))) + return -EWOULDBLOCK; + + if (down_interruptible(&tsock->sem)) + return -ERESTARTSYS; + + if (wait_event_interruptible(*sock->sk->sk_sleep, + skb_queue_len(&sock->sk->sk_receive_queue))) { + res = -ERESTARTSYS; + goto exit; + } + buf = skb_peek(&sock->sk->sk_receive_queue); + + res = tipc_create(newsock, 0); + if (!res) { + struct tipc_sock *new_tsock = tipc_sk(newsock->sk); + struct tipc_portid id; + struct tipc_msg *msg = buf_msg(buf); + u32 new_ref = new_tsock->p->ref; + + id.ref = msg_origport(msg); + id.node = msg_orignode(msg); + tipc_connect2port(new_ref, &id); + newsock->state = SS_CONNECTED; + + tipc_set_portimportance(new_ref, msg_importance(msg)); + if (msg_named(msg)) { + new_tsock->p->conn_type = msg_nametype(msg); + new_tsock->p->conn_instance = msg_nameinst(msg); + } + + /* + * Respond to 'SYN-' by discarding it & returning 'ACK'-. + * Respond to 'SYN+' by queuing it on new socket. + */ + + msg_dbg(msg,"sk->sk_receive_queue); + sock_unlock(tsock); + skb_queue_head(&newsock->sk->sk_receive_queue, buf); + } + } +exit: + up(&tsock->sem); + return res; +} + +/** + * shutdown - shutdown socket connection + * @sock: socket structure + * @how: direction to close (always treated as read + write) + * + * Terminates connection (if necessary), then purges socket's receive queue. + * + * Returns 0 on success, errno otherwise + */ + +static int shutdown(struct socket *sock, int how) +{ + struct tipc_sock* tsock = tipc_sk(sock->sk); + struct sk_buff *buf; + int res; + + /* Could return -EINVAL for an invalid "how", but why bother? */ + + if (down_interruptible(&tsock->sem)) + return -ERESTARTSYS; + + sock_lock(tsock); + + switch (sock->state) { + case SS_CONNECTED: + + /* Send 'FIN+' or 'FIN-' message to peer */ + + sock_unlock(tsock); +restart: + if ((buf = skb_dequeue(&sock->sk->sk_receive_queue))) { + atomic_dec(&tipc_queue_size); + if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf))) { + buf_discard(buf); + goto restart; + } + tipc_reject_msg(buf, TIPC_CONN_SHUTDOWN); + } + else { + tipc_shutdown(tsock->p->ref); + } + sock_lock(tsock); + + /* fall through */ + + case SS_DISCONNECTING: + + /* Discard any unreceived messages */ + + while ((buf = skb_dequeue(&sock->sk->sk_receive_queue))) { + atomic_dec(&tipc_queue_size); + buf_discard(buf); + } + tsock->p->conn_unacked = 0; + + /* fall through */ + + case SS_CONNECTING: + sock->state = SS_DISCONNECTING; + res = 0; + break; + + default: + res = -ENOTCONN; + } + + sock_unlock(tsock); + + up(&tsock->sem); + return res; +} + +/** + * setsockopt - set socket option + * @sock: socket structure + * @lvl: option level + * @opt: option identifier + * @ov: pointer to new option value + * @ol: length of option value + * + * For stream sockets only, accepts and ignores all IPPROTO_TCP options + * (to ease compatibility). + * + * Returns 0 on success, errno otherwise + */ + +static int setsockopt(struct socket *sock, int lvl, int opt, char *ov, int ol) +{ + struct tipc_sock *tsock = tipc_sk(sock->sk); + u32 value; + int res; + + if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM)) + return 0; + if (lvl != SOL_TIPC) + return -ENOPROTOOPT; + if (ol < sizeof(value)) + return -EINVAL; + if ((res = get_user(value, (u32 *)ov))) + return res; + + if (down_interruptible(&tsock->sem)) + return -ERESTARTSYS; + + switch (opt) { + case TIPC_IMPORTANCE: + res = tipc_set_portimportance(tsock->p->ref, value); + break; + case TIPC_SRC_DROPPABLE: + if (sock->type != SOCK_STREAM) + res = tipc_set_portunreliable(tsock->p->ref, value); + else + res = -ENOPROTOOPT; + break; + case TIPC_DEST_DROPPABLE: + res = tipc_set_portunreturnable(tsock->p->ref, value); + break; + case TIPC_CONN_TIMEOUT: + sock->sk->sk_rcvtimeo = (value * HZ / 1000); + break; + default: + res = -EINVAL; + } + + up(&tsock->sem); + return res; +} + +/** + * getsockopt - get socket option + * @sock: socket structure + * @lvl: option level + * @opt: option identifier + * @ov: receptacle for option value + * @ol: receptacle for length of option value + * + * For stream sockets only, returns 0 length result for all IPPROTO_TCP options + * (to ease compatibility). + * + * Returns 0 on success, errno otherwise + */ + +static int getsockopt(struct socket *sock, int lvl, int opt, char *ov, int *ol) +{ + struct tipc_sock *tsock = tipc_sk(sock->sk); + int len; + u32 value; + int res; + + if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM)) + return put_user(0, ol); + if (lvl != SOL_TIPC) + return -ENOPROTOOPT; + if ((res = get_user(len, ol))) + return res; + + if (down_interruptible(&tsock->sem)) + return -ERESTARTSYS; + + switch (opt) { + case TIPC_IMPORTANCE: + res = tipc_portimportance(tsock->p->ref, &value); + break; + case TIPC_SRC_DROPPABLE: + res = tipc_portunreliable(tsock->p->ref, &value); + break; + case TIPC_DEST_DROPPABLE: + res = tipc_portunreturnable(tsock->p->ref, &value); + break; + case TIPC_CONN_TIMEOUT: + value = (sock->sk->sk_rcvtimeo * 1000) / HZ; + break; + default: + res = -EINVAL; + } + + if (res) { + /* "get" failed */ + } + else if (len < sizeof(value)) { + res = -EINVAL; + } + else if ((res = copy_to_user(ov, &value, sizeof(value)))) { + /* couldn't return value */ + } + else { + res = put_user(sizeof(value), ol); + } + + up(&tsock->sem); + return res; +} + +/** + * Placeholders for non-implemented functionality + * + * Returns error code (POSIX-compliant where defined) + */ + +static int ioctl(struct socket *s, u32 cmd, unsigned long arg) +{ + return -EINVAL; +} + +static int no_mmap(struct file *file, struct socket *sock, + struct vm_area_struct *vma) +{ + return -EINVAL; +} +static ssize_t no_sendpage(struct socket *sock, struct page *page, + int offset, size_t size, int flags) +{ + return -EINVAL; +} + +static int no_skpair(struct socket *s1, struct socket *s2) +{ + return -EOPNOTSUPP; +} + +/** + * Protocol switches for the various types of TIPC sockets + */ + +static struct proto_ops msg_ops = { + .owner = THIS_MODULE, + .family = AF_TIPC, + .release = release, + .bind = bind, + .connect = connect, + .socketpair = no_skpair, + .accept = accept, + .getname = get_name, + .poll = poll, + .ioctl = ioctl, + .listen = listen, + .shutdown = shutdown, + .setsockopt = setsockopt, + .getsockopt = getsockopt, + .sendmsg = send_msg, + .recvmsg = recv_msg, + .mmap = no_mmap, + .sendpage = no_sendpage +}; + +static struct proto_ops packet_ops = { + .owner = THIS_MODULE, + .family = AF_TIPC, + .release = release, + .bind = bind, + .connect = connect, + .socketpair = no_skpair, + .accept = accept, + .getname = get_name, + .poll = poll, + .ioctl = ioctl, + .listen = listen, + .shutdown = shutdown, + .setsockopt = setsockopt, + .getsockopt = getsockopt, + .sendmsg = send_packet, + .recvmsg = recv_msg, + .mmap = no_mmap, + .sendpage = no_sendpage +}; + +static struct proto_ops stream_ops = { + .owner = THIS_MODULE, + .family = AF_TIPC, + .release = release, + .bind = bind, + .connect = connect, + .socketpair = no_skpair, + .accept = accept, + .getname = get_name, + .poll = poll, + .ioctl = ioctl, + .listen = listen, + .shutdown = shutdown, + .setsockopt = setsockopt, + .getsockopt = getsockopt, + .sendmsg = send_stream, + .recvmsg = recv_stream, + .mmap = no_mmap, + .sendpage = no_sendpage +}; + +static struct net_proto_family tipc_family_ops = { + .owner = THIS_MODULE, + .family = AF_TIPC, + .create = tipc_create +}; + +static struct proto tipc_proto = { + .name = "TIPC", + .owner = THIS_MODULE, + .obj_size = sizeof(struct tipc_sock) +}; + +/** + * socket_init - initialize TIPC socket interface + * + * Returns 0 on success, errno otherwise + */ +int socket_init(void) +{ + int res; + + res = proto_register(&tipc_proto, 1); + if (res) { + err("Unable to register TIPC protocol type\n"); + goto out; + } + + res = sock_register(&tipc_family_ops); + if (res) { + err("Unable to register TIPC socket type\n"); + proto_unregister(&tipc_proto); + goto out; + } + + sockets_enabled = 1; + out: + return res; +} + +/** + * sock_stop - stop TIPC socket interface + */ +void socket_stop(void) +{ + if (!sockets_enabled) + return; + + sockets_enabled = 0; + sock_unregister(tipc_family_ops.family); + proto_unregister(&tipc_proto); +} + diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c new file mode 100644 index 00000000000..6f651a2c477 --- /dev/null +++ b/net/tipc/subscr.c @@ -0,0 +1,522 @@ +/* + * net/tipc/subscr.c: TIPC subscription service + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "core.h" +#include "dbg.h" +#include "subscr.h" +#include "name_table.h" +#include "ref.h" + +/** + * struct subscriber - TIPC network topology subscriber + * @ref: object reference to subscriber object itself + * @lock: pointer to spinlock controlling access to subscriber object + * @subscriber_list: adjacent subscribers in top. server's list of subscribers + * @subscription_list: list of subscription objects for this subscriber + * @port_ref: object reference to port used to communicate with subscriber + * @swap: indicates if subscriber uses opposite endianness in its messages + */ + +struct subscriber { + u32 ref; + spinlock_t *lock; + struct list_head subscriber_list; + struct list_head subscription_list; + u32 port_ref; + int swap; +}; + +/** + * struct top_srv - TIPC network topology subscription service + * @user_ref: TIPC userid of subscription service + * @setup_port: reference to TIPC port that handles subscription requests + * @subscription_count: number of active subscriptions (not subscribers!) + * @subscriber_list: list of ports subscribing to service + * @lock: spinlock govering access to subscriber list + */ + +struct top_srv { + u32 user_ref; + u32 setup_port; + atomic_t subscription_count; + struct list_head subscriber_list; + spinlock_t lock; +}; + +static struct top_srv topsrv = { 0 }; + +/** + * htohl - convert value to endianness used by destination + * @in: value to convert + * @swap: non-zero if endianness must be reversed + * + * Returns converted value + */ + +static inline u32 htohl(u32 in, int swap) +{ + char *c = (char *)∈ + + return swap ? ((c[3] << 3) + (c[2] << 2) + (c[1] << 1) + c[0]) : in; +} + +/** + * subscr_send_event - send a message containing a tipc_event to the subscriber + */ + +static void subscr_send_event(struct subscription *sub, + u32 found_lower, + u32 found_upper, + u32 event, + u32 port_ref, + u32 node) +{ + struct iovec msg_sect; + + msg_sect.iov_base = (void *)&sub->evt; + msg_sect.iov_len = sizeof(struct tipc_event); + + sub->evt.event = htohl(event, sub->owner->swap); + sub->evt.found_lower = htohl(found_lower, sub->owner->swap); + sub->evt.found_upper = htohl(found_upper, sub->owner->swap); + sub->evt.port.ref = htohl(port_ref, sub->owner->swap); + sub->evt.port.node = htohl(node, sub->owner->swap); + tipc_send(sub->owner->port_ref, 1, &msg_sect); +} + +/** + * subscr_overlap - test for subscription overlap with the given values + * + * Returns 1 if there is overlap, otherwise 0. + */ + +int subscr_overlap(struct subscription *sub, + u32 found_lower, + u32 found_upper) + +{ + if (found_lower < sub->seq.lower) + found_lower = sub->seq.lower; + if (found_upper > sub->seq.upper) + found_upper = sub->seq.upper; + if (found_lower > found_upper) + return 0; + return 1; +} + +/** + * subscr_report_overlap - issue event if there is subscription overlap + * + * Protected by nameseq.lock in name_table.c + */ + +void subscr_report_overlap(struct subscription *sub, + u32 found_lower, + u32 found_upper, + u32 event, + u32 port_ref, + u32 node, + int must) +{ + dbg("Rep overlap %u:%u,%u<->%u,%u\n", sub->seq.type, sub->seq.lower, + sub->seq.upper, found_lower, found_upper); + if (!subscr_overlap(sub, found_lower, found_upper)) + return; + if (!must && (sub->filter != TIPC_SUB_PORTS)) + return; + subscr_send_event(sub, found_lower, found_upper, event, port_ref, node); +} + +/** + * subscr_timeout - subscription timeout has occurred + */ + +static void subscr_timeout(struct subscription *sub) +{ + struct subscriber *subscriber; + u32 subscriber_ref; + + /* Validate subscriber reference (in case subscriber is terminating) */ + + subscriber_ref = sub->owner->ref; + subscriber = (struct subscriber *)ref_lock(subscriber_ref); + if (subscriber == NULL) + return; + + /* Unlink subscription from name table */ + + nametbl_unsubscribe(sub); + + /* Notify subscriber of timeout, then unlink subscription */ + + subscr_send_event(sub, + sub->evt.s.seq.lower, + sub->evt.s.seq.upper, + TIPC_SUBSCR_TIMEOUT, + 0, + 0); + list_del(&sub->subscription_list); + + /* Now destroy subscription */ + + ref_unlock(subscriber_ref); + k_term_timer(&sub->timer); + kfree(sub); + atomic_dec(&topsrv.subscription_count); +} + +/** + * subscr_terminate - terminate communication with a subscriber + * + * Called with subscriber locked. Routine must temporarily release this lock + * to enable subscription timeout routine(s) to finish without deadlocking; + * the lock is then reclaimed to allow caller to release it upon return. + * (This should work even in the unlikely event some other thread creates + * a new object reference in the interim that uses this lock; this routine will + * simply wait for it to be released, then claim it.) + */ + +static void subscr_terminate(struct subscriber *subscriber) +{ + struct subscription *sub; + struct subscription *sub_temp; + + /* Invalidate subscriber reference */ + + ref_discard(subscriber->ref); + spin_unlock_bh(subscriber->lock); + + /* Destroy any existing subscriptions for subscriber */ + + list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, + subscription_list) { + if (sub->timeout != TIPC_WAIT_FOREVER) { + k_cancel_timer(&sub->timer); + k_term_timer(&sub->timer); + } + nametbl_unsubscribe(sub); + list_del(&sub->subscription_list); + dbg("Term: Removed sub %u,%u,%u from subscriber %x list\n", + sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber); + kfree(sub); + atomic_dec(&topsrv.subscription_count); + } + + /* Sever connection to subscriber */ + + tipc_shutdown(subscriber->port_ref); + tipc_deleteport(subscriber->port_ref); + + /* Remove subscriber from topology server's subscriber list */ + + spin_lock_bh(&topsrv.lock); + list_del(&subscriber->subscriber_list); + spin_unlock_bh(&topsrv.lock); + + /* Now destroy subscriber */ + + spin_lock_bh(subscriber->lock); + kfree(subscriber); +} + +/** + * subscr_subscribe - create subscription for subscriber + * + * Called with subscriber locked + */ + +static void subscr_subscribe(struct tipc_subscr *s, + struct subscriber *subscriber) +{ + struct subscription *sub; + + /* Refuse subscription if global limit exceeded */ + + if (atomic_read(&topsrv.subscription_count) >= tipc_max_subscriptions) { + warn("Failed: max %u subscriptions\n", tipc_max_subscriptions); + subscr_terminate(subscriber); + return; + } + + /* Allocate subscription object */ + + sub = kmalloc(sizeof(*sub), GFP_ATOMIC); + if (sub == NULL) { + warn("Memory squeeze; ignoring subscription\n"); + subscr_terminate(subscriber); + return; + } + + /* Determine/update subscriber's endianness */ + + if ((s->filter == TIPC_SUB_PORTS) || (s->filter == TIPC_SUB_SERVICE)) + subscriber->swap = 0; + else + subscriber->swap = 1; + + /* Initialize subscription object */ + + memset(sub, 0, sizeof(*sub)); + sub->seq.type = htohl(s->seq.type, subscriber->swap); + sub->seq.lower = htohl(s->seq.lower, subscriber->swap); + sub->seq.upper = htohl(s->seq.upper, subscriber->swap); + sub->timeout = htohl(s->timeout, subscriber->swap); + sub->filter = htohl(s->filter, subscriber->swap); + if ((((sub->filter != TIPC_SUB_PORTS) + && (sub->filter != TIPC_SUB_SERVICE))) + || (sub->seq.lower > sub->seq.upper)) { + warn("Rejecting illegal subscription %u,%u,%u\n", + sub->seq.type, sub->seq.lower, sub->seq.upper); + kfree(sub); + subscr_terminate(subscriber); + return; + } + memcpy(&sub->evt.s, s, sizeof(struct tipc_subscr)); + INIT_LIST_HEAD(&sub->subscription_list); + INIT_LIST_HEAD(&sub->nameseq_list); + list_add(&sub->subscription_list, &subscriber->subscription_list); + atomic_inc(&topsrv.subscription_count); + if (sub->timeout != TIPC_WAIT_FOREVER) { + k_init_timer(&sub->timer, + (Handler)subscr_timeout, (unsigned long)sub); + k_start_timer(&sub->timer, sub->timeout); + } + sub->owner = subscriber; + nametbl_subscribe(sub); +} + +/** + * subscr_conn_shutdown_event - handle termination request from subscriber + */ + +static void subscr_conn_shutdown_event(void *usr_handle, + u32 portref, + struct sk_buff **buf, + unsigned char const *data, + unsigned int size, + int reason) +{ + struct subscriber *subscriber = ref_lock((u32)usr_handle); + spinlock_t *subscriber_lock; + + if (subscriber == NULL) + return; + + subscriber_lock = subscriber->lock; + subscr_terminate(subscriber); + spin_unlock_bh(subscriber_lock); +} + +/** + * subscr_conn_msg_event - handle new subscription request from subscriber + */ + +static void subscr_conn_msg_event(void *usr_handle, + u32 port_ref, + struct sk_buff **buf, + const unchar *data, + u32 size) +{ + struct subscriber *subscriber = ref_lock((u32)usr_handle); + spinlock_t *subscriber_lock; + + if (subscriber == NULL) + return; + + subscriber_lock = subscriber->lock; + if (size != sizeof(struct tipc_subscr)) + subscr_terminate(subscriber); + else + subscr_subscribe((struct tipc_subscr *)data, subscriber); + + spin_unlock_bh(subscriber_lock); +} + +/** + * subscr_named_msg_event - handle request to establish a new subscriber + */ + +static void subscr_named_msg_event(void *usr_handle, + u32 port_ref, + struct sk_buff **buf, + const unchar *data, + u32 size, + u32 importance, + struct tipc_portid const *orig, + struct tipc_name_seq const *dest) +{ + struct subscriber *subscriber; + struct iovec msg_sect = {0, 0}; + spinlock_t *subscriber_lock; + + dbg("subscr_named_msg_event: orig = %x own = %x,\n", + orig->node, tipc_own_addr); + if (size && (size != sizeof(struct tipc_subscr))) { + warn("Received tipc_subscr of invalid size\n"); + return; + } + + /* Create subscriber object */ + + subscriber = kmalloc(sizeof(struct subscriber), GFP_ATOMIC); + if (subscriber == NULL) { + warn("Memory squeeze; ignoring subscriber setup\n"); + return; + } + memset(subscriber, 0, sizeof(struct subscriber)); + INIT_LIST_HEAD(&subscriber->subscription_list); + INIT_LIST_HEAD(&subscriber->subscriber_list); + subscriber->ref = ref_acquire(subscriber, &subscriber->lock); + if (subscriber->ref == 0) { + warn("Failed to acquire subscriber reference\n"); + kfree(subscriber); + return; + } + + /* Establish a connection to subscriber */ + + tipc_createport(topsrv.user_ref, + (void *)subscriber->ref, + importance, + 0, + 0, + subscr_conn_shutdown_event, + 0, + 0, + subscr_conn_msg_event, + 0, + &subscriber->port_ref); + if (subscriber->port_ref == 0) { + warn("Memory squeeze; failed to create subscription port\n"); + ref_discard(subscriber->ref); + kfree(subscriber); + return; + } + tipc_connect2port(subscriber->port_ref, orig); + + + /* Add subscriber to topology server's subscriber list */ + + ref_lock(subscriber->ref); + spin_lock_bh(&topsrv.lock); + list_add(&subscriber->subscriber_list, &topsrv.subscriber_list); + spin_unlock_bh(&topsrv.lock); + + /* + * Subscribe now if message contains a subscription, + * otherwise send an empty response to complete connection handshaking + */ + + subscriber_lock = subscriber->lock; + if (size) + subscr_subscribe((struct tipc_subscr *)data, subscriber); + else + tipc_send(subscriber->port_ref, 1, &msg_sect); + + spin_unlock_bh(subscriber_lock); +} + +int subscr_start(void) +{ + struct tipc_name_seq seq = {TIPC_TOP_SRV, TIPC_TOP_SRV, TIPC_TOP_SRV}; + int res = -1; + + memset(&topsrv, 0, sizeof (topsrv)); + topsrv.lock = SPIN_LOCK_UNLOCKED; + INIT_LIST_HEAD(&topsrv.subscriber_list); + + spin_lock_bh(&topsrv.lock); + res = tipc_attach(&topsrv.user_ref, 0, 0); + if (res) { + spin_unlock_bh(&topsrv.lock); + return res; + } + + res = tipc_createport(topsrv.user_ref, + 0, + TIPC_CRITICAL_IMPORTANCE, + 0, + 0, + 0, + 0, + subscr_named_msg_event, + 0, + 0, + &topsrv.setup_port); + if (res) + goto failed; + + res = nametbl_publish_rsv(topsrv.setup_port, TIPC_NODE_SCOPE, &seq); + if (res) + goto failed; + + spin_unlock_bh(&topsrv.lock); + return 0; + +failed: + err("Unable to create subscription service\n"); + tipc_detach(topsrv.user_ref); + topsrv.user_ref = 0; + spin_unlock_bh(&topsrv.lock); + return res; +} + +void subscr_stop(void) +{ + struct subscriber *subscriber; + struct subscriber *subscriber_temp; + spinlock_t *subscriber_lock; + + if (topsrv.user_ref) { + tipc_deleteport(topsrv.setup_port); + list_for_each_entry_safe(subscriber, subscriber_temp, + &topsrv.subscriber_list, + subscriber_list) { + ref_lock(subscriber->ref); + subscriber_lock = subscriber->lock; + subscr_terminate(subscriber); + spin_unlock_bh(subscriber_lock); + } + tipc_detach(topsrv.user_ref); + topsrv.user_ref = 0; + } +} + + +int tipc_ispublished(struct tipc_name const *name) +{ + u32 domain = 0; + + return(nametbl_translate(name->type, name->instance,&domain) != 0); +} + diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h new file mode 100644 index 00000000000..e6cb9c3ad87 --- /dev/null +++ b/net/tipc/subscr.h @@ -0,0 +1,77 @@ +/* + * net/tipc/subscr.h: Include file for TIPC subscription service + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _TIPC_SUBSCR_H +#define _TIPC_SUBSCR_H + +/** + * struct subscription - TIPC network topology subscription object + * @seq: name sequence associated with subscription + * @timeout: duration of subscription (in ms) + * @filter: event filtering to be done for subscription + * @evt: template for events generated by subscription + * @subscription_list: adjacent subscriptions in subscriber's subscription list + * @nameseq_list: adjacent subscriptions in name sequence's subscription list + * @timer_ref: reference to timer governing subscription duration (may be NULL) + * @owner: pointer to subscriber object associated with this subscription + */ + +struct subscription { + struct tipc_name_seq seq; + u32 timeout; + u32 filter; + struct tipc_event evt; + struct list_head subscription_list; + struct list_head nameseq_list; + struct timer_list timer; + struct subscriber *owner; +}; + +int subscr_overlap(struct subscription * sub, + u32 found_lower, + u32 found_upper); + +void subscr_report_overlap(struct subscription * sub, + u32 found_lower, + u32 found_upper, + u32 event, + u32 port_ref, + u32 node, + int must_report); + +int subscr_start(void); + +void subscr_stop(void); + + +#endif diff --git a/net/tipc/user_reg.c b/net/tipc/user_reg.c new file mode 100644 index 00000000000..e4da5becc34 --- /dev/null +++ b/net/tipc/user_reg.c @@ -0,0 +1,262 @@ +/* + * net/tipc/user_reg.c: TIPC user registry code + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2004-2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "core.h" +#include "user_reg.h" + +/* + * TIPC user registry keeps track of users of the tipc_port interface. + * + * The registry utilizes an array of "TIPC user" entries; + * a user's ID is the index of their associated array entry. + * Array entry 0 is not used, so userid 0 is not valid; + * TIPC sometimes uses this value to denote an anonymous user. + * The list of free entries is initially chained from last entry to entry 1. + */ + +/** + * struct tipc_user - registered TIPC user info + * @next: index of next free registry entry (or -1 for an allocated entry) + * @callback: ptr to routine to call when TIPC mode changes (NULL if none) + * @usr_handle: user-defined value passed to callback routine + * @ports: list of user ports owned by the user + */ + +struct tipc_user { + int next; + tipc_mode_event callback; + void *usr_handle; + struct list_head ports; +}; + +#define MAX_USERID 64 +#define USER_LIST_SIZE ((MAX_USERID + 1) * sizeof(struct tipc_user)) + +static struct tipc_user *users = 0; +static u32 next_free_user = MAX_USERID + 1; +static spinlock_t reg_lock = SPIN_LOCK_UNLOCKED; + +/** + * reg_init - create TIPC user registry (but don't activate it) + * + * If registry has been pre-initialized it is left "as is". + * NOTE: This routine may be called when TIPC is inactive. + */ + +static int reg_init(void) +{ + u32 i; + + spin_lock_bh(®_lock); + if (!users) { + users = (struct tipc_user *)kmalloc(USER_LIST_SIZE, GFP_ATOMIC); + if (users) { + memset(users, 0, USER_LIST_SIZE); + for (i = 1; i <= MAX_USERID; i++) { + users[i].next = i - 1; + } + next_free_user = MAX_USERID; + } + } + spin_unlock_bh(®_lock); + return users ? TIPC_OK : -ENOMEM; +} + +/** + * reg_callback - inform TIPC user about current operating mode + */ + +static void reg_callback(struct tipc_user *user_ptr) +{ + tipc_mode_event cb; + void *arg; + + spin_lock_bh(®_lock); + cb = user_ptr->callback; + arg = user_ptr->usr_handle; + spin_unlock_bh(®_lock); + + if (cb) + cb(arg, tipc_mode, tipc_own_addr); +} + +/** + * reg_start - activate TIPC user registry + */ + +int reg_start(void) +{ + u32 u; + int res; + + if ((res = reg_init())) + return res; + + for (u = 1; u <= MAX_USERID; u++) { + if (users[u].callback) + k_signal((Handler)reg_callback, + (unsigned long)&users[u]); + } + return TIPC_OK; +} + +/** + * reg_stop - shut down & delete TIPC user registry + */ + +void reg_stop(void) +{ + int id; + + if (!users) + return; + + for (id = 1; id <= MAX_USERID; id++) { + if (users[id].callback) + reg_callback(&users[id]); + } + kfree(users); + users = 0; +} + +/** + * tipc_attach - register a TIPC user + * + * NOTE: This routine may be called when TIPC is inactive. + */ + +int tipc_attach(u32 *userid, tipc_mode_event cb, void *usr_handle) +{ + struct tipc_user *user_ptr; + + if ((tipc_mode == TIPC_NOT_RUNNING) && !cb) + return -ENOPROTOOPT; + if (!users) + reg_init(); + + spin_lock_bh(®_lock); + if (!next_free_user) { + spin_unlock_bh(®_lock); + return -EBUSY; + } + user_ptr = &users[next_free_user]; + *userid = next_free_user; + next_free_user = user_ptr->next; + user_ptr->next = -1; + spin_unlock_bh(®_lock); + + user_ptr->callback = cb; + user_ptr->usr_handle = usr_handle; + INIT_LIST_HEAD(&user_ptr->ports); + atomic_inc(&tipc_user_count); + + if (cb && (tipc_mode != TIPC_NOT_RUNNING)) + k_signal((Handler)reg_callback, (unsigned long)user_ptr); + return TIPC_OK; +} + +/** + * tipc_detach - deregister a TIPC user + */ + +void tipc_detach(u32 userid) +{ + struct tipc_user *user_ptr; + struct list_head ports_temp; + struct user_port *up_ptr, *temp_up_ptr; + + if ((userid == 0) || (userid > MAX_USERID)) + return; + + spin_lock_bh(®_lock); + if ((!users) || (users[userid].next >= 0)) { + spin_unlock_bh(®_lock); + return; + } + + user_ptr = &users[userid]; + user_ptr->callback = NULL; + INIT_LIST_HEAD(&ports_temp); + list_splice(&user_ptr->ports, &ports_temp); + user_ptr->next = next_free_user; + next_free_user = userid; + spin_unlock_bh(®_lock); + + atomic_dec(&tipc_user_count); + + list_for_each_entry_safe(up_ptr, temp_up_ptr, &ports_temp, uport_list) { + tipc_deleteport(up_ptr->ref); + } +} + +/** + * reg_add_port - register a user's driver port + */ + +int reg_add_port(struct user_port *up_ptr) +{ + struct tipc_user *user_ptr; + + if (up_ptr->user_ref == 0) + return TIPC_OK; + if (up_ptr->user_ref > MAX_USERID) + return -EINVAL; + if ((tipc_mode == TIPC_NOT_RUNNING) || !users ) + return -ENOPROTOOPT; + + spin_lock_bh(®_lock); + user_ptr = &users[up_ptr->user_ref]; + list_add(&up_ptr->uport_list, &user_ptr->ports); + spin_unlock_bh(®_lock); + return TIPC_OK; +} + +/** + * reg_remove_port - deregister a user's driver port + */ + +int reg_remove_port(struct user_port *up_ptr) +{ + if (up_ptr->user_ref == 0) + return TIPC_OK; + if (up_ptr->user_ref > MAX_USERID) + return -EINVAL; + if (!users ) + return -ENOPROTOOPT; + + spin_lock_bh(®_lock); + list_del_init(&up_ptr->uport_list); + spin_unlock_bh(®_lock); + return TIPC_OK; +} + diff --git a/net/tipc/user_reg.h b/net/tipc/user_reg.h new file mode 100644 index 00000000000..44f219458a3 --- /dev/null +++ b/net/tipc/user_reg.h @@ -0,0 +1,45 @@ +/* + * net/tipc/user_reg.h: Include file for TIPC user registry code + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _TIPC_USER_REG_H +#define _TIPC_USER_REG_H + +#include "port.h" + +int reg_start(void); +void reg_stop(void); + +int reg_add_port(struct user_port *up_ptr); +int reg_remove_port(struct user_port *up_ptr); + +#endif diff --git a/net/tipc/zone.c b/net/tipc/zone.c new file mode 100644 index 00000000000..336eebb7bf5 --- /dev/null +++ b/net/tipc/zone.c @@ -0,0 +1,166 @@ +/* + * net/tipc/zone.c: TIPC zone management routines + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "core.h" +#include "zone.h" +#include "net.h" +#include "addr.h" +#include "node_subscr.h" +#include "cluster.h" +#include "node.h" + +struct _zone *zone_create(u32 addr) +{ + struct _zone *z_ptr = 0; + u32 z_num; + + if (!addr_domain_valid(addr)) + return 0; + + z_ptr = (struct _zone *)kmalloc(sizeof(*z_ptr), GFP_ATOMIC); + if (z_ptr != NULL) { + memset(z_ptr, 0, sizeof(*z_ptr)); + z_num = tipc_zone(addr); + z_ptr->addr = tipc_addr(z_num, 0, 0); + net.zones[z_num] = z_ptr; + } + return z_ptr; +} + +void zone_delete(struct _zone *z_ptr) +{ + u32 c_num; + + if (!z_ptr) + return; + for (c_num = 1; c_num <= tipc_max_clusters; c_num++) { + cluster_delete(z_ptr->clusters[c_num]); + } + kfree(z_ptr); +} + +void zone_attach_cluster(struct _zone *z_ptr, struct cluster *c_ptr) +{ + u32 c_num = tipc_cluster(c_ptr->addr); + + assert(c_ptr->addr); + assert(c_num <= tipc_max_clusters); + assert(z_ptr->clusters[c_num] == 0); + z_ptr->clusters[c_num] = c_ptr; +} + +void zone_remove_as_router(struct _zone *z_ptr, u32 router) +{ + u32 c_num; + + for (c_num = 1; c_num <= tipc_max_clusters; c_num++) { + if (z_ptr->clusters[c_num]) { + cluster_remove_as_router(z_ptr->clusters[c_num], + router); + } + } +} + +void zone_send_external_routes(struct _zone *z_ptr, u32 dest) +{ + u32 c_num; + + for (c_num = 1; c_num <= tipc_max_clusters; c_num++) { + if (z_ptr->clusters[c_num]) { + if (in_own_cluster(z_ptr->addr)) + continue; + cluster_send_ext_routes(z_ptr->clusters[c_num], dest); + } + } +} + +struct node *zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref) +{ + struct cluster *c_ptr; + struct node *n_ptr; + u32 c_num; + + if (!z_ptr) + return 0; + c_ptr = z_ptr->clusters[tipc_cluster(addr)]; + if (!c_ptr) + return 0; + n_ptr = cluster_select_node(c_ptr, ref); + if (n_ptr) + return n_ptr; + + /* Links to any other clusters within this zone ? */ + for (c_num = 1; c_num <= tipc_max_clusters; c_num++) { + c_ptr = z_ptr->clusters[c_num]; + if (!c_ptr) + return 0; + n_ptr = cluster_select_node(c_ptr, ref); + if (n_ptr) + return n_ptr; + } + return 0; +} + +u32 zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref) +{ + struct cluster *c_ptr; + u32 c_num; + u32 router; + + if (!z_ptr) + return 0; + c_ptr = z_ptr->clusters[tipc_cluster(addr)]; + router = c_ptr ? cluster_select_router(c_ptr, ref) : 0; + if (router) + return router; + + /* Links to any other clusters within the zone? */ + for (c_num = 1; c_num <= tipc_max_clusters; c_num++) { + c_ptr = z_ptr->clusters[c_num]; + router = c_ptr ? cluster_select_router(c_ptr, ref) : 0; + if (router) + return router; + } + return 0; +} + + +u32 zone_next_node(u32 addr) +{ + struct cluster *c_ptr = cluster_find(addr); + + if (c_ptr) + return cluster_next_node(c_ptr, addr); + return 0; +} + diff --git a/net/tipc/zone.h b/net/tipc/zone.h new file mode 100644 index 00000000000..19fd51a8bd2 --- /dev/null +++ b/net/tipc/zone.h @@ -0,0 +1,68 @@ +/* + * net/tipc/zone.h: Include file for TIPC zone management routines + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _TIPC_ZONE_H +#define _TIPC_ZONE_H + +#include "node_subscr.h" +#include "net.h" + + +/** + * struct _zone - TIPC zone structure + * @addr: network address of zone + * @clusters: array of pointers to all clusters within zone + * @links: (used for inter-zone communication) + */ + +struct _zone { + u32 addr; + struct cluster *clusters[2]; /* currently limited to just 1 cluster */ + u32 links; +}; + +struct node *zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref); +u32 zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref); +void zone_remove_as_router(struct _zone *z_ptr, u32 router); +void zone_send_external_routes(struct _zone *z_ptr, u32 dest); +struct _zone *zone_create(u32 addr); +void zone_delete(struct _zone *z_ptr); +void zone_attach_cluster(struct _zone *z_ptr, struct cluster *c_ptr); +u32 zone_next_node(u32 addr); + +static inline struct _zone *zone_find(u32 addr) +{ + return net.zones[tipc_zone(addr)]; +} + +#endif -- GitLab From 1dba9743337cabacea79e47ed6d709e636c5ed47 Mon Sep 17 00:00:00 2001 From: Per Liden Date: Thu, 5 Jan 2006 16:34:00 +0100 Subject: [PATCH 039/465] [TIPC] Use dynamically allocated family id with NETLINK_GENERIC Signed-off-by: Per Liden --- include/linux/tipc.h | 1 - net/tipc/netlink.c | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/include/linux/tipc.h b/include/linux/tipc.h index ca754f3317f..1faab77626f 100644 --- a/include/linux/tipc.h +++ b/include/linux/tipc.h @@ -539,7 +539,6 @@ static inline void TLV_LIST_STEP(struct tlv_list_desc *list) * Configuration messages exchanged via NETLINK_GENERIC use the following * family id, name, version and command. */ -#define TIPC_GENL_FAMILY 0x222 #define TIPC_GENL_NAME "TIPC" #define TIPC_GENL_VERSION 0x1 #define TIPC_GENL_CMD 0x1 diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index 35fbc793360..08b974ed910 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c @@ -40,7 +40,7 @@ static int handle_cmd(struct sk_buff *skb, struct genl_info *info) struct nlmsghdr *rep_nlh; struct nlmsghdr *req_nlh = info->nlhdr; struct tipc_genlmsghdr *req_userhdr = info->userhdr; - int hdr_space = NLMSG_SPACE(0); + int hdr_space = NLMSG_SPACE(GENL_HDRLEN + TIPC_GENL_HDRLEN); if ((req_userhdr->cmd & 0xC000) && (!capable(CAP_NET_ADMIN))) rep_buf = cfg_reply_error_string(TIPC_CFG_NOT_NET_ADMIN); @@ -63,7 +63,7 @@ static int handle_cmd(struct sk_buff *skb, struct genl_info *info) } static struct genl_family family = { - .id = TIPC_GENL_FAMILY, + .id = GENL_ID_GENERATE, .name = TIPC_GENL_NAME, .version = TIPC_GENL_VERSION, .hdrsize = TIPC_GENL_HDRLEN, -- GitLab From b70e4f45a8d8125e4f420c62e71688b8a766689a Mon Sep 17 00:00:00 2001 From: Jon Maloy Date: Tue, 10 Jan 2006 18:54:24 +0000 Subject: [PATCH 040/465] [TIPC} Fixed bug in disc_timeout() Signed-off-by: Jon Maloy --- net/tipc/discover.c | 28 ++-------------------------- net/tipc/netlink.c | 4 +++- 2 files changed, 5 insertions(+), 27 deletions(-) diff --git a/net/tipc/discover.c b/net/tipc/discover.c index c83c1be17f8..73e151cf2a5 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c @@ -258,32 +258,8 @@ void disc_update_link_req(struct link_req *req) static void disc_timeout(struct link_req *req) { - struct tipc_msg *msg = buf_msg(req->buf); - spin_lock_bh(&req->bearer->publ.lock); -#if 0 - /* CURRENTLY DON'T SUPPORT INTER-ZONE LINKS */ - u32 dest_domain = msg_dest_domain(msg); - int stop = 0; - if (!in_scope(dest_domain, tipc_own_addr)) { - struct _zone *z_ptr = zone_find(dest_domain); - - if (z_ptr && (z_ptr->links >= msg_req_links(msg))) - stop = 1; - if (req->timer_intv >= 32000) - stop = 1; - } - if (stop) { - k_cancel_timer(&req->timer); - buf_discard(req->buf); - kfree(req); - spin_unlock_bh(&req->bearer->publ.lock); - return; - } -#endif - - msg_dbg(msg,"SEND:"); req->bearer->media->send_msg(req->buf, &req->bearer->publ, &req->dest); if ((req->timer_intv == TIPC_LINK_REQ_SLOW) || @@ -291,8 +267,8 @@ static void disc_timeout(struct link_req *req) /* leave timer interval "as is" if already at a "normal" rate */ } else { req->timer_intv *= 2; - if (req->timer_intv > TIPC_LINK_REQ_FAST) - req->timer_intv = TIPC_LINK_REQ_FAST; + if (req->timer_intv > TIPC_LINK_REQ_SLOW) + req->timer_intv = TIPC_LINK_REQ_SLOW; if ((req->timer_intv == TIPC_LINK_REQ_FAST) && (req->bearer->nodes.count)) req->timer_intv = TIPC_LINK_REQ_SLOW; diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index 08b974ed910..2d778dfc449 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c @@ -80,6 +80,8 @@ static int family_registered = 0; int netlink_start(void) { + + if (genl_register_family(&family)) goto err; @@ -88,7 +90,7 @@ int netlink_start(void) if (genl_register_ops(&family, &ops)) goto err_unregister; - return 0; + return 0; err_unregister: genl_unregister_family(&family); -- GitLab From ea714ccda5d5858ee677a77cf33dbaf34a0060c3 Mon Sep 17 00:00:00 2001 From: Per Liden Date: Wed, 11 Jan 2006 12:28:47 +0100 Subject: [PATCH 041/465] [TIPC] Moved configuration interface into tipc_config.h Restored the old tipc_config.h to get a cleaner division between the interfaces used by normal TIPC users and TIPC administration utilities. Signed-off-by: Per Liden --- include/linux/tipc.h | 434 ++------------------------------- include/linux/tipc_config.h | 404 ++++++++++++++++++++++++++++++ include/net/tipc/tipc_bearer.h | 28 ++- net/tipc/config.h | 1 + net/tipc/socket.c | 1 + 5 files changed, 456 insertions(+), 412 deletions(-) create mode 100644 include/linux/tipc_config.h diff --git a/include/linux/tipc.h b/include/linux/tipc.h index 1faab77626f..4ecd0047550 100644 --- a/include/linux/tipc.h +++ b/include/linux/tipc.h @@ -1,5 +1,5 @@ /* - * include/linux/tipc.h: Include file for TIPC users + * include/linux/tipc.h: Include file for TIPC socket interface * * Copyright (c) 2003-2005, Ericsson Research Canada * Copyright (c) 2005, Wind River Systems @@ -35,8 +35,6 @@ #define _LINUX_TIPC_H_ #include -#include -#include /* * TIPC addressing primitives @@ -62,51 +60,51 @@ static inline __u32 tipc_addr(unsigned int zone, unsigned int cluster, unsigned int node) { - return(zone << 24) | (cluster << 12) | node; + return (zone << 24) | (cluster << 12) | node; } static inline unsigned int tipc_zone(__u32 addr) { - return addr >> 24; + return addr >> 24; } static inline unsigned int tipc_cluster(__u32 addr) { - return(addr >> 12) & 0xfff; + return (addr >> 12) & 0xfff; } static inline unsigned int tipc_node(__u32 addr) { - return addr & 0xfff; + return addr & 0xfff; } /* * Application-accessible port name types */ -#define TIPC_NET_EVENTS 0 /* network event subscription name type */ -#define TIPC_TOP_SRV 1 /* topology service name type */ +#define TIPC_CFG_SRV 0 /* configuration service name type */ +#define TIPC_TOP_SRV 1 /* topology service name type */ #define TIPC_RESERVED_TYPES 64 /* lowest user-publishable name type */ /* * Publication scopes when binding port names and port name sequences */ -#define TIPC_ZONE_SCOPE 1 -#define TIPC_CLUSTER_SCOPE 2 -#define TIPC_NODE_SCOPE 3 +#define TIPC_ZONE_SCOPE 1 +#define TIPC_CLUSTER_SCOPE 2 +#define TIPC_NODE_SCOPE 3 /* * Limiting values for messages */ -#define TIPC_MAX_USER_MSG_SIZE 66000 +#define TIPC_MAX_USER_MSG_SIZE 66000 -/* +/* * Message importance levels */ -#define TIPC_LOW_IMPORTANCE 0 /* default */ +#define TIPC_LOW_IMPORTANCE 0 /* default */ #define TIPC_MEDIUM_IMPORTANCE 1 #define TIPC_HIGH_IMPORTANCE 2 #define TIPC_CRITICAL_IMPORTANCE 3 @@ -135,7 +133,7 @@ static inline unsigned int tipc_node(__u32 addr) #define TIPC_SUB_SINGLE_EVT 0x10 /* expire after first event */ #endif -#define TIPC_WAIT_FOREVER ~0 /* timeout for permanent subscription */ +#define TIPC_WAIT_FOREVER ~0 /* timeout for permanent subscription */ struct tipc_subscr { struct tipc_name_seq seq; /* name sequence of interest */ @@ -144,16 +142,15 @@ struct tipc_subscr { char usr_handle[8]; /* available for subscriber use */ }; - -#define TIPC_PUBLISHED 1 /* publication event */ -#define TIPC_WITHDRAWN 2 /* withdraw event */ -#define TIPC_SUBSCR_TIMEOUT 3 /* subscription timeout event */ +#define TIPC_PUBLISHED 1 /* publication event */ +#define TIPC_WITHDRAWN 2 /* withdraw event */ +#define TIPC_SUBSCR_TIMEOUT 3 /* subscription timeout event */ struct tipc_event { __u32 event; /* event type */ __u32 found_lower; /* matching name seq instances */ __u32 found_upper; /* " " " " */ - struct tipc_portid port; /* associated port */ + struct tipc_portid port; /* associated port */ struct tipc_subscr s; /* associated subscription */ }; @@ -173,10 +170,10 @@ struct tipc_event { #define SOL_TIPC 271 #endif -#define TIPC_ADDR_NAMESEQ 1 -#define TIPC_ADDR_MCAST 1 -#define TIPC_ADDR_NAME 2 -#define TIPC_ADDR_ID 3 +#define TIPC_ADDR_NAMESEQ 1 +#define TIPC_ADDR_MCAST 1 +#define TIPC_ADDR_NAME 2 +#define TIPC_ADDR_ID 3 struct sockaddr_tipc { unsigned short family; @@ -207,391 +204,6 @@ struct sockaddr_tipc { #define TIPC_IMPORTANCE 127 /* Default: TIPC_LOW_IMPORTANCE */ #define TIPC_SRC_DROPPABLE 128 /* Default: 0 (resend congested msg) */ #define TIPC_DEST_DROPPABLE 129 /* Default: based on socket type */ -#define TIPC_CONN_TIMEOUT 130 /* Default: 8000 (ms) */ - -/* - * Bearer - */ - -/* Identifiers of supported TIPC media types */ - -#define TIPC_MEDIA_TYPE_ETH 1 - -/* Maximum sizes of TIPC bearer-related names (including terminating NUL) */ - -#define TIPC_MAX_MEDIA_NAME 16 /* format = media */ -#define TIPC_MAX_IF_NAME 16 /* format = interface */ -#define TIPC_MAX_BEARER_NAME 32 /* format = media:interface */ -#define TIPC_MAX_LINK_NAME 60 /* format = Z.C.N:interface-Z.C.N:interface */ - -struct tipc_media_addr { - __u32 type; - union { - __u8 eth_addr[6]; /* Ethernet bearer */ -#if 0 - /* Prototypes for other possible bearer types */ - - struct { - __u16 sin_family; - __u16 sin_port; - struct { - __u32 s_addr; - } sin_addr; - char pad[4]; - } addr_in; /* IP-based bearer */ - __u16 sock_descr; /* generic socket bearer */ -#endif - } dev_addr; -}; - - -/* Link priority limits (range from 0 to # priorities - 1) */ - -#define TIPC_NUM_LINK_PRI 32 - -/* Link tolerance limits (min, default, max), in ms */ - -#define TIPC_MIN_LINK_TOL 50 -#define TIPC_DEF_LINK_TOL 1500 -#define TIPC_MAX_LINK_TOL 30000 - -/* Link window limits (min, default, max), in packets */ - -#define TIPC_MIN_LINK_WIN 16 -#define TIPC_DEF_LINK_WIN 50 -#define TIPC_MAX_LINK_WIN 150 - -/* - * Configuration - * - * All configuration management messaging involves sending a request message - * to the TIPC configuration service on a node, which sends a reply message - * back. (In the future multi-message replies may be supported.) - * - * Both request and reply messages consist of a transport header and payload. - * The transport header contains info about the desired operation; - * the payload consists of zero or more type/length/value (TLV) items - * which specify parameters or results for the operation. - * - * For many operations, the request and reply messages have a fixed number - * of TLVs (usually zero or one); however, some reply messages may return - * a variable number of TLVs. A failed request is denoted by the presence - * of an "error string" TLV in the reply message instead of the TLV(s) the - * reply should contain if the request succeeds. - */ - -#define TIPC_CFG_SRV 0 /* configuration service name type */ - -/* - * Public commands: - * May be issued by any process. - * Accepted by own node, or by remote node only if remote management enabled. - */ - -#define TIPC_CMD_NOOP 0x0000 /* tx none, rx none */ -#define TIPC_CMD_GET_NODES 0x0001 /* tx net_addr, rx node_info(s) */ -#define TIPC_CMD_GET_MEDIA_NAMES 0x0002 /* tx none, rx media_name(s) */ -#define TIPC_CMD_GET_BEARER_NAMES 0x0003 /* tx none, rx bearer_name(s) */ -#define TIPC_CMD_GET_LINKS 0x0004 /* tx net_addr, rx link_info(s) */ -#define TIPC_CMD_SHOW_NAME_TABLE 0x0005 /* tx name_tbl_query, rx ultra_string */ -#define TIPC_CMD_SHOW_PORTS 0x0006 /* tx none, rx ultra_string */ -#define TIPC_CMD_SHOW_LINK_STATS 0x000B /* tx link_name, rx ultra_string */ - -#if 0 -#define TIPC_CMD_SHOW_PORT_STATS 0x0008 /* tx port_ref, rx ultra_string */ -#define TIPC_CMD_RESET_PORT_STATS 0x0009 /* tx port_ref, rx none */ -#define TIPC_CMD_GET_ROUTES 0x000A /* tx ?, rx ? */ -#define TIPC_CMD_GET_LINK_PEER 0x000D /* tx link_name, rx ? */ -#endif - -/* - * Protected commands: - * May only be issued by "network administration capable" process. - * Accepted by own node, or by remote node only if remote management enabled - * and this node is zone manager. - */ - -#define TIPC_CMD_GET_REMOTE_MNG 0x4003 /* tx none, rx unsigned */ -#define TIPC_CMD_GET_MAX_PORTS 0x4004 /* tx none, rx unsigned */ -#define TIPC_CMD_GET_MAX_PUBL 0x4005 /* tx none, rx unsigned */ -#define TIPC_CMD_GET_MAX_SUBSCR 0x4006 /* tx none, rx unsigned */ -#define TIPC_CMD_GET_MAX_ZONES 0x4007 /* tx none, rx unsigned */ -#define TIPC_CMD_GET_MAX_CLUSTERS 0x4008 /* tx none, rx unsigned */ -#define TIPC_CMD_GET_MAX_NODES 0x4009 /* tx none, rx unsigned */ -#define TIPC_CMD_GET_MAX_SLAVES 0x400A /* tx none, rx unsigned */ -#define TIPC_CMD_GET_NETID 0x400B /* tx none, rx unsigned */ - -#define TIPC_CMD_ENABLE_BEARER 0x4101 /* tx bearer_config, rx none */ -#define TIPC_CMD_DISABLE_BEARER 0x4102 /* tx bearer_name, rx none */ -#define TIPC_CMD_SET_LINK_TOL 0x4107 /* tx link_config, rx none */ -#define TIPC_CMD_SET_LINK_PRI 0x4108 /* tx link_config, rx none */ -#define TIPC_CMD_SET_LINK_WINDOW 0x4109 /* tx link_config, rx none */ -#define TIPC_CMD_SET_LOG_SIZE 0x410A /* tx unsigned, rx none */ -#define TIPC_CMD_DUMP_LOG 0x410B /* tx none, rx ultra_string */ -#define TIPC_CMD_RESET_LINK_STATS 0x410C /* tx link_name, rx none */ - -#if 0 -#define TIPC_CMD_CREATE_LINK 0x4103 /* tx link_create, rx none */ -#define TIPC_CMD_REMOVE_LINK 0x4104 /* tx link_name, rx none */ -#define TIPC_CMD_BLOCK_LINK 0x4105 /* tx link_name, rx none */ -#define TIPC_CMD_UNBLOCK_LINK 0x4106 /* tx link_name, rx none */ -#endif - -/* - * Private commands: - * May only be issued by "network administration capable" process. - * Accepted by own node only; cannot be used on a remote node. - */ - -#define TIPC_CMD_SET_NODE_ADDR 0x8001 /* tx net_addr, rx none */ -#if 0 -#define TIPC_CMD_SET_ZONE_MASTER 0x8002 /* tx none, rx none */ -#endif -#define TIPC_CMD_SET_REMOTE_MNG 0x8003 /* tx unsigned, rx none */ -#define TIPC_CMD_SET_MAX_PORTS 0x8004 /* tx unsigned, rx none */ -#define TIPC_CMD_SET_MAX_PUBL 0x8005 /* tx unsigned, rx none */ -#define TIPC_CMD_SET_MAX_SUBSCR 0x8006 /* tx unsigned, rx none */ -#define TIPC_CMD_SET_MAX_ZONES 0x8007 /* tx unsigned, rx none */ -#define TIPC_CMD_SET_MAX_CLUSTERS 0x8008 /* tx unsigned, rx none */ -#define TIPC_CMD_SET_MAX_NODES 0x8009 /* tx unsigned, rx none */ -#define TIPC_CMD_SET_MAX_SLAVES 0x800A /* tx unsigned, rx none */ -#define TIPC_CMD_SET_NETID 0x800B /* tx unsigned, rx none */ - -/* - * TLV types defined for TIPC - */ - -#define TIPC_TLV_NONE 0 /* no TLV present */ -#define TIPC_TLV_VOID 1 /* empty TLV (0 data bytes)*/ -#define TIPC_TLV_UNSIGNED 2 /* 32-bit integer */ -#define TIPC_TLV_STRING 3 /* char[128] (max) */ -#define TIPC_TLV_LARGE_STRING 4 /* char[2048] (max) */ -#define TIPC_TLV_ULTRA_STRING 5 /* char[32768] (max) */ - -#define TIPC_TLV_ERROR_STRING 16 /* char[128] containing "error code" */ -#define TIPC_TLV_NET_ADDR 17 /* 32-bit integer denoting */ -#define TIPC_TLV_MEDIA_NAME 18 /* char[MAX_MEDIA_NAME] */ -#define TIPC_TLV_BEARER_NAME 19 /* char[MAX_BEARER_NAME] */ -#define TIPC_TLV_LINK_NAME 20 /* char[MAX_LINK_NAME] */ -#define TIPC_TLV_NODE_INFO 21 /* struct tipc_node_info */ -#define TIPC_TLV_LINK_INFO 22 /* struct tipc_link_info */ -#define TIPC_TLV_BEARER_CONFIG 23 /* struct tipc_bearer_config */ -#define TIPC_TLV_LINK_CONFIG 24 /* struct tipc_link_config */ -#define TIPC_TLV_NAME_TBL_QUERY 25 /* struct tipc_name_table_query */ -#define TIPC_TLV_PORT_REF 26 /* 32-bit port reference */ - -struct tipc_node_info { - __u32 addr; /* network address of node */ - __u32 up; /* 0=down, 1= up */ -}; - -struct tipc_link_info { - __u32 dest; /* network address of peer node */ - __u32 up; /* 0=down, 1=up */ - char str[TIPC_MAX_LINK_NAME]; /* link name */ -}; - -struct tipc_bearer_config { - __u32 priority; /* Range [1,31]. Override per link */ - __u32 detect_scope; - char name[TIPC_MAX_BEARER_NAME]; -}; - -struct tipc_link_config { - __u32 value; - char name[TIPC_MAX_LINK_NAME]; -}; - -#define TIPC_NTQ_ALLTYPES 0x80000000 - -struct tipc_name_table_query { - __u32 depth; /* 1:type, 2:+name info, 3:+port info, 4+:+debug info */ - __u32 type; /* {t,l,u} info ignored if high bit of "depth" is set */ - __u32 lowbound; /* (i.e. displays all entries of name table) */ - __u32 upbound; -}; - -/* - * The error string TLV is a null-terminated string describing the cause - * of the request failure. To simplify error processing (and to save space) - * the first character of the string can be a special error code character - * (lying by the range 0x80 to 0xFF) which represents a pre-defined reason. - */ - -#define TIPC_CFG_TLV_ERROR "\x80" /* request contains incorrect TLV(s) */ -#define TIPC_CFG_NOT_NET_ADMIN "\x81" /* must be network administrator */ -#define TIPC_CFG_NOT_ZONE_MSTR "\x82" /* must be zone master */ -#define TIPC_CFG_NO_REMOTE "\x83" /* remote management not enabled */ -#define TIPC_CFG_NOT_SUPPORTED "\x84" /* request is not supported by TIPC */ -#define TIPC_CFG_INVALID_VALUE "\x85" /* request has invalid argument value */ - -#if 0 -/* prototypes TLV structures for proposed commands */ -struct tipc_link_create { - __u32 domain; - struct tipc_media_addr peer_addr; - char bearer_name[MAX_BEARER_NAME]; -}; - -struct tipc_route_info { - __u32 dest; - __u32 router; -}; -#endif - -/* - * A TLV consists of a descriptor, followed by the TLV value. - * TLV descriptor fields are stored in network byte order; - * TLV values must also be stored in network byte order (where applicable). - * TLV descriptors must be aligned to addresses which are multiple of 4, - * so up to 3 bytes of padding may exist at the end of the TLV value area. - * There must not be any padding between the TLV descriptor and its value. - */ - -struct tlv_desc { - __u16 tlv_len; /* TLV length (descriptor + value) */ - __u16 tlv_type; /* TLV identifier */ -}; - -#define TLV_ALIGNTO 4 - -#define TLV_ALIGN(datalen) (((datalen)+(TLV_ALIGNTO-1)) & ~(TLV_ALIGNTO-1)) -#define TLV_LENGTH(datalen) (sizeof(struct tlv_desc) + (datalen)) -#define TLV_SPACE(datalen) (TLV_ALIGN(TLV_LENGTH(datalen))) -#define TLV_DATA(tlv) ((void *)((char *)(tlv) + TLV_LENGTH(0))) - -static inline int TLV_OK(const void *tlv, __u16 space) -{ - /* - * Would also like to check that "tlv" is a multiple of 4, - * but don't know how to do this in a portable way. - * - Tried doing (!(tlv & (TLV_ALIGNTO-1))), but GCC compiler - * won't allow binary "&" with a pointer. - * - Tried casting "tlv" to integer type, but causes warning about size - * mismatch when pointer is bigger than chosen type (int, long, ...). - */ - - return (space >= TLV_SPACE(0)) && - (ntohs(((struct tlv_desc *)tlv)->tlv_len) <= space); -} - -static inline int TLV_CHECK(const void *tlv, __u16 space, __u16 exp_type) -{ - return TLV_OK(tlv, space) && - (ntohs(((struct tlv_desc *)tlv)->tlv_type) == exp_type); -} - -static inline int TLV_SET(void *tlv, __u16 type, void *data, __u16 len) -{ - struct tlv_desc *tlv_ptr; - int tlv_len; - - tlv_len = TLV_LENGTH(len); - tlv_ptr = (struct tlv_desc *)tlv; - tlv_ptr->tlv_type = htons(type); - tlv_ptr->tlv_len = htons(tlv_len); - if (len && data) - memcpy(TLV_DATA(tlv_ptr), data, tlv_len); - return TLV_SPACE(len); -} - -/* - * A TLV list descriptor simplifies processing of messages - * containing multiple TLVs. - */ - -struct tlv_list_desc { - struct tlv_desc *tlv_ptr; /* ptr to current TLV */ - __u32 tlv_space; /* # bytes from curr TLV to list end */ -}; - -static inline void TLV_LIST_INIT(struct tlv_list_desc *list, - void *data, __u32 space) -{ - list->tlv_ptr = (struct tlv_desc *)data; - list->tlv_space = space; -} - -static inline int TLV_LIST_EMPTY(struct tlv_list_desc *list) -{ - return (list->tlv_space == 0); -} - -static inline int TLV_LIST_CHECK(struct tlv_list_desc *list, __u16 exp_type) -{ - return TLV_CHECK(list->tlv_ptr, list->tlv_space, exp_type); -} - -static inline void *TLV_LIST_DATA(struct tlv_list_desc *list) -{ - return TLV_DATA(list->tlv_ptr); -} - -static inline void TLV_LIST_STEP(struct tlv_list_desc *list) -{ - __u16 tlv_space = TLV_ALIGN(ntohs(list->tlv_ptr->tlv_len)); - - list->tlv_ptr = (struct tlv_desc *)((char *)list->tlv_ptr + tlv_space); - list->tlv_space -= tlv_space; -} - -/* - * Configuration messages exchanged via NETLINK_GENERIC use the following - * family id, name, version and command. - */ -#define TIPC_GENL_NAME "TIPC" -#define TIPC_GENL_VERSION 0x1 -#define TIPC_GENL_CMD 0x1 - -/* - * TIPC specific header used in NETLINK_GENERIC requests. - */ -struct tipc_genlmsghdr { - __u32 dest; /* Destination address */ - __u16 cmd; /* Command */ - __u16 reserved; /* Unused */ -}; - -#define TIPC_GENL_HDRLEN NLMSG_ALIGN(sizeof(struct tipc_genlmsghdr)) - -/* - * Configuration messages exchanged via TIPC sockets use the TIPC configuration - * message header, which is defined below. This structure is analogous - * to the Netlink message header, but fields are stored in network byte order - * and no padding is permitted between the header and the message data - * that follows. - */ - -struct tipc_cfg_msg_hdr -{ - __u32 tcm_len; /* Message length (including header) */ - __u16 tcm_type; /* Command type */ - __u16 tcm_flags; /* Additional flags */ - char tcm_reserved[8]; /* Unused */ -}; - -#define TCM_F_REQUEST 0x1 /* Flag: Request message */ -#define TCM_F_MORE 0x2 /* Flag: Message to be continued */ - -#define TCM_ALIGN(datalen) (((datalen)+3) & ~3) -#define TCM_LENGTH(datalen) (sizeof(struct tipc_cfg_msg_hdr) + datalen) -#define TCM_SPACE(datalen) (TCM_ALIGN(TCM_LENGTH(datalen))) -#define TCM_DATA(tcm_hdr) ((void *)((char *)(tcm_hdr) + TCM_LENGTH(0))) - -static inline int TCM_SET(void *msg, __u16 cmd, __u16 flags, - void *data, __u16 data_len) -{ - struct tipc_cfg_msg_hdr *tcm_hdr; - int msg_len; - - msg_len = TCM_LENGTH(data_len); - tcm_hdr = (struct tipc_cfg_msg_hdr *)msg; - tcm_hdr->tcm_len = htonl(msg_len); - tcm_hdr->tcm_type = htons(cmd); - tcm_hdr->tcm_flags = htons(flags); - if (data_len && data) - memcpy(TCM_DATA(msg), data, data_len); - return TCM_SPACE(data_len); -} +#define TIPC_CONN_TIMEOUT 130 /* Default: 8000 (ms) */ #endif diff --git a/include/linux/tipc_config.h b/include/linux/tipc_config.h new file mode 100644 index 00000000000..97ead313882 --- /dev/null +++ b/include/linux/tipc_config.h @@ -0,0 +1,404 @@ +/* + * include/linux/tipc_config.h: Include file for TIPC configuration interface + * + * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2005, Wind River Systems + * Copyright (c) 2005-2006, Ericsson AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUX_TIPC_CONFIG_H_ +#define _LINUX_TIPC_CONFIG_H_ + +#include +#include +#include + +/* + * Configuration + * + * All configuration management messaging involves sending a request message + * to the TIPC configuration service on a node, which sends a reply message + * back. (In the future multi-message replies may be supported.) + * + * Both request and reply messages consist of a transport header and payload. + * The transport header contains info about the desired operation; + * the payload consists of zero or more type/length/value (TLV) items + * which specify parameters or results for the operation. + * + * For many operations, the request and reply messages have a fixed number + * of TLVs (usually zero or one); however, some reply messages may return + * a variable number of TLVs. A failed request is denoted by the presence + * of an "error string" TLV in the reply message instead of the TLV(s) the + * reply should contain if the request succeeds. + */ + +/* + * Public commands: + * May be issued by any process. + * Accepted by own node, or by remote node only if remote management enabled. + */ + +#define TIPC_CMD_NOOP 0x0000 /* tx none, rx none */ +#define TIPC_CMD_GET_NODES 0x0001 /* tx net_addr, rx node_info(s) */ +#define TIPC_CMD_GET_MEDIA_NAMES 0x0002 /* tx none, rx media_name(s) */ +#define TIPC_CMD_GET_BEARER_NAMES 0x0003 /* tx none, rx bearer_name(s) */ +#define TIPC_CMD_GET_LINKS 0x0004 /* tx net_addr, rx link_info(s) */ +#define TIPC_CMD_SHOW_NAME_TABLE 0x0005 /* tx name_tbl_query, rx ultra_string */ +#define TIPC_CMD_SHOW_PORTS 0x0006 /* tx none, rx ultra_string */ +#define TIPC_CMD_SHOW_LINK_STATS 0x000B /* tx link_name, rx ultra_string */ + +#if 0 +#define TIPC_CMD_SHOW_PORT_STATS 0x0008 /* tx port_ref, rx ultra_string */ +#define TIPC_CMD_RESET_PORT_STATS 0x0009 /* tx port_ref, rx none */ +#define TIPC_CMD_GET_ROUTES 0x000A /* tx ?, rx ? */ +#define TIPC_CMD_GET_LINK_PEER 0x000D /* tx link_name, rx ? */ +#endif + +/* + * Protected commands: + * May only be issued by "network administration capable" process. + * Accepted by own node, or by remote node only if remote management enabled + * and this node is zone manager. + */ + +#define TIPC_CMD_GET_REMOTE_MNG 0x4003 /* tx none, rx unsigned */ +#define TIPC_CMD_GET_MAX_PORTS 0x4004 /* tx none, rx unsigned */ +#define TIPC_CMD_GET_MAX_PUBL 0x4005 /* tx none, rx unsigned */ +#define TIPC_CMD_GET_MAX_SUBSCR 0x4006 /* tx none, rx unsigned */ +#define TIPC_CMD_GET_MAX_ZONES 0x4007 /* tx none, rx unsigned */ +#define TIPC_CMD_GET_MAX_CLUSTERS 0x4008 /* tx none, rx unsigned */ +#define TIPC_CMD_GET_MAX_NODES 0x4009 /* tx none, rx unsigned */ +#define TIPC_CMD_GET_MAX_SLAVES 0x400A /* tx none, rx unsigned */ +#define TIPC_CMD_GET_NETID 0x400B /* tx none, rx unsigned */ + +#define TIPC_CMD_ENABLE_BEARER 0x4101 /* tx bearer_config, rx none */ +#define TIPC_CMD_DISABLE_BEARER 0x4102 /* tx bearer_name, rx none */ +#define TIPC_CMD_SET_LINK_TOL 0x4107 /* tx link_config, rx none */ +#define TIPC_CMD_SET_LINK_PRI 0x4108 /* tx link_config, rx none */ +#define TIPC_CMD_SET_LINK_WINDOW 0x4109 /* tx link_config, rx none */ +#define TIPC_CMD_SET_LOG_SIZE 0x410A /* tx unsigned, rx none */ +#define TIPC_CMD_DUMP_LOG 0x410B /* tx none, rx ultra_string */ +#define TIPC_CMD_RESET_LINK_STATS 0x410C /* tx link_name, rx none */ + +#if 0 +#define TIPC_CMD_CREATE_LINK 0x4103 /* tx link_create, rx none */ +#define TIPC_CMD_REMOVE_LINK 0x4104 /* tx link_name, rx none */ +#define TIPC_CMD_BLOCK_LINK 0x4105 /* tx link_name, rx none */ +#define TIPC_CMD_UNBLOCK_LINK 0x4106 /* tx link_name, rx none */ +#endif + +/* + * Private commands: + * May only be issued by "network administration capable" process. + * Accepted by own node only; cannot be used on a remote node. + */ + +#define TIPC_CMD_SET_NODE_ADDR 0x8001 /* tx net_addr, rx none */ +#if 0 +#define TIPC_CMD_SET_ZONE_MASTER 0x8002 /* tx none, rx none */ +#endif +#define TIPC_CMD_SET_REMOTE_MNG 0x8003 /* tx unsigned, rx none */ +#define TIPC_CMD_SET_MAX_PORTS 0x8004 /* tx unsigned, rx none */ +#define TIPC_CMD_SET_MAX_PUBL 0x8005 /* tx unsigned, rx none */ +#define TIPC_CMD_SET_MAX_SUBSCR 0x8006 /* tx unsigned, rx none */ +#define TIPC_CMD_SET_MAX_ZONES 0x8007 /* tx unsigned, rx none */ +#define TIPC_CMD_SET_MAX_CLUSTERS 0x8008 /* tx unsigned, rx none */ +#define TIPC_CMD_SET_MAX_NODES 0x8009 /* tx unsigned, rx none */ +#define TIPC_CMD_SET_MAX_SLAVES 0x800A /* tx unsigned, rx none */ +#define TIPC_CMD_SET_NETID 0x800B /* tx unsigned, rx none */ + +/* + * TLV types defined for TIPC + */ + +#define TIPC_TLV_NONE 0 /* no TLV present */ +#define TIPC_TLV_VOID 1 /* empty TLV (0 data bytes)*/ +#define TIPC_TLV_UNSIGNED 2 /* 32-bit integer */ +#define TIPC_TLV_STRING 3 /* char[128] (max) */ +#define TIPC_TLV_LARGE_STRING 4 /* char[2048] (max) */ +#define TIPC_TLV_ULTRA_STRING 5 /* char[32768] (max) */ + +#define TIPC_TLV_ERROR_STRING 16 /* char[128] containing "error code" */ +#define TIPC_TLV_NET_ADDR 17 /* 32-bit integer denoting */ +#define TIPC_TLV_MEDIA_NAME 18 /* char[TIPC_MAX_MEDIA_NAME] */ +#define TIPC_TLV_BEARER_NAME 19 /* char[TIPC_MAX_BEARER_NAME] */ +#define TIPC_TLV_LINK_NAME 20 /* char[TIPC_MAX_LINK_NAME] */ +#define TIPC_TLV_NODE_INFO 21 /* struct tipc_node_info */ +#define TIPC_TLV_LINK_INFO 22 /* struct tipc_link_info */ +#define TIPC_TLV_BEARER_CONFIG 23 /* struct tipc_bearer_config */ +#define TIPC_TLV_LINK_CONFIG 24 /* struct tipc_link_config */ +#define TIPC_TLV_NAME_TBL_QUERY 25 /* struct tipc_name_table_query */ +#define TIPC_TLV_PORT_REF 26 /* 32-bit port reference */ + +/* + * Maximum sizes of TIPC bearer-related names (including terminating NUL) + */ + +#define TIPC_MAX_MEDIA_NAME 16 /* format = media */ +#define TIPC_MAX_IF_NAME 16 /* format = interface */ +#define TIPC_MAX_BEARER_NAME 32 /* format = media:interface */ +#define TIPC_MAX_LINK_NAME 60 /* format = Z.C.N:interface-Z.C.N:interface */ + +/* + * Link priority limits (range from 0 to # priorities - 1) + */ + +#define TIPC_NUM_LINK_PRI 32 + +/* + * Link tolerance limits (min, default, max), in ms + */ + +#define TIPC_MIN_LINK_TOL 50 +#define TIPC_DEF_LINK_TOL 1500 +#define TIPC_MAX_LINK_TOL 30000 + +/* + * Link window limits (min, default, max), in packets + */ + +#define TIPC_MIN_LINK_WIN 16 +#define TIPC_DEF_LINK_WIN 50 +#define TIPC_MAX_LINK_WIN 150 + + +struct tipc_node_info { + __u32 addr; /* network address of node */ + __u32 up; /* 0=down, 1= up */ +}; + +struct tipc_link_info { + __u32 dest; /* network address of peer node */ + __u32 up; /* 0=down, 1=up */ + char str[TIPC_MAX_LINK_NAME]; /* link name */ +}; + +struct tipc_bearer_config { + __u32 priority; /* Range [1,31]. Override per link */ + __u32 detect_scope; + char name[TIPC_MAX_BEARER_NAME]; +}; + +struct tipc_link_config { + __u32 value; + char name[TIPC_MAX_LINK_NAME]; +}; + +#define TIPC_NTQ_ALLTYPES 0x80000000 + +struct tipc_name_table_query { + __u32 depth; /* 1:type, 2:+name info, 3:+port info, 4+:+debug info */ + __u32 type; /* {t,l,u} info ignored if high bit of "depth" is set */ + __u32 lowbound; /* (i.e. displays all entries of name table) */ + __u32 upbound; +}; + +/* + * The error string TLV is a null-terminated string describing the cause + * of the request failure. To simplify error processing (and to save space) + * the first character of the string can be a special error code character + * (lying by the range 0x80 to 0xFF) which represents a pre-defined reason. + */ + +#define TIPC_CFG_TLV_ERROR "\x80" /* request contains incorrect TLV(s) */ +#define TIPC_CFG_NOT_NET_ADMIN "\x81" /* must be network administrator */ +#define TIPC_CFG_NOT_ZONE_MSTR "\x82" /* must be zone master */ +#define TIPC_CFG_NO_REMOTE "\x83" /* remote management not enabled */ +#define TIPC_CFG_NOT_SUPPORTED "\x84" /* request is not supported by TIPC */ +#define TIPC_CFG_INVALID_VALUE "\x85" /* request has invalid argument value */ + +#if 0 +/* prototypes TLV structures for proposed commands */ +struct tipc_link_create { + __u32 domain; + struct tipc_media_addr peer_addr; + char bearer_name[TIPC_MAX_BEARER_NAME]; +}; + +struct tipc_route_info { + __u32 dest; + __u32 router; +}; +#endif + +/* + * A TLV consists of a descriptor, followed by the TLV value. + * TLV descriptor fields are stored in network byte order; + * TLV values must also be stored in network byte order (where applicable). + * TLV descriptors must be aligned to addresses which are multiple of 4, + * so up to 3 bytes of padding may exist at the end of the TLV value area. + * There must not be any padding between the TLV descriptor and its value. + */ + +struct tlv_desc { + __u16 tlv_len; /* TLV length (descriptor + value) */ + __u16 tlv_type; /* TLV identifier */ +}; + +#define TLV_ALIGNTO 4 + +#define TLV_ALIGN(datalen) (((datalen)+(TLV_ALIGNTO-1)) & ~(TLV_ALIGNTO-1)) +#define TLV_LENGTH(datalen) (sizeof(struct tlv_desc) + (datalen)) +#define TLV_SPACE(datalen) (TLV_ALIGN(TLV_LENGTH(datalen))) +#define TLV_DATA(tlv) ((void *)((char *)(tlv) + TLV_LENGTH(0))) + +static inline int TLV_OK(const void *tlv, __u16 space) +{ + /* + * Would also like to check that "tlv" is a multiple of 4, + * but don't know how to do this in a portable way. + * - Tried doing (!(tlv & (TLV_ALIGNTO-1))), but GCC compiler + * won't allow binary "&" with a pointer. + * - Tried casting "tlv" to integer type, but causes warning about size + * mismatch when pointer is bigger than chosen type (int, long, ...). + */ + + return (space >= TLV_SPACE(0)) && + (ntohs(((struct tlv_desc *)tlv)->tlv_len) <= space); +} + +static inline int TLV_CHECK(const void *tlv, __u16 space, __u16 exp_type) +{ + return TLV_OK(tlv, space) && + (ntohs(((struct tlv_desc *)tlv)->tlv_type) == exp_type); +} + +static inline int TLV_SET(void *tlv, __u16 type, void *data, __u16 len) +{ + struct tlv_desc *tlv_ptr; + int tlv_len; + + tlv_len = TLV_LENGTH(len); + tlv_ptr = (struct tlv_desc *)tlv; + tlv_ptr->tlv_type = htons(type); + tlv_ptr->tlv_len = htons(tlv_len); + if (len && data) + memcpy(TLV_DATA(tlv_ptr), data, tlv_len); + return TLV_SPACE(len); +} + +/* + * A TLV list descriptor simplifies processing of messages + * containing multiple TLVs. + */ + +struct tlv_list_desc { + struct tlv_desc *tlv_ptr; /* ptr to current TLV */ + __u32 tlv_space; /* # bytes from curr TLV to list end */ +}; + +static inline void TLV_LIST_INIT(struct tlv_list_desc *list, + void *data, __u32 space) +{ + list->tlv_ptr = (struct tlv_desc *)data; + list->tlv_space = space; +} + +static inline int TLV_LIST_EMPTY(struct tlv_list_desc *list) +{ + return (list->tlv_space == 0); +} + +static inline int TLV_LIST_CHECK(struct tlv_list_desc *list, __u16 exp_type) +{ + return TLV_CHECK(list->tlv_ptr, list->tlv_space, exp_type); +} + +static inline void *TLV_LIST_DATA(struct tlv_list_desc *list) +{ + return TLV_DATA(list->tlv_ptr); +} + +static inline void TLV_LIST_STEP(struct tlv_list_desc *list) +{ + __u16 tlv_space = TLV_ALIGN(ntohs(list->tlv_ptr->tlv_len)); + + list->tlv_ptr = (struct tlv_desc *)((char *)list->tlv_ptr + tlv_space); + list->tlv_space -= tlv_space; +} + +/* + * Configuration messages exchanged via NETLINK_GENERIC use the following + * family id, name, version and command. + */ +#define TIPC_GENL_NAME "TIPC" +#define TIPC_GENL_VERSION 0x1 +#define TIPC_GENL_CMD 0x1 + +/* + * TIPC specific header used in NETLINK_GENERIC requests. + */ +struct tipc_genlmsghdr { + __u32 dest; /* Destination address */ + __u16 cmd; /* Command */ + __u16 reserved; /* Unused */ +}; + +#define TIPC_GENL_HDRLEN NLMSG_ALIGN(sizeof(struct tipc_genlmsghdr)) + +/* + * Configuration messages exchanged via TIPC sockets use the TIPC configuration + * message header, which is defined below. This structure is analogous + * to the Netlink message header, but fields are stored in network byte order + * and no padding is permitted between the header and the message data + * that follows. + */ + +struct tipc_cfg_msg_hdr +{ + __u32 tcm_len; /* Message length (including header) */ + __u16 tcm_type; /* Command type */ + __u16 tcm_flags; /* Additional flags */ + char tcm_reserved[8]; /* Unused */ +}; + +#define TCM_F_REQUEST 0x1 /* Flag: Request message */ +#define TCM_F_MORE 0x2 /* Flag: Message to be continued */ + +#define TCM_ALIGN(datalen) (((datalen)+3) & ~3) +#define TCM_LENGTH(datalen) (sizeof(struct tipc_cfg_msg_hdr) + datalen) +#define TCM_SPACE(datalen) (TCM_ALIGN(TCM_LENGTH(datalen))) +#define TCM_DATA(tcm_hdr) ((void *)((char *)(tcm_hdr) + TCM_LENGTH(0))) + +static inline int TCM_SET(void *msg, __u16 cmd, __u16 flags, + void *data, __u16 data_len) +{ + struct tipc_cfg_msg_hdr *tcm_hdr; + int msg_len; + + msg_len = TCM_LENGTH(data_len); + tcm_hdr = (struct tipc_cfg_msg_hdr *)msg; + tcm_hdr->tcm_len = htonl(msg_len); + tcm_hdr->tcm_type = htons(cmd); + tcm_hdr->tcm_flags = htons(flags); + if (data_len && data) + memcpy(TCM_DATA(msg), data, data_len); + return TCM_SPACE(data_len); +} + +#endif diff --git a/include/net/tipc/tipc_bearer.h b/include/net/tipc/tipc_bearer.h index a3daf697b6b..df7b9145a59 100644 --- a/include/net/tipc/tipc_bearer.h +++ b/include/net/tipc/tipc_bearer.h @@ -36,10 +36,36 @@ #ifdef __KERNEL__ -#include +#include #include #include +/* + * Identifiers of supported TIPC media types + */ + +#define TIPC_MEDIA_TYPE_ETH 1 + +struct tipc_media_addr { + __u32 type; + union { + __u8 eth_addr[6]; /* Ethernet bearer */ +#if 0 + /* Prototypes for other possible bearer types */ + + struct { + __u16 sin_family; + __u16 sin_port; + struct { + __u32 s_addr; + } sin_addr; + char pad[4]; + } addr_in; /* IP-based bearer */ + __u16 sock_descr; /* generic socket bearer */ +#endif + } dev_addr; +}; + /** * struct tipc_bearer - TIPC bearer info available to privileged users * @usr_handle: pointer to additional user-defined information about bearer diff --git a/net/tipc/config.h b/net/tipc/config.h index 7ac0af57bf5..ca76cb85a3b 100644 --- a/net/tipc/config.h +++ b/net/tipc/config.h @@ -37,6 +37,7 @@ /* ---------------------------------------------------------------------- */ #include +#include #include "link.h" struct sk_buff *cfg_reply_alloc(int payload_size); diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 22dcb724e76..688de0bf72d 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -48,6 +48,7 @@ #include #include +#include #include #include -- GitLab From 9ea1fd3c1a15c620d1e3d0aa269d34b705477003 Mon Sep 17 00:00:00 2001 From: Per Liden Date: Wed, 11 Jan 2006 13:30:43 +0100 Subject: [PATCH 042/465] [TIPC] License header update The license header in each file now more clearly state that this code is licensed under a dual BSD/GPL. Before this was only evident if you looked at the MODULE_LICENSE line in core.c. Signed-off-by: Per Liden --- include/linux/tipc.h | 42 +++++++++++++++++++--------------- include/linux/tipc_config.h | 42 +++++++++++++++++++--------------- include/net/tipc/tipc.h | 42 +++++++++++++++++++--------------- include/net/tipc/tipc_bearer.h | 42 +++++++++++++++++++--------------- include/net/tipc/tipc_msg.h | 42 +++++++++++++++++++--------------- include/net/tipc/tipc_port.h | 42 +++++++++++++++++++--------------- net/tipc/addr.c | 42 +++++++++++++++++++--------------- net/tipc/addr.h | 42 +++++++++++++++++++--------------- net/tipc/bcast.c | 42 +++++++++++++++++++--------------- net/tipc/bcast.h | 42 +++++++++++++++++++--------------- net/tipc/bearer.c | 42 +++++++++++++++++++--------------- net/tipc/bearer.h | 42 +++++++++++++++++++--------------- net/tipc/cluster.c | 20 +++++++++------- net/tipc/cluster.h | 42 +++++++++++++++++++--------------- net/tipc/config.c | 42 +++++++++++++++++++--------------- net/tipc/config.h | 42 +++++++++++++++++++--------------- net/tipc/core.c | 42 +++++++++++++++++++--------------- net/tipc/core.h | 42 +++++++++++++++++++--------------- net/tipc/dbg.c | 42 +++++++++++++++++++--------------- net/tipc/dbg.h | 42 +++++++++++++++++++--------------- net/tipc/discover.c | 42 +++++++++++++++++++--------------- net/tipc/discover.h | 42 +++++++++++++++++++--------------- net/tipc/eth_media.c | 42 +++++++++++++++++++--------------- net/tipc/handler.c | 42 +++++++++++++++++++--------------- net/tipc/link.c | 42 +++++++++++++++++++--------------- net/tipc/link.h | 42 +++++++++++++++++++--------------- net/tipc/msg.c | 42 +++++++++++++++++++--------------- net/tipc/msg.h | 42 +++++++++++++++++++--------------- net/tipc/name_distr.c | 42 +++++++++++++++++++--------------- net/tipc/name_distr.h | 42 +++++++++++++++++++--------------- net/tipc/name_table.c | 42 +++++++++++++++++++--------------- net/tipc/name_table.h | 42 +++++++++++++++++++--------------- net/tipc/net.c | 20 +++++++++------- net/tipc/net.h | 22 ++++++++++-------- net/tipc/netlink.c | 42 +++++++++++++++++++--------------- net/tipc/node.c | 42 +++++++++++++++++++--------------- net/tipc/node.h | 42 +++++++++++++++++++--------------- net/tipc/node_subscr.c | 42 +++++++++++++++++++--------------- net/tipc/node_subscr.h | 42 +++++++++++++++++++--------------- net/tipc/port.c | 42 +++++++++++++++++++--------------- net/tipc/port.h | 42 +++++++++++++++++++--------------- net/tipc/ref.c | 22 ++++++++++-------- net/tipc/ref.h | 42 +++++++++++++++++++--------------- net/tipc/socket.c | 42 +++++++++++++++++++--------------- net/tipc/subscr.c | 42 +++++++++++++++++++--------------- net/tipc/subscr.h | 42 +++++++++++++++++++--------------- net/tipc/user_reg.c | 22 ++++++++++-------- net/tipc/user_reg.h | 42 +++++++++++++++++++--------------- net/tipc/zone.c | 20 +++++++++------- net/tipc/zone.h | 20 +++++++++------- 50 files changed, 1076 insertions(+), 876 deletions(-) diff --git a/include/linux/tipc.h b/include/linux/tipc.h index 4ecd0047550..ff109c1c141 100644 --- a/include/linux/tipc.h +++ b/include/linux/tipc.h @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/include/linux/tipc_config.h b/include/linux/tipc_config.h index 97ead313882..6e5a3af0d21 100644 --- a/include/linux/tipc_config.h +++ b/include/linux/tipc_config.h @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/include/net/tipc/tipc.h b/include/net/tipc/tipc.h index 1d4d8d0701e..b763d556355 100644 --- a/include/net/tipc/tipc.h +++ b/include/net/tipc/tipc.h @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/include/net/tipc/tipc_bearer.h b/include/net/tipc/tipc_bearer.h index df7b9145a59..0cfb9bbd9ac 100644 --- a/include/net/tipc/tipc_bearer.h +++ b/include/net/tipc/tipc_bearer.h @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/include/net/tipc/tipc_msg.h b/include/net/tipc/tipc_msg.h index 78513f5236b..a5c7ed598fc 100644 --- a/include/net/tipc/tipc_msg.h +++ b/include/net/tipc/tipc_msg.h @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/include/net/tipc/tipc_port.h b/include/net/tipc/tipc_port.h index ec0f0de7f0e..db947ff1265 100644 --- a/include/net/tipc/tipc_port.h +++ b/include/net/tipc/tipc_port.h @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/addr.c b/net/tipc/addr.c index bc353639562..89a25a2d03b 100644 --- a/net/tipc/addr.c +++ b/net/tipc/addr.c @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/addr.h b/net/tipc/addr.h index 9dabebcba6d..b65a0ab2647 100644 --- a/net/tipc/addr.h +++ b/net/tipc/addr.h @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 35ca90667a5..180d80b37a8 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -7,28 +7,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h index cc2ede15c4f..27d1bba5c94 100644 --- a/net/tipc/bcast.h +++ b/net/tipc/bcast.h @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index c19465c5f03..579b17ded6c 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 02a16f86def..96d4bd9e767 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/cluster.c b/net/tipc/cluster.c index d7d0f5f17e0..4e86b2a6fc7 100644 --- a/net/tipc/cluster.c +++ b/net/tipc/cluster.c @@ -9,14 +9,18 @@ * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/net/tipc/cluster.h b/net/tipc/cluster.h index c12875ab46b..a066b5e518b 100644 --- a/net/tipc/cluster.h +++ b/net/tipc/cluster.h @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/config.c b/net/tipc/config.c index 0f31c342d11..9e55cf8caec 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/config.h b/net/tipc/config.h index ca76cb85a3b..a12c6482c9c 100644 --- a/net/tipc/config.h +++ b/net/tipc/config.h @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/core.c b/net/tipc/core.c index 17c723f4918..6d45d71bdae 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/core.h b/net/tipc/core.h index d92898d6c09..4b29fb63c8f 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/dbg.c b/net/tipc/dbg.c index efd6d652d05..22fa030150f 100644 --- a/net/tipc/dbg.c +++ b/net/tipc/dbg.c @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/dbg.h b/net/tipc/dbg.h index af4217a993c..07a42ba6846 100644 --- a/net/tipc/dbg.h +++ b/net/tipc/dbg.h @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/discover.c b/net/tipc/discover.c index 73e151cf2a5..31e242f39e7 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/discover.h b/net/tipc/discover.h index 90c1de905e7..17c150b18dc 100644 --- a/net/tipc/discover.h +++ b/net/tipc/discover.h @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c index b634d7a5640..8acbef8e93a 100644 --- a/net/tipc/eth_media.c +++ b/net/tipc/eth_media.c @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/handler.c b/net/tipc/handler.c index c8fbb2071df..8f5dcbd4cd3 100644 --- a/net/tipc/handler.c +++ b/net/tipc/handler.c @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/link.c b/net/tipc/link.c index 92acb80bb24..c9261002ea6 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/link.h b/net/tipc/link.h index e7db3476d84..a67868606ef 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/msg.c b/net/tipc/msg.c index c6e90efd59f..acc6e354290 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/msg.h b/net/tipc/msg.h index 3dcd23f5188..6323de97434 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index 5e0604cb3ae..31448272a13 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/name_distr.h b/net/tipc/name_distr.h index 7c6616aecc0..3f9c28d87cc 100644 --- a/net/tipc/name_distr.h +++ b/net/tipc/name_distr.h @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 9626c5b3067..e152d6dddfa 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h index 5036b5bac36..8e3749cf9b7 100644 --- a/net/tipc/name_table.h +++ b/net/tipc/name_table.h @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/net.c b/net/tipc/net.c index eba88033b90..73c6aa8fa1a 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -9,14 +9,18 @@ * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/net/tipc/net.h b/net/tipc/net.h index 50098455a89..97650ff6359 100644 --- a/net/tipc/net.h +++ b/net/tipc/net.h @@ -8,15 +8,19 @@ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index 2d778dfc449..de3eb45a668 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c @@ -5,28 +5,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/node.c b/net/tipc/node.c index e311638b9b3..e86614494c1 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/node.h b/net/tipc/node.h index 1f616873a72..8919c873b0e 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/node_subscr.c b/net/tipc/node_subscr.c index c38a3b0e847..ecdb9821668 100644 --- a/net/tipc/node_subscr.c +++ b/net/tipc/node_subscr.c @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/node_subscr.h b/net/tipc/node_subscr.h index 63ae92e0c82..3d2d8f546ef 100644 --- a/net/tipc/node_subscr.h +++ b/net/tipc/node_subscr.h @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/port.c b/net/tipc/port.c index f0f228c9589..e69e8b42a19 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/port.h b/net/tipc/port.h index e40235ef92f..e10d85a4bf9 100644 --- a/net/tipc/port.h +++ b/net/tipc/port.h @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/ref.c b/net/tipc/ref.c index aee48c797b1..b6f60822ec3 100644 --- a/net/tipc/ref.c +++ b/net/tipc/ref.c @@ -8,15 +8,19 @@ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/net/tipc/ref.h b/net/tipc/ref.h index e6cd5bb3dc2..08ba83fd561 100644 --- a/net/tipc/ref.h +++ b/net/tipc/ref.h @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 688de0bf72d..1120d034031 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 6f651a2c477..9486d8ee98b 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h index e6cb9c3ad87..6b91ca9e241 100644 --- a/net/tipc/subscr.h +++ b/net/tipc/subscr.h @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/user_reg.c b/net/tipc/user_reg.c index e4da5becc34..64165ec4604 100644 --- a/net/tipc/user_reg.c +++ b/net/tipc/user_reg.c @@ -8,15 +8,19 @@ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/net/tipc/user_reg.h b/net/tipc/user_reg.h index 44f219458a3..0f96004ebdc 100644 --- a/net/tipc/user_reg.h +++ b/net/tipc/user_reg.h @@ -6,28 +6,32 @@ * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ diff --git a/net/tipc/zone.c b/net/tipc/zone.c index 336eebb7bf5..b47deecb73f 100644 --- a/net/tipc/zone.c +++ b/net/tipc/zone.c @@ -9,14 +9,18 @@ * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE diff --git a/net/tipc/zone.h b/net/tipc/zone.h index 19fd51a8bd2..e05cc610204 100644 --- a/net/tipc/zone.h +++ b/net/tipc/zone.h @@ -9,14 +9,18 @@ * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -- GitLab From d0a14a9dbdf613d9307c4b748b03a11678fe8d16 Mon Sep 17 00:00:00 2001 From: Per Liden Date: Wed, 11 Jan 2006 13:52:51 +0100 Subject: [PATCH 043/465] [TIPC] Cleaned up info/warn/err macros Signed-off-by: Per Liden --- net/tipc/core.h | 6 +++--- net/tipc/netlink.c | 2 +- net/tipc/socket.c | 4 ++-- net/tipc/subscr.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/net/tipc/core.h b/net/tipc/core.h index 4b29fb63c8f..4f71fde023e 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -117,9 +117,9 @@ void tipc_dump(struct print_buf*,const char *fmt, ...); * - debug messages are not printed */ -#define err(fmt, arg...) printk(KERN_ERR "%s: " fmt "\n" , __FILE__ , ## arg) -#define info(fmt, arg...) printk(KERN_INFO "%s: " fmt "\n" , __FILE__ , ## arg) -#define warn(fmt, arg...) printk(KERN_WARNING "%s: " fmt "\n" , __FILE__ , ## arg) +#define err(fmt, arg...) printk(KERN_ERR "TIPC: " fmt , ## arg) +#define info(fmt, arg...) printk(KERN_INFO "TIPC: " fmt , ## arg) +#define warn(fmt, arg...) printk(KERN_WARNING "TIPC: " fmt , ## arg) #define dbg(fmt, arg...) do {} while (0) #define msg_dbg(msg,txt) do {} while (0) diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index de3eb45a668..7b963833964 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c @@ -100,7 +100,7 @@ int netlink_start(void) genl_unregister_family(&family); family_registered = 0; err: - err("Failed to register netlink interface"); + err("Failed to register netlink interface\n"); return -EFAULT; } diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 1120d034031..e0b429c20ba 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -1696,13 +1696,13 @@ int socket_init(void) res = proto_register(&tipc_proto, 1); if (res) { - err("Unable to register TIPC protocol type\n"); + err("Failed to register TIPC protocol type\n"); goto out; } res = sock_register(&tipc_family_ops); if (res) { - err("Unable to register TIPC socket type\n"); + err("Failed to register TIPC socket type\n"); proto_unregister(&tipc_proto); goto out; } diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 9486d8ee98b..b52959fca5e 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -488,7 +488,7 @@ int subscr_start(void) return 0; failed: - err("Unable to create subscription service\n"); + err("Failed to create subscription service\n"); tipc_detach(topsrv.user_ref); topsrv.user_ref = 0; spin_unlock_bh(&topsrv.lock); -- GitLab From 9da1c8b694f8e72a16f259614caaae50cbcdaf10 Mon Sep 17 00:00:00 2001 From: Per Liden Date: Wed, 11 Jan 2006 18:40:41 +0100 Subject: [PATCH 044/465] [TIPC] Update of file headers The copyright statements from different parts of Ericsson have been merged into one. Signed-off-by: Per Liden --- include/linux/tipc.h | 3 +-- include/linux/tipc_config.h | 3 +-- include/net/tipc/tipc.h | 3 +-- include/net/tipc/tipc_bearer.h | 3 +-- include/net/tipc/tipc_msg.h | 3 +-- include/net/tipc/tipc_port.h | 3 +-- net/tipc/addr.c | 3 +-- net/tipc/addr.h | 3 +-- net/tipc/bcast.c | 3 +-- net/tipc/bcast.h | 3 +-- net/tipc/bearer.c | 3 +-- net/tipc/bearer.h | 3 +-- net/tipc/cluster.c | 3 +-- net/tipc/cluster.h | 3 +-- net/tipc/config.c | 3 +-- net/tipc/config.h | 3 +-- net/tipc/core.c | 3 +-- net/tipc/core.h | 3 +-- net/tipc/dbg.c | 3 +-- net/tipc/dbg.h | 3 +-- net/tipc/discover.c | 3 +-- net/tipc/discover.h | 3 +-- net/tipc/eth_media.c | 3 +-- net/tipc/handler.c | 3 +-- net/tipc/link.c | 3 +-- net/tipc/link.h | 3 +-- net/tipc/msg.c | 3 +-- net/tipc/msg.h | 3 +-- net/tipc/name_distr.c | 3 +-- net/tipc/name_distr.h | 3 +-- net/tipc/name_table.c | 3 +-- net/tipc/name_table.h | 3 +-- net/tipc/net.c | 3 +-- net/tipc/net.h | 3 +-- net/tipc/netlink.c | 1 - net/tipc/node.c | 3 +-- net/tipc/node.h | 3 +-- net/tipc/node_subscr.c | 3 +-- net/tipc/node_subscr.h | 3 +-- net/tipc/port.c | 3 +-- net/tipc/port.h | 3 +-- net/tipc/ref.c | 3 +-- net/tipc/ref.h | 3 +-- net/tipc/socket.c | 3 +-- net/tipc/subscr.c | 3 +-- net/tipc/subscr.h | 3 +-- net/tipc/user_reg.c | 3 +-- net/tipc/user_reg.h | 3 +-- net/tipc/zone.c | 3 +-- net/tipc/zone.h | 3 +-- 50 files changed, 49 insertions(+), 99 deletions(-) diff --git a/include/linux/tipc.h b/include/linux/tipc.h index ff109c1c141..243a15f5400 100644 --- a/include/linux/tipc.h +++ b/include/linux/tipc.h @@ -1,9 +1,8 @@ /* * include/linux/tipc.h: Include file for TIPC socket interface * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/linux/tipc_config.h b/include/linux/tipc_config.h index 6e5a3af0d21..a52c8c64a5a 100644 --- a/include/linux/tipc_config.h +++ b/include/linux/tipc_config.h @@ -1,9 +1,8 @@ /* * include/linux/tipc_config.h: Include file for TIPC configuration interface * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/net/tipc/tipc.h b/include/net/tipc/tipc.h index b763d556355..560a329660f 100644 --- a/include/net/tipc/tipc.h +++ b/include/net/tipc/tipc.h @@ -1,9 +1,8 @@ /* * include/net/tipc/tipc.h: Main include file for TIPC users * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/net/tipc/tipc_bearer.h b/include/net/tipc/tipc_bearer.h index 0cfb9bbd9ac..098607cd4b7 100644 --- a/include/net/tipc/tipc_bearer.h +++ b/include/net/tipc/tipc_bearer.h @@ -1,9 +1,8 @@ /* * include/net/tipc/tipc_bearer.h: Include file for privileged access to TIPC bearers * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/net/tipc/tipc_msg.h b/include/net/tipc/tipc_msg.h index a5c7ed598fc..4d096eebc93 100644 --- a/include/net/tipc/tipc_msg.h +++ b/include/net/tipc/tipc_msg.h @@ -1,9 +1,8 @@ /* * include/net/tipc/tipc_msg.h: Include file for privileged access to TIPC message headers * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/net/tipc/tipc_port.h b/include/net/tipc/tipc_port.h index db947ff1265..3f602744164 100644 --- a/include/net/tipc/tipc_port.h +++ b/include/net/tipc/tipc_port.h @@ -1,9 +1,8 @@ /* * include/net/tipc/tipc_port.h: Include file for privileged access to TIPC ports * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/addr.c b/net/tipc/addr.c index 89a25a2d03b..6d5709deee6 100644 --- a/net/tipc/addr.c +++ b/net/tipc/addr.c @@ -1,9 +1,8 @@ /* * net/tipc/addr.c: TIPC address utility routines * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2004-2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/addr.h b/net/tipc/addr.h index b65a0ab2647..cdf95486043 100644 --- a/net/tipc/addr.h +++ b/net/tipc/addr.h @@ -1,9 +1,8 @@ /* * net/tipc/addr.h: Include file for TIPC address utility routines * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2004-2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 180d80b37a8..d7d06f29f19 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -1,10 +1,9 @@ /* * net/tipc/bcast.c: TIPC broadcast code * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2004, Intel Corporation. * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h index 27d1bba5c94..5430e524b4f 100644 --- a/net/tipc/bcast.h +++ b/net/tipc/bcast.h @@ -1,9 +1,8 @@ /* * net/tipc/bcast.h: Include file for TIPC broadcast code * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 579b17ded6c..9c8ab26301d 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -1,9 +1,8 @@ /* * net/tipc/bearer.c: TIPC bearer code * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2004-2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 96d4bd9e767..55197ccf1a1 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h @@ -1,9 +1,8 @@ /* * net/tipc/bearer.h: Include file for TIPC bearer code * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/cluster.c b/net/tipc/cluster.c index 4e86b2a6fc7..7c31f690c38 100644 --- a/net/tipc/cluster.c +++ b/net/tipc/cluster.c @@ -1,9 +1,8 @@ /* * net/tipc/cluster.c: TIPC cluster management routines * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/cluster.h b/net/tipc/cluster.h index a066b5e518b..a9a46fa4fc2 100644 --- a/net/tipc/cluster.h +++ b/net/tipc/cluster.h @@ -1,9 +1,8 @@ /* * net/tipc/cluster.h: Include file for TIPC cluster management routines * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/config.c b/net/tipc/config.c index 9e55cf8caec..6c45771bd99 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -1,9 +1,8 @@ /* * net/tipc/config.c: TIPC configuration management code * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2004-2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/config.h b/net/tipc/config.h index a12c6482c9c..646377d4045 100644 --- a/net/tipc/config.h +++ b/net/tipc/config.h @@ -1,9 +1,8 @@ /* * net/tipc/config.h: Include file for TIPC configuration service code * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/core.c b/net/tipc/core.c index 6d45d71bdae..e83ac06e31b 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -1,9 +1,8 @@ /* * net/tipc/core.c: TIPC module code * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/core.h b/net/tipc/core.h index 4f71fde023e..deee5de5fb3 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -1,9 +1,8 @@ /* * net/tipc/core.h: Include file for TIPC global declarations * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/dbg.c b/net/tipc/dbg.c index 22fa030150f..3264ccb7448 100644 --- a/net/tipc/dbg.c +++ b/net/tipc/dbg.c @@ -1,9 +1,8 @@ /* * net/tipc/dbg.c: TIPC print buffer routines for debuggign * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/dbg.h b/net/tipc/dbg.h index 07a42ba6846..264c741f95b 100644 --- a/net/tipc/dbg.h +++ b/net/tipc/dbg.h @@ -1,9 +1,8 @@ /* * net/tipc/dbg.h: Include file for TIPC print buffer routines * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/discover.c b/net/tipc/discover.c index 31e242f39e7..b106ef1621c 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c @@ -1,9 +1,8 @@ /* * net/tipc/discover.c * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/discover.h b/net/tipc/discover.h index 17c150b18dc..2a6114d9162 100644 --- a/net/tipc/discover.h +++ b/net/tipc/discover.h @@ -1,9 +1,8 @@ /* * net/tipc/discover.h * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c index 8acbef8e93a..fe0a4286e48 100644 --- a/net/tipc/eth_media.c +++ b/net/tipc/eth_media.c @@ -1,9 +1,8 @@ /* * net/tipc/eth_media.c: Ethernet bearer support for TIPC * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/handler.c b/net/tipc/handler.c index 8f5dcbd4cd3..cab6f615046 100644 --- a/net/tipc/handler.c +++ b/net/tipc/handler.c @@ -1,9 +1,8 @@ /* * net/tipc/handler.c: TIPC signal handling * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/link.c b/net/tipc/link.c index c9261002ea6..48d0483297e 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1,9 +1,8 @@ /* * net/tipc/link.c: TIPC link code * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2004-2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/link.h b/net/tipc/link.h index a67868606ef..686eb7d684e 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h @@ -1,9 +1,8 @@ /* * net/tipc/link.h: Include file for TIPC link code * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2004-2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/msg.c b/net/tipc/msg.c index acc6e354290..4ffbb9d4442 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c @@ -1,9 +1,8 @@ /* * net/tipc/msg.c: TIPC message header routines * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/msg.h b/net/tipc/msg.h index 6323de97434..71e272face6 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h @@ -1,9 +1,8 @@ /* * net/tipc/msg.h: Include file for TIPC message header routines * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index 31448272a13..93ac2b25220 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c @@ -1,9 +1,8 @@ /* * net/tipc/name_distr.c: TIPC name distribution code * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/name_distr.h b/net/tipc/name_distr.h index 3f9c28d87cc..41c1b1c065d 100644 --- a/net/tipc/name_distr.h +++ b/net/tipc/name_distr.h @@ -1,9 +1,8 @@ /* * net/tipc/name_distr.h: Include file for TIPC name distribution code * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index e152d6dddfa..8568df3cc6b 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c @@ -1,9 +1,8 @@ /* * net/tipc/name_table.c: TIPC name table code * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2004-2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h index 8e3749cf9b7..c771b093e12 100644 --- a/net/tipc/name_table.h +++ b/net/tipc/name_table.h @@ -1,9 +1,8 @@ /* * net/tipc/name_table.h: Include file for TIPC name table code * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2004-2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/net.c b/net/tipc/net.c index 73c6aa8fa1a..a6989946e23 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -1,9 +1,8 @@ /* * net/tipc/net.c: TIPC network routing code * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/net.h b/net/tipc/net.h index 97650ff6359..6f0758e894c 100644 --- a/net/tipc/net.h +++ b/net/tipc/net.h @@ -1,9 +1,8 @@ /* * net/tipc/net.h: Include file for TIPC network routing code * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index 7b963833964..c19c2fa2ce5 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c @@ -2,7 +2,6 @@ * net/tipc/netlink.c: TIPC configuration handling * * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/node.c b/net/tipc/node.c index e86614494c1..565c35b54c0 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -1,9 +1,8 @@ /* * net/tipc/node.c: TIPC node management routines * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/node.h b/net/tipc/node.h index 8919c873b0e..26c04ba2d49 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h @@ -1,9 +1,8 @@ /* * net/tipc/node.h: Include file for TIPC node management routines * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/node_subscr.c b/net/tipc/node_subscr.c index ecdb9821668..f271b61ecc2 100644 --- a/net/tipc/node_subscr.c +++ b/net/tipc/node_subscr.c @@ -1,9 +1,8 @@ /* * net/tipc/node_subscr.c: TIPC "node down" subscription handling * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/node_subscr.h b/net/tipc/node_subscr.h index 3d2d8f546ef..3145339b55b 100644 --- a/net/tipc/node_subscr.h +++ b/net/tipc/node_subscr.h @@ -1,9 +1,8 @@ /* * net/tipc/node_subscr.h: Include file for TIPC "node down" subscription handling * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/port.c b/net/tipc/port.c index e69e8b42a19..ea45b17b045 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -1,9 +1,8 @@ /* * net/tipc/port.c: TIPC port code * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2004-2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/port.h b/net/tipc/port.h index e10d85a4bf9..c15f687bd69 100644 --- a/net/tipc/port.h +++ b/net/tipc/port.h @@ -1,9 +1,8 @@ /* * net/tipc/port.h: Include file for TIPC port code * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2004-2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/ref.c b/net/tipc/ref.c index b6f60822ec3..eb5f2b2799d 100644 --- a/net/tipc/ref.c +++ b/net/tipc/ref.c @@ -1,9 +1,8 @@ /* * net/tipc/ref.c: TIPC object registry code * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2004-2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/ref.h b/net/tipc/ref.h index 08ba83fd561..12dd827be30 100644 --- a/net/tipc/ref.h +++ b/net/tipc/ref.h @@ -1,9 +1,8 @@ /* * net/tipc/ref.h: Include file for TIPC object registry code * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/socket.c b/net/tipc/socket.c index e0b429c20ba..cb90d8a9988 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -1,9 +1,8 @@ /* * net/tipc/socket.c: TIPC socket API * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2004-2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index b52959fca5e..728f9f073a5 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -1,9 +1,8 @@ /* * net/tipc/subscr.c: TIPC subscription service * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h index 6b91ca9e241..ccff4efcb75 100644 --- a/net/tipc/subscr.h +++ b/net/tipc/subscr.h @@ -1,9 +1,8 @@ /* * net/tipc/subscr.h: Include file for TIPC subscription service * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/user_reg.c b/net/tipc/user_reg.c index 64165ec4604..37b73e3ba07 100644 --- a/net/tipc/user_reg.c +++ b/net/tipc/user_reg.c @@ -1,9 +1,8 @@ /* * net/tipc/user_reg.c: TIPC user registry code * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2004-2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/user_reg.h b/net/tipc/user_reg.h index 0f96004ebdc..3a55c755f1f 100644 --- a/net/tipc/user_reg.h +++ b/net/tipc/user_reg.h @@ -1,9 +1,8 @@ /* * net/tipc/user_reg.h: Include file for TIPC user registry code * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/zone.c b/net/tipc/zone.c index b47deecb73f..cb5528699a6 100644 --- a/net/tipc/zone.c +++ b/net/tipc/zone.c @@ -1,9 +1,8 @@ /* * net/tipc/zone.c: TIPC zone management routines * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/net/tipc/zone.h b/net/tipc/zone.h index e05cc610204..2fc5ed71b6d 100644 --- a/net/tipc/zone.h +++ b/net/tipc/zone.h @@ -1,9 +1,8 @@ /* * net/tipc/zone.h: Include file for TIPC zone management routines * - * Copyright (c) 2003-2005, Ericsson Research Canada + * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems - * Copyright (c) 2005-2006, Ericsson AB * All rights reserved. * * Redistribution and use in source and binary forms, with or without -- GitLab From 593a5f22d8035b1396a958b6bbde9f13c0f09549 Mon Sep 17 00:00:00 2001 From: Per Liden Date: Wed, 11 Jan 2006 19:14:19 +0100 Subject: [PATCH 045/465] [TIPC] More updates of file headers Updated copyright notice to include the year the file was actually created. Information about file creation dates was extracted from the files in the old CVS repository at tipc.sourceforge.net. Signed-off-by: Per Liden --- include/net/tipc/tipc.h | 1 - include/net/tipc/tipc_port.h | 2 +- net/tipc/addr.c | 2 +- net/tipc/addr.h | 2 +- net/tipc/bcast.c | 2 +- net/tipc/bearer.c | 2 +- net/tipc/bearer.h | 2 +- net/tipc/cluster.c | 2 +- net/tipc/cluster.h | 2 +- net/tipc/config.c | 2 +- net/tipc/core.h | 2 +- net/tipc/dbg.c | 2 +- net/tipc/dbg.h | 2 +- net/tipc/eth_media.c | 2 +- net/tipc/handler.c | 2 +- net/tipc/link.c | 2 +- net/tipc/link.h | 2 +- net/tipc/msg.c | 2 +- net/tipc/msg.h | 2 +- net/tipc/name_distr.c | 2 +- net/tipc/name_distr.h | 2 +- net/tipc/name_table.c | 2 +- net/tipc/name_table.h | 2 +- net/tipc/net.c | 2 +- net/tipc/net.h | 2 +- net/tipc/netlink.c | 1 + net/tipc/node.c | 2 +- net/tipc/node.h | 2 +- net/tipc/node_subscr.c | 2 +- net/tipc/node_subscr.h | 2 +- net/tipc/port.c | 2 +- net/tipc/port.h | 2 +- net/tipc/ref.c | 2 +- net/tipc/ref.h | 2 +- net/tipc/socket.c | 2 +- net/tipc/subscr.c | 2 +- net/tipc/user_reg.c | 2 +- net/tipc/user_reg.h | 2 +- net/tipc/zone.c | 2 +- net/tipc/zone.h | 2 +- 40 files changed, 39 insertions(+), 39 deletions(-) diff --git a/include/net/tipc/tipc.h b/include/net/tipc/tipc.h index 560a329660f..9566608c88c 100644 --- a/include/net/tipc/tipc.h +++ b/include/net/tipc/tipc.h @@ -44,7 +44,6 @@ /* * Native API - * ---------- */ /* diff --git a/include/net/tipc/tipc_port.h b/include/net/tipc/tipc_port.h index 3f602744164..333bba6dc52 100644 --- a/include/net/tipc/tipc_port.h +++ b/include/net/tipc/tipc_port.h @@ -1,7 +1,7 @@ /* * include/net/tipc/tipc_port.h: Include file for privileged access to TIPC ports * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 1994-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/addr.c b/net/tipc/addr.c index 6d5709deee6..eca22260c98 100644 --- a/net/tipc/addr.c +++ b/net/tipc/addr.c @@ -1,7 +1,7 @@ /* * net/tipc/addr.c: TIPC address utility routines * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 2000-2006, Ericsson AB * Copyright (c) 2004-2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/addr.h b/net/tipc/addr.h index cdf95486043..02ca71783e2 100644 --- a/net/tipc/addr.h +++ b/net/tipc/addr.h @@ -1,7 +1,7 @@ /* * net/tipc/addr.h: Include file for TIPC address utility routines * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 2000-2006, Ericsson AB * Copyright (c) 2004-2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index d7d06f29f19..24d949c8943 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -1,7 +1,7 @@ /* * net/tipc/bcast.c: TIPC broadcast code * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 2004-2006, Ericsson AB * Copyright (c) 2004, Intel Corporation. * Copyright (c) 2005, Wind River Systems * All rights reserved. diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 9c8ab26301d..3dd19fdc5a2 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -1,7 +1,7 @@ /* * net/tipc/bearer.c: TIPC bearer code * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 1996-2006, Ericsson AB * Copyright (c) 2004-2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 55197ccf1a1..21e63d3f018 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h @@ -1,7 +1,7 @@ /* * net/tipc/bearer.h: Include file for TIPC bearer code * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 1996-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/cluster.c b/net/tipc/cluster.c index 7c31f690c38..f0f7bac51d4 100644 --- a/net/tipc/cluster.c +++ b/net/tipc/cluster.c @@ -1,7 +1,7 @@ /* * net/tipc/cluster.c: TIPC cluster management routines * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 2000-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/cluster.h b/net/tipc/cluster.h index a9a46fa4fc2..1ffb095991d 100644 --- a/net/tipc/cluster.h +++ b/net/tipc/cluster.h @@ -1,7 +1,7 @@ /* * net/tipc/cluster.h: Include file for TIPC cluster management routines * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 2000-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/config.c b/net/tipc/config.c index 6c45771bd99..8ddef4fce2c 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -1,7 +1,7 @@ /* * net/tipc/config.c: TIPC configuration management code * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 2002-2006, Ericsson AB * Copyright (c) 2004-2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/core.h b/net/tipc/core.h index deee5de5fb3..b69b60b2cc8 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -1,7 +1,7 @@ /* * net/tipc/core.h: Include file for TIPC global declarations * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 2005-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/dbg.c b/net/tipc/dbg.c index 3264ccb7448..7ed60a1cfbb 100644 --- a/net/tipc/dbg.c +++ b/net/tipc/dbg.c @@ -1,7 +1,7 @@ /* * net/tipc/dbg.c: TIPC print buffer routines for debuggign * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 1996-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/dbg.h b/net/tipc/dbg.h index 264c741f95b..c6b2a64c224 100644 --- a/net/tipc/dbg.h +++ b/net/tipc/dbg.h @@ -1,7 +1,7 @@ /* * net/tipc/dbg.h: Include file for TIPC print buffer routines * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 1997-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c index fe0a4286e48..34d0462db3a 100644 --- a/net/tipc/eth_media.c +++ b/net/tipc/eth_media.c @@ -1,7 +1,7 @@ /* * net/tipc/eth_media.c: Ethernet bearer support for TIPC * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 2001-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/handler.c b/net/tipc/handler.c index cab6f615046..f320010f8a6 100644 --- a/net/tipc/handler.c +++ b/net/tipc/handler.c @@ -1,7 +1,7 @@ /* * net/tipc/handler.c: TIPC signal handling * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 2000-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/link.c b/net/tipc/link.c index 48d0483297e..7265f4be476 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1,7 +1,7 @@ /* * net/tipc/link.c: TIPC link code * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 1996-2006, Ericsson AB * Copyright (c) 2004-2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/link.h b/net/tipc/link.h index 686eb7d684e..c2553f07375 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h @@ -1,7 +1,7 @@ /* * net/tipc/link.h: Include file for TIPC link code * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 1995-2006, Ericsson AB * Copyright (c) 2004-2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/msg.c b/net/tipc/msg.c index 4ffbb9d4442..03dbc55cb04 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c @@ -1,7 +1,7 @@ /* * net/tipc/msg.c: TIPC message header routines * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 2000-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/msg.h b/net/tipc/msg.h index 71e272face6..662c81862a0 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h @@ -1,7 +1,7 @@ /* * net/tipc/msg.h: Include file for TIPC message header routines * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 2000-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index 93ac2b25220..41cbaf1a4a7 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c @@ -1,7 +1,7 @@ /* * net/tipc/name_distr.c: TIPC name distribution code * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 2000-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/name_distr.h b/net/tipc/name_distr.h index 41c1b1c065d..a04bdeac84e 100644 --- a/net/tipc/name_distr.h +++ b/net/tipc/name_distr.h @@ -1,7 +1,7 @@ /* * net/tipc/name_distr.h: Include file for TIPC name distribution code * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 2000-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 8568df3cc6b..972c83eb83b 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c @@ -1,7 +1,7 @@ /* * net/tipc/name_table.c: TIPC name table code * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 2000-2006, Ericsson AB * Copyright (c) 2004-2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h index c771b093e12..f82693384f6 100644 --- a/net/tipc/name_table.h +++ b/net/tipc/name_table.h @@ -1,7 +1,7 @@ /* * net/tipc/name_table.h: Include file for TIPC name table code * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 2000-2006, Ericsson AB * Copyright (c) 2004-2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/net.c b/net/tipc/net.c index a6989946e23..6826b493c1d 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -1,7 +1,7 @@ /* * net/tipc/net.c: TIPC network routing code * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 1995-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/net.h b/net/tipc/net.h index 6f0758e894c..948c6d42102 100644 --- a/net/tipc/net.h +++ b/net/tipc/net.h @@ -1,7 +1,7 @@ /* * net/tipc/net.h: Include file for TIPC network routing code * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 1995-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index c19c2fa2ce5..6fe95acde4f 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c @@ -1,6 +1,7 @@ /* * net/tipc/netlink.c: TIPC configuration handling * + * Copyright (c) 2005-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/node.c b/net/tipc/node.c index 565c35b54c0..05688d01138 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -1,7 +1,7 @@ /* * net/tipc/node.c: TIPC node management routines * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 2000-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/node.h b/net/tipc/node.h index 26c04ba2d49..b39442badcc 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h @@ -1,7 +1,7 @@ /* * net/tipc/node.h: Include file for TIPC node management routines * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 2000-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/node_subscr.c b/net/tipc/node_subscr.c index f271b61ecc2..79375927916 100644 --- a/net/tipc/node_subscr.c +++ b/net/tipc/node_subscr.c @@ -1,7 +1,7 @@ /* * net/tipc/node_subscr.c: TIPC "node down" subscription handling * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 1995-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/node_subscr.h b/net/tipc/node_subscr.h index 3145339b55b..a3b87ac4859 100644 --- a/net/tipc/node_subscr.h +++ b/net/tipc/node_subscr.h @@ -1,7 +1,7 @@ /* * net/tipc/node_subscr.h: Include file for TIPC "node down" subscription handling * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 1995-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/port.c b/net/tipc/port.c index ea45b17b045..bb9404661df 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -1,7 +1,7 @@ /* * net/tipc/port.c: TIPC port code * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 1992-2006, Ericsson AB * Copyright (c) 2004-2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/port.h b/net/tipc/port.h index c15f687bd69..e829a99d3b7 100644 --- a/net/tipc/port.h +++ b/net/tipc/port.h @@ -1,7 +1,7 @@ /* * net/tipc/port.h: Include file for TIPC port code * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 1994-2006, Ericsson AB * Copyright (c) 2004-2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/ref.c b/net/tipc/ref.c index eb5f2b2799d..944093fe246 100644 --- a/net/tipc/ref.c +++ b/net/tipc/ref.c @@ -1,7 +1,7 @@ /* * net/tipc/ref.c: TIPC object registry code * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 1991-2006, Ericsson AB * Copyright (c) 2004-2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/ref.h b/net/tipc/ref.h index 12dd827be30..429cde57228 100644 --- a/net/tipc/ref.h +++ b/net/tipc/ref.h @@ -1,7 +1,7 @@ /* * net/tipc/ref.h: Include file for TIPC object registry code * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 1991-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/socket.c b/net/tipc/socket.c index cb90d8a9988..d21f8c0cd25 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -1,7 +1,7 @@ /* * net/tipc/socket.c: TIPC socket API * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 2001-2006, Ericsson AB * Copyright (c) 2004-2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 728f9f073a5..451d875befc 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -1,7 +1,7 @@ /* * net/tipc/subscr.c: TIPC subscription service * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 2000-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/user_reg.c b/net/tipc/user_reg.c index 37b73e3ba07..35ec7dc8211 100644 --- a/net/tipc/user_reg.c +++ b/net/tipc/user_reg.c @@ -1,7 +1,7 @@ /* * net/tipc/user_reg.c: TIPC user registry code * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 2000-2006, Ericsson AB * Copyright (c) 2004-2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/user_reg.h b/net/tipc/user_reg.h index 3a55c755f1f..122ca9be367 100644 --- a/net/tipc/user_reg.h +++ b/net/tipc/user_reg.h @@ -1,7 +1,7 @@ /* * net/tipc/user_reg.h: Include file for TIPC user registry code * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 2000-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/zone.c b/net/tipc/zone.c index cb5528699a6..4eaef662d56 100644 --- a/net/tipc/zone.c +++ b/net/tipc/zone.c @@ -1,7 +1,7 @@ /* * net/tipc/zone.c: TIPC zone management routines * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 2000-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems * All rights reserved. * diff --git a/net/tipc/zone.h b/net/tipc/zone.h index 2fc5ed71b6d..4326f78d829 100644 --- a/net/tipc/zone.h +++ b/net/tipc/zone.h @@ -1,7 +1,7 @@ /* * net/tipc/zone.h: Include file for TIPC zone management routines * - * Copyright (c) 2003-2006, Ericsson AB + * Copyright (c) 2000-2006, Ericsson AB * Copyright (c) 2005, Wind River Systems * All rights reserved. * -- GitLab From e86eaa3abc285a988524d95e867285aad5d026a7 Mon Sep 17 00:00:00 2001 From: Per Liden Date: Thu, 12 Jan 2006 16:45:18 +0100 Subject: [PATCH 046/465] [TIPC] Added entry for TIPC in MAINTAINERS Signed-off-by: Per Liden --- MAINTAINERS | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 0db72a36e24..71693c5c313 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2519,6 +2519,19 @@ P: Romain Lievin M: roms@lpg.ticalc.org S: Maintained +TIPC NETWORK LAYER +P: Per Liden +M: per.liden@nospam.ericsson.com +P: Jon Maloy +M: jon.maloy@nospam.ericsson.com +P: Allan Stephens +M: allan.stephens@nospam.windriver.com +L: tipc-discussion@lists.sourceforge.net +W: http://tipc.sourceforge.net/ +W: http://tipc.cslab.ericsson.net/ +T: git tipc.cslab.ericsson.net:/pub/git/tipc.git +S: Maintained + TLAN NETWORK DRIVER P: Samuel Chessman M: chessman@tux.org -- GitLab From 880b005f294454d989783d0984dc554dfe3c8214 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 12 Jan 2006 13:22:32 -0800 Subject: [PATCH 047/465] [TIPC]: Fix 64-bit build warnings. When storing u32 values in a pointer, need to do some long casts to keep GCC happy. Signed-off-by: David S. Miller --- net/tipc/bcast.c | 4 ++-- net/tipc/port.c | 3 ++- net/tipc/subscr.c | 8 +++++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 24d949c8943..9713d622efb 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -114,12 +114,12 @@ static inline u32 buf_seqno(struct sk_buff *buf) static inline u32 bcbuf_acks(struct sk_buff *buf) { - return (u32)TIPC_SKB_CB(buf)->handle; + return (u32)(unsigned long)TIPC_SKB_CB(buf)->handle; } static inline void bcbuf_set_acks(struct sk_buff *buf, u32 acks) { - TIPC_SKB_CB(buf)->handle = (void *)acks; + TIPC_SKB_CB(buf)->handle = (void *)(unsigned long)acks; } static inline void bcbuf_decr_acks(struct sk_buff *buf) diff --git a/net/tipc/port.c b/net/tipc/port.c index bb9404661df..66caca7abe9 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -1234,7 +1234,8 @@ int tipc_connect2port(u32 ref, struct tipc_portid const *peer) p_ptr->publ.connected = 1; k_start_timer(&p_ptr->timer, p_ptr->probing_interval); - nodesub_subscribe(&p_ptr->subscription,peer->node, (void *)ref, + nodesub_subscribe(&p_ptr->subscription,peer->node, + (void *)(unsigned long)ref, (net_ev_handler)port_handle_node_down); res = TIPC_OK; exit: diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 451d875befc..80e219ba527 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -329,9 +329,10 @@ static void subscr_conn_shutdown_event(void *usr_handle, unsigned int size, int reason) { - struct subscriber *subscriber = ref_lock((u32)usr_handle); + struct subscriber *subscriber; spinlock_t *subscriber_lock; + subscriber = ref_lock((u32)(unsigned long)usr_handle); if (subscriber == NULL) return; @@ -350,9 +351,10 @@ static void subscr_conn_msg_event(void *usr_handle, const unchar *data, u32 size) { - struct subscriber *subscriber = ref_lock((u32)usr_handle); + struct subscriber *subscriber; spinlock_t *subscriber_lock; + subscriber = ref_lock((u32)(unsigned long)usr_handle); if (subscriber == NULL) return; @@ -409,7 +411,7 @@ static void subscr_named_msg_event(void *usr_handle, /* Establish a connection to subscriber */ tipc_createport(topsrv.user_ref, - (void *)subscriber->ref, + (void *)(unsigned long)subscriber->ref, importance, 0, 0, -- GitLab From 2e4e6a17af35be359cc8f1c924f8f198fbd478cc Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 12 Jan 2006 13:30:04 -0800 Subject: [PATCH 048/465] [NETFILTER] x_tables: Abstraction layer for {ip,ip6,arp}_tables This monster-patch tries to do the best job for unifying the data structures and backend interfaces for the three evil clones ip_tables, ip6_tables and arp_tables. In an ideal world we would never have allowed this kind of copy+paste programming... but well, our world isn't (yet?) ideal. o introduce a new x_tables module o {ip,arp,ip6}_tables depend on this x_tables module o registration functions for tables, matches and targets are only wrappers around x_tables provided functions o all matches/targets that are used from ip_tables and ip6_tables are now implemented as xt_FOOBAR.c files and provide module aliases to ipt_FOOBAR and ip6t_FOOBAR o header files for xt_matches are in include/linux/netfilter/, include/linux/netfilter_{ipv4,ipv6} contains compatibility wrappers around the xt_FOOBAR.h headers Based on this patchset we're going to further unify the code, gradually getting rid of all the layer 3 specific assumptions. Signed-off-by: Harald Welte Signed-off-by: David S. Miller --- include/linux/netfilter/nf_conntrack_common.h | 3 + include/linux/netfilter/x_tables.h | 224 +++++ include/linux/netfilter/xt_CLASSIFY.h | 8 + include/linux/netfilter/xt_CONNMARK.h | 25 + include/linux/netfilter/xt_MARK.h | 21 + include/linux/netfilter/xt_NFQUEUE.h | 16 + include/linux/netfilter/xt_comment.h | 10 + include/linux/netfilter/xt_connbytes.h | 25 + include/linux/netfilter/xt_connmark.h | 18 + include/linux/netfilter/xt_conntrack.h | 63 ++ include/linux/netfilter/xt_dccp.h | 23 + include/linux/netfilter/xt_helper.h | 8 + include/linux/netfilter/xt_length.h | 9 + include/linux/netfilter/xt_limit.h | 21 + include/linux/netfilter/xt_mac.h | 8 + include/linux/netfilter/xt_mark.h | 9 + include/linux/netfilter/xt_physdev.h | 24 + include/linux/netfilter/xt_pkttype.h | 8 + include/linux/netfilter/xt_realm.h | 10 + include/linux/netfilter/xt_sctp.h | 107 +++ include/linux/netfilter/xt_state.h | 13 + include/linux/netfilter/xt_string.h | 18 + include/linux/netfilter/xt_tcpmss.h | 9 + include/linux/netfilter/xt_tcpudp.h | 36 + include/linux/netfilter_arp/arp_tables.h | 123 +-- include/linux/netfilter_ipv4/ip_conntrack.h | 3 - include/linux/netfilter_ipv4/ip_tables.h | 217 +---- include/linux/netfilter_ipv4/ipt_CLASSIFY.h | 5 +- include/linux/netfilter_ipv4/ipt_CONNMARK.h | 16 +- include/linux/netfilter_ipv4/ipt_MARK.h | 22 +- include/linux/netfilter_ipv4/ipt_NFQUEUE.h | 8 +- include/linux/netfilter_ipv4/ipt_comment.h | 8 +- include/linux/netfilter_ipv4/ipt_connbytes.h | 31 +- include/linux/netfilter_ipv4/ipt_connmark.h | 15 +- include/linux/netfilter_ipv4/ipt_conntrack.h | 66 +- include/linux/netfilter_ipv4/ipt_dccp.h | 22 +- include/linux/netfilter_ipv4/ipt_helper.h | 7 +- include/linux/netfilter_ipv4/ipt_length.h | 6 +- include/linux/netfilter_ipv4/ipt_limit.h | 19 +- include/linux/netfilter_ipv4/ipt_mac.h | 7 +- include/linux/netfilter_ipv4/ipt_mark.h | 8 +- include/linux/netfilter_ipv4/ipt_physdev.h | 27 +- include/linux/netfilter_ipv4/ipt_pkttype.h | 7 +- include/linux/netfilter_ipv4/ipt_realm.h | 7 +- include/linux/netfilter_ipv4/ipt_state.h | 16 +- include/linux/netfilter_ipv4/ipt_string.h | 16 +- include/linux/netfilter_ipv4/ipt_tcpmss.h | 6 +- include/linux/netfilter_ipv6/ip6_tables.h | 208 +---- include/linux/netfilter_ipv6/ip6t_MARK.h | 9 +- include/linux/netfilter_ipv6/ip6t_length.h | 6 +- include/linux/netfilter_ipv6/ip6t_limit.h | 21 +- include/linux/netfilter_ipv6/ip6t_mac.h | 9 +- include/linux/netfilter_ipv6/ip6t_mark.h | 8 +- include/linux/netfilter_ipv6/ip6t_physdev.h | 27 +- .../net/netfilter/ipv4/nf_conntrack_ipv4.h | 3 - include/net/netfilter/nf_conntrack.h | 3 - net/bridge/netfilter/ebt_log.c | 1 + net/ipv4/netfilter/Kconfig | 250 +----- net/ipv4/netfilter/Makefile | 21 - net/ipv4/netfilter/arp_tables.c | 444 ++------- net/ipv4/netfilter/arpt_mangle.c | 7 +- net/ipv4/netfilter/arptable_filter.c | 1 + net/ipv4/netfilter/ip_conntrack_standalone.c | 4 +- net/ipv4/netfilter/ip_nat_rule.c | 5 +- net/ipv4/netfilter/ip_nat_standalone.c | 2 +- net/ipv4/netfilter/ip_tables.c | 842 ++---------------- net/ipv4/netfilter/ipt_CLUSTERIP.c | 3 +- net/ipv4/netfilter/ipt_DSCP.c | 2 +- net/ipv4/netfilter/ipt_ECN.c | 3 +- net/ipv4/netfilter/ipt_LOG.c | 2 +- net/ipv4/netfilter/ipt_MASQUERADE.c | 2 +- net/ipv4/netfilter/ipt_NETMAP.c | 2 +- net/ipv4/netfilter/ipt_NFQUEUE.c | 70 -- net/ipv4/netfilter/ipt_REDIRECT.c | 2 +- net/ipv4/netfilter/ipt_REJECT.c | 3 +- net/ipv4/netfilter/ipt_SAME.c | 2 +- net/ipv4/netfilter/ipt_TCPMSS.c | 3 +- net/ipv4/netfilter/ipt_TOS.c | 2 +- net/ipv4/netfilter/ipt_TTL.c | 2 +- net/ipv4/netfilter/ipt_ULOG.c | 2 +- net/ipv4/netfilter/ipt_addrtype.c | 4 +- net/ipv4/netfilter/ipt_ah.c | 6 +- net/ipv4/netfilter/ipt_dscp.c | 4 +- net/ipv4/netfilter/ipt_ecn.c | 5 +- net/ipv4/netfilter/ipt_esp.c | 6 +- net/ipv4/netfilter/ipt_hashlimit.c | 3 +- net/ipv4/netfilter/ipt_iprange.c | 4 +- net/ipv4/netfilter/ipt_length.c | 64 -- net/ipv4/netfilter/ipt_multiport.c | 10 +- net/ipv4/netfilter/ipt_owner.c | 3 +- net/ipv4/netfilter/ipt_physdev.c | 135 --- net/ipv4/netfilter/ipt_recent.c | 6 +- net/ipv4/netfilter/ipt_tos.c | 3 +- net/ipv4/netfilter/ipt_ttl.c | 4 +- net/ipv4/netfilter/iptable_filter.c | 3 +- net/ipv4/netfilter/iptable_mangle.c | 1 + net/ipv4/netfilter/iptable_raw.c | 3 +- .../netfilter/nf_conntrack_l3proto_ipv4.c | 7 +- net/ipv6/netfilter/Kconfig | 72 +- net/ipv6/netfilter/Makefile | 6 - net/ipv6/netfilter/ip6_tables.c | 828 +++-------------- net/ipv6/netfilter/ip6t_HL.c | 2 +- net/ipv6/netfilter/ip6t_LOG.c | 2 +- net/ipv6/netfilter/ip6t_MARK.c | 81 -- net/ipv6/netfilter/ip6t_NFQUEUE.c | 70 -- net/ipv6/netfilter/ip6t_REJECT.c | 3 +- net/ipv6/netfilter/ip6t_ah.c | 2 +- net/ipv6/netfilter/ip6t_dst.c | 2 +- net/ipv6/netfilter/ip6t_esp.c | 2 +- net/ipv6/netfilter/ip6t_eui64.c | 2 +- net/ipv6/netfilter/ip6t_frag.c | 2 +- net/ipv6/netfilter/ip6t_hbh.c | 2 +- net/ipv6/netfilter/ip6t_hl.c | 2 +- net/ipv6/netfilter/ip6t_ipv6header.c | 2 +- net/ipv6/netfilter/ip6t_length.c | 66 -- net/ipv6/netfilter/ip6t_limit.c | 147 --- net/ipv6/netfilter/ip6t_mac.c | 81 -- net/ipv6/netfilter/ip6t_mark.c | 66 -- net/ipv6/netfilter/ip6t_multiport.c | 3 +- net/ipv6/netfilter/ip6t_owner.c | 2 +- net/ipv6/netfilter/ip6t_rt.c | 2 +- net/ipv6/netfilter/ip6table_filter.c | 1 + net/ipv6/netfilter/ip6table_mangle.c | 1 + net/ipv6/netfilter/ip6table_raw.c | 5 +- .../netfilter/nf_conntrack_l3proto_ipv6.c | 8 +- net/ipv6/netfilter/nf_conntrack_reasm.c | 45 +- net/netfilter/Kconfig | 258 ++++++ net/netfilter/Makefile | 37 +- net/netfilter/nf_conntrack_standalone.c | 4 +- net/netfilter/x_tables.c | 624 +++++++++++++ .../xt_CLASSIFY.c} | 41 +- .../xt_CONNMARK.c} | 51 +- .../ipt_MARK.c => netfilter/xt_MARK.c} | 79 +- net/netfilter/xt_NFQUEUE.c | 107 +++ .../ipt_NOTRACK.c => netfilter/xt_NOTRACK.c} | 38 +- .../ipt_comment.c => netfilter/xt_comment.c} | 35 +- .../xt_connbytes.c} | 73 +- .../xt_connmark.c} | 41 +- .../xt_conntrack.c} | 110 +-- .../ipt_dccp.c => netfilter/xt_dccp.c} | 105 ++- .../ipt_helper.c => netfilter/xt_helper.c} | 56 +- net/netfilter/xt_length.c | 98 ++ .../ipt_limit.c => netfilter/xt_limit.c} | 48 +- .../ipt_mac.c => netfilter/xt_mac.c} | 38 +- .../ipt_mark.c => netfilter/xt_mark.c} | 38 +- .../ip6t_physdev.c => netfilter/xt_physdev.c} | 82 +- .../ipt_pkttype.c => netfilter/xt_pkttype.c} | 46 +- .../ipt_realm.c => netfilter/xt_realm.c} | 25 +- .../ipt_sctp.c => netfilter/xt_sctp.c} | 109 ++- .../ipt_state.c => netfilter/xt_state.c} | 50 +- .../ipt_string.c => netfilter/xt_string.c} | 40 +- .../ipt_tcpmss.c => netfilter/xt_tcpmss.c} | 69 +- net/netfilter/xt_tcpudp.c | 333 +++++++ net/sched/act_ipt.c | 2 +- 154 files changed, 3615 insertions(+), 4149 deletions(-) create mode 100644 include/linux/netfilter/x_tables.h create mode 100644 include/linux/netfilter/xt_CLASSIFY.h create mode 100644 include/linux/netfilter/xt_CONNMARK.h create mode 100644 include/linux/netfilter/xt_MARK.h create mode 100644 include/linux/netfilter/xt_NFQUEUE.h create mode 100644 include/linux/netfilter/xt_comment.h create mode 100644 include/linux/netfilter/xt_connbytes.h create mode 100644 include/linux/netfilter/xt_connmark.h create mode 100644 include/linux/netfilter/xt_conntrack.h create mode 100644 include/linux/netfilter/xt_dccp.h create mode 100644 include/linux/netfilter/xt_helper.h create mode 100644 include/linux/netfilter/xt_length.h create mode 100644 include/linux/netfilter/xt_limit.h create mode 100644 include/linux/netfilter/xt_mac.h create mode 100644 include/linux/netfilter/xt_mark.h create mode 100644 include/linux/netfilter/xt_physdev.h create mode 100644 include/linux/netfilter/xt_pkttype.h create mode 100644 include/linux/netfilter/xt_realm.h create mode 100644 include/linux/netfilter/xt_sctp.h create mode 100644 include/linux/netfilter/xt_state.h create mode 100644 include/linux/netfilter/xt_string.h create mode 100644 include/linux/netfilter/xt_tcpmss.h create mode 100644 include/linux/netfilter/xt_tcpudp.h delete mode 100644 net/ipv4/netfilter/ipt_NFQUEUE.c delete mode 100644 net/ipv4/netfilter/ipt_length.c delete mode 100644 net/ipv4/netfilter/ipt_physdev.c delete mode 100644 net/ipv6/netfilter/ip6t_MARK.c delete mode 100644 net/ipv6/netfilter/ip6t_NFQUEUE.c delete mode 100644 net/ipv6/netfilter/ip6t_length.c delete mode 100644 net/ipv6/netfilter/ip6t_limit.c delete mode 100644 net/ipv6/netfilter/ip6t_mac.c delete mode 100644 net/ipv6/netfilter/ip6t_mark.c create mode 100644 net/netfilter/x_tables.c rename net/{ipv4/netfilter/ipt_CLASSIFY.c => netfilter/xt_CLASSIFY.c} (66%) rename net/{ipv4/netfilter/ipt_CONNMARK.c => netfilter/xt_CONNMARK.c} (73%) rename net/{ipv4/netfilter/ipt_MARK.c => netfilter/xt_MARK.c} (61%) create mode 100644 net/netfilter/xt_NFQUEUE.c rename net/{ipv4/netfilter/ipt_NOTRACK.c => netfilter/xt_NOTRACK.c} (69%) rename net/{ipv4/netfilter/ipt_comment.c => netfilter/xt_comment.c} (55%) rename net/{ipv4/netfilter/ipt_connbytes.c => netfilter/xt_connbytes.c} (66%) rename net/{ipv4/netfilter/ipt_connmark.c => netfilter/xt_connmark.c} (70%) rename net/{ipv4/netfilter/ipt_conntrack.c => netfilter/xt_conntrack.c} (63%) rename net/{ipv4/netfilter/ipt_dccp.c => netfilter/xt_dccp.c} (58%) rename net/{ipv4/netfilter/ipt_helper.c => netfilter/xt_helper.c} (72%) create mode 100644 net/netfilter/xt_length.c rename net/{ipv4/netfilter/ipt_limit.c => netfilter/xt_limit.c} (78%) rename net/{ipv4/netfilter/ipt_mac.c => netfilter/xt_mac.c} (65%) rename net/{ipv4/netfilter/ipt_mark.c => netfilter/xt_mark.c} (60%) rename net/{ipv6/netfilter/ip6t_physdev.c => netfilter/xt_physdev.c} (57%) rename net/{ipv4/netfilter/ipt_pkttype.c => netfilter/xt_pkttype.c} (55%) rename net/{ipv4/netfilter/ipt_realm.c => netfilter/xt_realm.c} (70%) rename net/{ipv4/netfilter/ipt_sctp.c => netfilter/xt_sctp.c} (62%) rename net/{ipv4/netfilter/ipt_state.c => netfilter/xt_state.c} (53%) rename net/{ipv4/netfilter/ipt_string.c => netfilter/xt_string.c} (66%) rename net/{ipv4/netfilter/ipt_tcpmss.c => netfilter/xt_tcpmss.c} (59%) create mode 100644 net/netfilter/xt_tcpudp.c diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h index 6d39b518486..3ff88c87830 100644 --- a/include/linux/netfilter/nf_conntrack_common.h +++ b/include/linux/netfilter/nf_conntrack_common.h @@ -154,6 +154,9 @@ struct ip_conntrack_stat unsigned int expect_delete; }; +/* call to create an explicit dependency on nf_conntrack. */ +extern void need_conntrack(void); + #endif /* __KERNEL__ */ #endif /* _NF_CONNTRACK_COMMON_H */ diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h new file mode 100644 index 00000000000..472f0483480 --- /dev/null +++ b/include/linux/netfilter/x_tables.h @@ -0,0 +1,224 @@ +#ifndef _X_TABLES_H +#define _X_TABLES_H + +#define XT_FUNCTION_MAXNAMELEN 30 +#define XT_TABLE_MAXNAMELEN 32 + +/* The argument to IPT_SO_GET_REVISION_*. Returns highest revision + * kernel supports, if >= revision. */ +struct xt_get_revision +{ + char name[XT_FUNCTION_MAXNAMELEN-1]; + + u_int8_t revision; +}; + +/* CONTINUE verdict for targets */ +#define XT_CONTINUE 0xFFFFFFFF + +/* For standard target */ +#define XT_RETURN (-NF_REPEAT - 1) + +#define XT_ALIGN(s) (((s) + (__alignof__(void *)-1)) & ~(__alignof__(void *)-1)) + +/* Standard return verdict, or do jump. */ +#define XT_STANDARD_TARGET "" +/* Error verdict. */ +#define XT_ERROR_TARGET "ERROR" + +/* + * New IP firewall options for [gs]etsockopt at the RAW IP level. + * Unlike BSD Linux inherits IP options so you don't have to use a raw + * socket for this. Instead we check rights in the calls. */ +#define XT_BASE_CTL 64 /* base for firewall socket options */ + +#define XT_SO_SET_REPLACE (XT_BASE_CTL) +#define XT_SO_SET_ADD_COUNTERS (XT_BASE_CTL + 1) +#define XT_SO_SET_MAX XT_SO_SET_ADD_COUNTERS + +#define XT_SO_GET_INFO (XT_BASE_CTL) +#define XT_SO_GET_ENTRIES (XT_BASE_CTL + 1) +#define XT_SO_GET_REVISION_MATCH (XT_BASE_CTL + 2) +#define XT_SO_GET_REVISION_TARGET (XT_BASE_CTL + 3) +#define XT_SO_GET_MAX XT_SO_GET_REVISION_TARGET + +#define SET_COUNTER(c,b,p) do { (c).bcnt = (b); (c).pcnt = (p); } while(0) +#define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0) + +struct xt_counters +{ + u_int64_t pcnt, bcnt; /* Packet and byte counters */ +}; + +/* The argument to IPT_SO_ADD_COUNTERS. */ +struct xt_counters_info +{ + /* Which table. */ + char name[XT_TABLE_MAXNAMELEN]; + + unsigned int num_counters; + + /* The counters (actually `number' of these). */ + struct xt_counters counters[0]; +}; + +#define XT_INV_PROTO 0x40 /* Invert the sense of PROTO. */ + +#ifdef __KERNEL__ + +#include + +#define ASSERT_READ_LOCK(x) +#define ASSERT_WRITE_LOCK(x) +#include + +struct xt_match +{ + struct list_head list; + + const char name[XT_FUNCTION_MAXNAMELEN-1]; + + u_int8_t revision; + + /* Return true or false: return FALSE and set *hotdrop = 1 to + force immediate packet drop. */ + /* Arguments changed since 2.6.9, as this must now handle + non-linear skb, using skb_header_pointer and + skb_ip_make_writable. */ + int (*match)(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const void *matchinfo, + int offset, + unsigned int protoff, + int *hotdrop); + + /* Called when user tries to insert an entry of this type. */ + /* Should return true or false. */ + int (*checkentry)(const char *tablename, + const void *ip, + void *matchinfo, + unsigned int matchinfosize, + unsigned int hook_mask); + + /* Called when entry of this type deleted. */ + void (*destroy)(void *matchinfo, unsigned int matchinfosize); + + /* Set this to THIS_MODULE if you are a module, otherwise NULL */ + struct module *me; +}; + +/* Registration hooks for targets. */ +struct xt_target +{ + struct list_head list; + + const char name[XT_FUNCTION_MAXNAMELEN-1]; + + u_int8_t revision; + + /* Returns verdict. Argument order changed since 2.6.9, as this + must now handle non-linear skbs, using skb_copy_bits and + skb_ip_make_writable. */ + unsigned int (*target)(struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + unsigned int hooknum, + const void *targinfo, + void *userdata); + + /* Called when user tries to insert an entry of this type: + hook_mask is a bitmask of hooks from which it can be + called. */ + /* Should return true or false. */ + int (*checkentry)(const char *tablename, + const void *entry, + void *targinfo, + unsigned int targinfosize, + unsigned int hook_mask); + + /* Called when entry of this type deleted. */ + void (*destroy)(void *targinfo, unsigned int targinfosize); + + /* Set this to THIS_MODULE if you are a module, otherwise NULL */ + struct module *me; +}; + +/* Furniture shopping... */ +struct xt_table +{ + struct list_head list; + + /* A unique name... */ + char name[XT_TABLE_MAXNAMELEN]; + + /* What hooks you will enter on */ + unsigned int valid_hooks; + + /* Lock for the curtain */ + rwlock_t lock; + + /* Man behind the curtain... */ + //struct ip6t_table_info *private; + void *private; + + /* Set this to THIS_MODULE if you are a module, otherwise NULL */ + struct module *me; + + int af; /* address/protocol family */ +}; + +#include + +/* The table itself */ +struct xt_table_info +{ + /* Size per table */ + unsigned int size; + /* Number of entries: FIXME. --RR */ + unsigned int number; + /* Initial number of entries. Needed for module usage count */ + unsigned int initial_entries; + + /* Entry points and underflows */ + unsigned int hook_entry[NF_IP_NUMHOOKS]; + unsigned int underflow[NF_IP_NUMHOOKS]; + + /* ipt_entry tables: one per CPU */ + char *entries[NR_CPUS]; +}; + +extern int xt_register_target(int af, struct xt_target *target); +extern void xt_unregister_target(int af, struct xt_target *target); +extern int xt_register_match(int af, struct xt_match *target); +extern void xt_unregister_match(int af, struct xt_match *target); + +extern int xt_register_table(struct xt_table *table, + struct xt_table_info *bootstrap, + struct xt_table_info *newinfo); +extern void *xt_unregister_table(struct xt_table *table); + +extern struct xt_table_info *xt_replace_table(struct xt_table *table, + unsigned int num_counters, + struct xt_table_info *newinfo, + int *error); + +extern struct xt_match *xt_find_match(int af, const char *name, u8 revision); +extern struct xt_target *xt_find_target(int af, const char *name, u8 revision); +extern struct xt_target *xt_request_find_target(int af, const char *name, + u8 revision); +extern int xt_find_revision(int af, const char *name, u8 revision, int target, + int *err); + +extern struct xt_table *xt_find_table_lock(int af, const char *name); +extern void xt_table_unlock(struct xt_table *t); + +extern int xt_proto_init(int af); +extern void xt_proto_fini(int af); + +extern struct xt_table_info *xt_alloc_table_info(unsigned int size); +extern void xt_free_table_info(struct xt_table_info *info); + +#endif /* __KERNEL__ */ + +#endif /* _X_TABLES_H */ diff --git a/include/linux/netfilter/xt_CLASSIFY.h b/include/linux/netfilter/xt_CLASSIFY.h new file mode 100644 index 00000000000..58111355255 --- /dev/null +++ b/include/linux/netfilter/xt_CLASSIFY.h @@ -0,0 +1,8 @@ +#ifndef _XT_CLASSIFY_H +#define _XT_CLASSIFY_H + +struct xt_classify_target_info { + u_int32_t priority; +}; + +#endif /*_XT_CLASSIFY_H */ diff --git a/include/linux/netfilter/xt_CONNMARK.h b/include/linux/netfilter/xt_CONNMARK.h new file mode 100644 index 00000000000..9f744689fff --- /dev/null +++ b/include/linux/netfilter/xt_CONNMARK.h @@ -0,0 +1,25 @@ +#ifndef _XT_CONNMARK_H_target +#define _XT_CONNMARK_H_target + +/* Copyright (C) 2002,2004 MARA Systems AB + * by Henrik Nordstrom + * + * 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. + */ + +enum { + XT_CONNMARK_SET = 0, + XT_CONNMARK_SAVE, + XT_CONNMARK_RESTORE +}; + +struct xt_connmark_target_info { + unsigned long mark; + unsigned long mask; + u_int8_t mode; +}; + +#endif /*_XT_CONNMARK_H_target*/ diff --git a/include/linux/netfilter/xt_MARK.h b/include/linux/netfilter/xt_MARK.h new file mode 100644 index 00000000000..b021e93ee5d --- /dev/null +++ b/include/linux/netfilter/xt_MARK.h @@ -0,0 +1,21 @@ +#ifndef _XT_MARK_H_target +#define _XT_MARK_H_target + +/* Version 0 */ +struct xt_mark_target_info { + unsigned long mark; +}; + +/* Version 1 */ +enum { + XT_MARK_SET=0, + XT_MARK_AND, + XT_MARK_OR, +}; + +struct xt_mark_target_info_v1 { + unsigned long mark; + u_int8_t mode; +}; + +#endif /*_XT_MARK_H_target */ diff --git a/include/linux/netfilter/xt_NFQUEUE.h b/include/linux/netfilter/xt_NFQUEUE.h new file mode 100644 index 00000000000..9a9af79f74d --- /dev/null +++ b/include/linux/netfilter/xt_NFQUEUE.h @@ -0,0 +1,16 @@ +/* iptables module for using NFQUEUE mechanism + * + * (C) 2005 Harald Welte + * + * This software is distributed under GNU GPL v2, 1991 + * +*/ +#ifndef _XT_NFQ_TARGET_H +#define _XT_NFQ_TARGET_H + +/* target info */ +struct xt_NFQ_info { + u_int16_t queuenum; +}; + +#endif /* _XT_NFQ_TARGET_H */ diff --git a/include/linux/netfilter/xt_comment.h b/include/linux/netfilter/xt_comment.h new file mode 100644 index 00000000000..eacfedc6b5d --- /dev/null +++ b/include/linux/netfilter/xt_comment.h @@ -0,0 +1,10 @@ +#ifndef _XT_COMMENT_H +#define _XT_COMMENT_H + +#define XT_MAX_COMMENT_LEN 256 + +struct xt_comment_info { + unsigned char comment[XT_MAX_COMMENT_LEN]; +}; + +#endif /* XT_COMMENT_H */ diff --git a/include/linux/netfilter/xt_connbytes.h b/include/linux/netfilter/xt_connbytes.h new file mode 100644 index 00000000000..c022c989754 --- /dev/null +++ b/include/linux/netfilter/xt_connbytes.h @@ -0,0 +1,25 @@ +#ifndef _XT_CONNBYTES_H +#define _XT_CONNBYTES_H + +enum xt_connbytes_what { + XT_CONNBYTES_PKTS, + XT_CONNBYTES_BYTES, + XT_CONNBYTES_AVGPKT, +}; + +enum xt_connbytes_direction { + XT_CONNBYTES_DIR_ORIGINAL, + XT_CONNBYTES_DIR_REPLY, + XT_CONNBYTES_DIR_BOTH, +}; + +struct xt_connbytes_info +{ + struct { + aligned_u64 from; /* count to be matched */ + aligned_u64 to; /* count to be matched */ + } count; + u_int8_t what; /* ipt_connbytes_what */ + u_int8_t direction; /* ipt_connbytes_direction */ +}; +#endif diff --git a/include/linux/netfilter/xt_connmark.h b/include/linux/netfilter/xt_connmark.h new file mode 100644 index 00000000000..c592f6ae088 --- /dev/null +++ b/include/linux/netfilter/xt_connmark.h @@ -0,0 +1,18 @@ +#ifndef _XT_CONNMARK_H +#define _XT_CONNMARK_H + +/* Copyright (C) 2002,2004 MARA Systems AB + * by Henrik Nordstrom + * + * 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. + */ + +struct xt_connmark_info { + unsigned long mark, mask; + u_int8_t invert; +}; + +#endif /*_XT_CONNMARK_H*/ diff --git a/include/linux/netfilter/xt_conntrack.h b/include/linux/netfilter/xt_conntrack.h new file mode 100644 index 00000000000..34f63cf2e29 --- /dev/null +++ b/include/linux/netfilter/xt_conntrack.h @@ -0,0 +1,63 @@ +/* Header file for kernel module to match connection tracking information. + * GPL (C) 2001 Marc Boucher (marc@mbsi.ca). + */ + +#ifndef _XT_CONNTRACK_H +#define _XT_CONNTRACK_H + +#include +#include + +#define XT_CONNTRACK_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1)) +#define XT_CONNTRACK_STATE_INVALID (1 << 0) + +#define XT_CONNTRACK_STATE_SNAT (1 << (IP_CT_NUMBER + 1)) +#define XT_CONNTRACK_STATE_DNAT (1 << (IP_CT_NUMBER + 2)) +#define XT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3)) + +/* flags, invflags: */ +#define XT_CONNTRACK_STATE 0x01 +#define XT_CONNTRACK_PROTO 0x02 +#define XT_CONNTRACK_ORIGSRC 0x04 +#define XT_CONNTRACK_ORIGDST 0x08 +#define XT_CONNTRACK_REPLSRC 0x10 +#define XT_CONNTRACK_REPLDST 0x20 +#define XT_CONNTRACK_STATUS 0x40 +#define XT_CONNTRACK_EXPIRES 0x80 + +/* This is exposed to userspace, so remains frozen in time. */ +struct ip_conntrack_old_tuple +{ + struct { + __u32 ip; + union { + __u16 all; + } u; + } src; + + struct { + __u32 ip; + union { + __u16 all; + } u; + + /* The protocol. */ + u16 protonum; + } dst; +}; + +struct xt_conntrack_info +{ + unsigned int statemask, statusmask; + + struct ip_conntrack_old_tuple tuple[IP_CT_DIR_MAX]; + struct in_addr sipmsk[IP_CT_DIR_MAX], dipmsk[IP_CT_DIR_MAX]; + + unsigned long expires_min, expires_max; + + /* Flags word */ + u_int8_t flags; + /* Inverse flags */ + u_int8_t invflags; +}; +#endif /*_XT_CONNTRACK_H*/ diff --git a/include/linux/netfilter/xt_dccp.h b/include/linux/netfilter/xt_dccp.h new file mode 100644 index 00000000000..e0221b9d32c --- /dev/null +++ b/include/linux/netfilter/xt_dccp.h @@ -0,0 +1,23 @@ +#ifndef _XT_DCCP_H_ +#define _XT_DCCP_H_ + +#define XT_DCCP_SRC_PORTS 0x01 +#define XT_DCCP_DEST_PORTS 0x02 +#define XT_DCCP_TYPE 0x04 +#define XT_DCCP_OPTION 0x08 + +#define XT_DCCP_VALID_FLAGS 0x0f + +struct xt_dccp_info { + u_int16_t dpts[2]; /* Min, Max */ + u_int16_t spts[2]; /* Min, Max */ + + u_int16_t flags; + u_int16_t invflags; + + u_int16_t typemask; + u_int8_t option; +}; + +#endif /* _XT_DCCP_H_ */ + diff --git a/include/linux/netfilter/xt_helper.h b/include/linux/netfilter/xt_helper.h new file mode 100644 index 00000000000..6b42763f999 --- /dev/null +++ b/include/linux/netfilter/xt_helper.h @@ -0,0 +1,8 @@ +#ifndef _XT_HELPER_H +#define _XT_HELPER_H + +struct xt_helper_info { + int invert; + char name[30]; +}; +#endif /* _XT_HELPER_H */ diff --git a/include/linux/netfilter/xt_length.h b/include/linux/netfilter/xt_length.h new file mode 100644 index 00000000000..7c2b439f73f --- /dev/null +++ b/include/linux/netfilter/xt_length.h @@ -0,0 +1,9 @@ +#ifndef _XT_LENGTH_H +#define _XT_LENGTH_H + +struct xt_length_info { + u_int16_t min, max; + u_int8_t invert; +}; + +#endif /*_XT_LENGTH_H*/ diff --git a/include/linux/netfilter/xt_limit.h b/include/linux/netfilter/xt_limit.h new file mode 100644 index 00000000000..b3ce65375ec --- /dev/null +++ b/include/linux/netfilter/xt_limit.h @@ -0,0 +1,21 @@ +#ifndef _XT_RATE_H +#define _XT_RATE_H + +/* timings are in milliseconds. */ +#define XT_LIMIT_SCALE 10000 + +/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490 + seconds, or one every 59 hours. */ +struct xt_rateinfo { + u_int32_t avg; /* Average secs between packets * scale */ + u_int32_t burst; /* Period multiplier for upper limit. */ + + /* Used internally by the kernel */ + unsigned long prev; + u_int32_t credit; + u_int32_t credit_cap, cost; + + /* Ugly, ugly fucker. */ + struct xt_rateinfo *master; +}; +#endif /*_XT_RATE_H*/ diff --git a/include/linux/netfilter/xt_mac.h b/include/linux/netfilter/xt_mac.h new file mode 100644 index 00000000000..b892cdc67e0 --- /dev/null +++ b/include/linux/netfilter/xt_mac.h @@ -0,0 +1,8 @@ +#ifndef _XT_MAC_H +#define _XT_MAC_H + +struct xt_mac_info { + unsigned char srcaddr[ETH_ALEN]; + int invert; +}; +#endif /*_XT_MAC_H*/ diff --git a/include/linux/netfilter/xt_mark.h b/include/linux/netfilter/xt_mark.h new file mode 100644 index 00000000000..802dd4842ca --- /dev/null +++ b/include/linux/netfilter/xt_mark.h @@ -0,0 +1,9 @@ +#ifndef _XT_MARK_H +#define _XT_MARK_H + +struct xt_mark_info { + unsigned long mark, mask; + u_int8_t invert; +}; + +#endif /*_XT_MARK_H*/ diff --git a/include/linux/netfilter/xt_physdev.h b/include/linux/netfilter/xt_physdev.h new file mode 100644 index 00000000000..25a7a1815b5 --- /dev/null +++ b/include/linux/netfilter/xt_physdev.h @@ -0,0 +1,24 @@ +#ifndef _XT_PHYSDEV_H +#define _XT_PHYSDEV_H + +#ifdef __KERNEL__ +#include +#endif + +#define XT_PHYSDEV_OP_IN 0x01 +#define XT_PHYSDEV_OP_OUT 0x02 +#define XT_PHYSDEV_OP_BRIDGED 0x04 +#define XT_PHYSDEV_OP_ISIN 0x08 +#define XT_PHYSDEV_OP_ISOUT 0x10 +#define XT_PHYSDEV_OP_MASK (0x20 - 1) + +struct xt_physdev_info { + char physindev[IFNAMSIZ]; + char in_mask[IFNAMSIZ]; + char physoutdev[IFNAMSIZ]; + char out_mask[IFNAMSIZ]; + u_int8_t invert; + u_int8_t bitmask; +}; + +#endif /*_XT_PHYSDEV_H*/ diff --git a/include/linux/netfilter/xt_pkttype.h b/include/linux/netfilter/xt_pkttype.h new file mode 100644 index 00000000000..f265cf52fae --- /dev/null +++ b/include/linux/netfilter/xt_pkttype.h @@ -0,0 +1,8 @@ +#ifndef _XT_PKTTYPE_H +#define _XT_PKTTYPE_H + +struct xt_pkttype_info { + int pkttype; + int invert; +}; +#endif /*_XT_PKTTYPE_H*/ diff --git a/include/linux/netfilter/xt_realm.h b/include/linux/netfilter/xt_realm.h new file mode 100644 index 00000000000..220e8724571 --- /dev/null +++ b/include/linux/netfilter/xt_realm.h @@ -0,0 +1,10 @@ +#ifndef _XT_REALM_H +#define _XT_REALM_H + +struct xt_realm_info { + u_int32_t id; + u_int32_t mask; + u_int8_t invert; +}; + +#endif /* _XT_REALM_H */ diff --git a/include/linux/netfilter/xt_sctp.h b/include/linux/netfilter/xt_sctp.h new file mode 100644 index 00000000000..b157897e779 --- /dev/null +++ b/include/linux/netfilter/xt_sctp.h @@ -0,0 +1,107 @@ +#ifndef _XT_SCTP_H_ +#define _XT_SCTP_H_ + +#define XT_SCTP_SRC_PORTS 0x01 +#define XT_SCTP_DEST_PORTS 0x02 +#define XT_SCTP_CHUNK_TYPES 0x04 + +#define XT_SCTP_VALID_FLAGS 0x07 + +#define ELEMCOUNT(x) (sizeof(x)/sizeof(x[0])) + + +struct xt_sctp_flag_info { + u_int8_t chunktype; + u_int8_t flag; + u_int8_t flag_mask; +}; + +#define XT_NUM_SCTP_FLAGS 4 + +struct xt_sctp_info { + u_int16_t dpts[2]; /* Min, Max */ + u_int16_t spts[2]; /* Min, Max */ + + u_int32_t chunkmap[256 / sizeof (u_int32_t)]; /* Bit mask of chunks to be matched according to RFC 2960 */ + +#define SCTP_CHUNK_MATCH_ANY 0x01 /* Match if any of the chunk types are present */ +#define SCTP_CHUNK_MATCH_ALL 0x02 /* Match if all of the chunk types are present */ +#define SCTP_CHUNK_MATCH_ONLY 0x04 /* Match if these are the only chunk types present */ + + u_int32_t chunk_match_type; + struct xt_sctp_flag_info flag_info[XT_NUM_SCTP_FLAGS]; + int flag_count; + + u_int32_t flags; + u_int32_t invflags; +}; + +#define bytes(type) (sizeof(type) * 8) + +#define SCTP_CHUNKMAP_SET(chunkmap, type) \ + do { \ + chunkmap[type / bytes(u_int32_t)] |= \ + 1 << (type % bytes(u_int32_t)); \ + } while (0) + +#define SCTP_CHUNKMAP_CLEAR(chunkmap, type) \ + do { \ + chunkmap[type / bytes(u_int32_t)] &= \ + ~(1 << (type % bytes(u_int32_t))); \ + } while (0) + +#define SCTP_CHUNKMAP_IS_SET(chunkmap, type) \ +({ \ + (chunkmap[type / bytes (u_int32_t)] & \ + (1 << (type % bytes (u_int32_t)))) ? 1: 0; \ +}) + +#define SCTP_CHUNKMAP_RESET(chunkmap) \ + do { \ + int i; \ + for (i = 0; i < ELEMCOUNT(chunkmap); i++) \ + chunkmap[i] = 0; \ + } while (0) + +#define SCTP_CHUNKMAP_SET_ALL(chunkmap) \ + do { \ + int i; \ + for (i = 0; i < ELEMCOUNT(chunkmap); i++) \ + chunkmap[i] = ~0; \ + } while (0) + +#define SCTP_CHUNKMAP_COPY(destmap, srcmap) \ + do { \ + int i; \ + for (i = 0; i < ELEMCOUNT(chunkmap); i++) \ + destmap[i] = srcmap[i]; \ + } while (0) + +#define SCTP_CHUNKMAP_IS_CLEAR(chunkmap) \ +({ \ + int i; \ + int flag = 1; \ + for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \ + if (chunkmap[i]) { \ + flag = 0; \ + break; \ + } \ + } \ + flag; \ +}) + +#define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap) \ +({ \ + int i; \ + int flag = 1; \ + for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \ + if (chunkmap[i] != ~0) { \ + flag = 0; \ + break; \ + } \ + } \ + flag; \ +}) + +#endif /* _XT_SCTP_H_ */ + diff --git a/include/linux/netfilter/xt_state.h b/include/linux/netfilter/xt_state.h new file mode 100644 index 00000000000..c06f32edee0 --- /dev/null +++ b/include/linux/netfilter/xt_state.h @@ -0,0 +1,13 @@ +#ifndef _XT_STATE_H +#define _XT_STATE_H + +#define XT_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1)) +#define XT_STATE_INVALID (1 << 0) + +#define XT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1)) + +struct xt_state_info +{ + unsigned int statemask; +}; +#endif /*_XT_STATE_H*/ diff --git a/include/linux/netfilter/xt_string.h b/include/linux/netfilter/xt_string.h new file mode 100644 index 00000000000..3b3419f2637 --- /dev/null +++ b/include/linux/netfilter/xt_string.h @@ -0,0 +1,18 @@ +#ifndef _XT_STRING_H +#define _XT_STRING_H + +#define XT_STRING_MAX_PATTERN_SIZE 128 +#define XT_STRING_MAX_ALGO_NAME_SIZE 16 + +struct xt_string_info +{ + u_int16_t from_offset; + u_int16_t to_offset; + char algo[XT_STRING_MAX_ALGO_NAME_SIZE]; + char pattern[XT_STRING_MAX_PATTERN_SIZE]; + u_int8_t patlen; + u_int8_t invert; + struct ts_config __attribute__((aligned(8))) *config; +}; + +#endif /*_XT_STRING_H*/ diff --git a/include/linux/netfilter/xt_tcpmss.h b/include/linux/netfilter/xt_tcpmss.h new file mode 100644 index 00000000000..e03274c4c79 --- /dev/null +++ b/include/linux/netfilter/xt_tcpmss.h @@ -0,0 +1,9 @@ +#ifndef _XT_TCPMSS_MATCH_H +#define _XT_TCPMSS_MATCH_H + +struct xt_tcpmss_match_info { + u_int16_t mss_min, mss_max; + u_int8_t invert; +}; + +#endif /*_XT_TCPMSS_MATCH_H*/ diff --git a/include/linux/netfilter/xt_tcpudp.h b/include/linux/netfilter/xt_tcpudp.h new file mode 100644 index 00000000000..78bc65f11ad --- /dev/null +++ b/include/linux/netfilter/xt_tcpudp.h @@ -0,0 +1,36 @@ +#ifndef _XT_TCPUDP_H +#define _XT_TCPUDP_H + +/* TCP matching stuff */ +struct xt_tcp +{ + u_int16_t spts[2]; /* Source port range. */ + u_int16_t dpts[2]; /* Destination port range. */ + u_int8_t option; /* TCP Option iff non-zero*/ + u_int8_t flg_mask; /* TCP flags mask byte */ + u_int8_t flg_cmp; /* TCP flags compare byte */ + u_int8_t invflags; /* Inverse flags */ +}; + +/* Values for "inv" field in struct ipt_tcp. */ +#define XT_TCP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ +#define XT_TCP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ +#define XT_TCP_INV_FLAGS 0x04 /* Invert the sense of TCP flags. */ +#define XT_TCP_INV_OPTION 0x08 /* Invert the sense of option test. */ +#define XT_TCP_INV_MASK 0x0F /* All possible flags. */ + +/* UDP matching stuff */ +struct xt_udp +{ + u_int16_t spts[2]; /* Source port range. */ + u_int16_t dpts[2]; /* Destination port range. */ + u_int8_t invflags; /* Inverse flags */ +}; + +/* Values for "invflags" field in struct ipt_udp. */ +#define XT_UDP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ +#define XT_UDP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ +#define XT_UDP_INV_MASK 0x03 /* All possible flags. */ + + +#endif diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h index e98a870a20b..fd21796e513 100644 --- a/include/linux/netfilter_arp/arp_tables.h +++ b/include/linux/netfilter_arp/arp_tables.h @@ -19,8 +19,12 @@ #include #include -#define ARPT_FUNCTION_MAXNAMELEN 30 -#define ARPT_TABLE_MAXNAMELEN 32 +#include + +#define ARPT_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN +#define ARPT_TABLE_MAXNAMELEN XT_TABLE_MAXNAMELEN +#define arpt_target xt_target +#define arpt_table xt_table #define ARPT_DEV_ADDR_LEN_MAX 16 @@ -91,11 +95,6 @@ struct arpt_standard_target int verdict; }; -struct arpt_counters -{ - u_int64_t pcnt, bcnt; /* Packet and byte counters */ -}; - /* Values for "flag" field in struct arpt_ip (general arp structure). * No flags defined yet. */ @@ -130,7 +129,7 @@ struct arpt_entry unsigned int comefrom; /* Packet and byte counters. */ - struct arpt_counters counters; + struct xt_counters counters; /* The matches (if any), then the target. */ unsigned char elems[0]; @@ -141,23 +140,24 @@ struct arpt_entry * Unlike BSD Linux inherits IP options so you don't have to use a raw * socket for this. Instead we check rights in the calls. */ -#define ARPT_BASE_CTL 96 /* base for firewall socket options */ +#define ARPT_CTL_OFFSET 32 +#define ARPT_BASE_CTL (XT_BASE_CTL+ARPT_CTL_OFFSET) -#define ARPT_SO_SET_REPLACE (ARPT_BASE_CTL) -#define ARPT_SO_SET_ADD_COUNTERS (ARPT_BASE_CTL + 1) -#define ARPT_SO_SET_MAX ARPT_SO_SET_ADD_COUNTERS +#define ARPT_SO_SET_REPLACE (XT_SO_SET_REPLACE+ARPT_CTL_OFFSET) +#define ARPT_SO_SET_ADD_COUNTERS (XT_SO_SET_ADD_COUNTERS+ARPT_CTL_OFFSET) +#define ARPT_SO_SET_MAX (XT_SO_SET_MAX+ARPT_CTL_OFFSET) -#define ARPT_SO_GET_INFO (ARPT_BASE_CTL) -#define ARPT_SO_GET_ENTRIES (ARPT_BASE_CTL + 1) -/* #define ARPT_SO_GET_REVISION_MATCH (ARPT_BASE_CTL + 2)*/ -#define ARPT_SO_GET_REVISION_TARGET (ARPT_BASE_CTL + 3) -#define ARPT_SO_GET_MAX ARPT_SO_GET_REVISION_TARGET +#define ARPT_SO_GET_INFO (XT_SO_GET_INFO+ARPT_CTL_OFFSET) +#define ARPT_SO_GET_ENTRIES (XT_SO_GET_ENTRIES+ARPT_CTL_OFFSET) +/* #define ARPT_SO_GET_REVISION_MATCH XT_SO_GET_REVISION_MATCH */ +#define ARPT_SO_GET_REVISION_TARGET (XT_SO_GET_REVISION_TARGET+ARPT_CTL_OFFSET) +#define ARPT_SO_GET_MAX (XT_SO_GET_REVISION_TARGET+ARPT_CTL_OFFSET) /* CONTINUE verdict for targets */ -#define ARPT_CONTINUE 0xFFFFFFFF +#define ARPT_CONTINUE XT_CONTINUE /* For standard target */ -#define ARPT_RETURN (-NF_REPEAT - 1) +#define ARPT_RETURN XT_RETURN /* The argument to ARPT_SO_GET_INFO */ struct arpt_getinfo @@ -208,23 +208,14 @@ struct arpt_replace /* Number of counters (must be equal to current number of entries). */ unsigned int num_counters; /* The old entries' counters. */ - struct arpt_counters __user *counters; + struct xt_counters __user *counters; /* The entries (hang off end: not really an array). */ struct arpt_entry entries[0]; }; /* The argument to ARPT_SO_ADD_COUNTERS. */ -struct arpt_counters_info -{ - /* Which table. */ - char name[ARPT_TABLE_MAXNAMELEN]; - - unsigned int num_counters; - - /* The counters (actually `number' of these). */ - struct arpt_counters counters[0]; -}; +#define arpt_counters_info xt_counters_info /* The argument to ARPT_SO_GET_ENTRIES. */ struct arpt_get_entries @@ -239,19 +230,10 @@ struct arpt_get_entries struct arpt_entry entrytable[0]; }; -/* The argument to ARPT_SO_GET_REVISION_*. Returns highest revision - * kernel supports, if >= revision. */ -struct arpt_get_revision -{ - char name[ARPT_FUNCTION_MAXNAMELEN-1]; - - u_int8_t revision; -}; - /* Standard return verdict, or do jump. */ -#define ARPT_STANDARD_TARGET "" +#define ARPT_STANDARD_TARGET XT_STANDARD_TARGET /* Error verdict. */ -#define ARPT_ERROR_TARGET "ERROR" +#define ARPT_ERROR_TARGET XT_ERROR_TARGET /* Helper functions */ static __inline__ struct arpt_entry_target *arpt_get_target(struct arpt_entry *e) @@ -281,63 +263,8 @@ static __inline__ struct arpt_entry_target *arpt_get_target(struct arpt_entry *e */ #ifdef __KERNEL__ -/* Registration hooks for targets. */ -struct arpt_target -{ - struct list_head list; - - const char name[ARPT_FUNCTION_MAXNAMELEN-1]; - - u_int8_t revision; - - /* Returns verdict. */ - unsigned int (*target)(struct sk_buff **pskb, - unsigned int hooknum, - const struct net_device *in, - const struct net_device *out, - const void *targinfo, - void *userdata); - - /* Called when user tries to insert an entry of this type: - hook_mask is a bitmask of hooks from which it can be - called. */ - /* Should return true or false. */ - int (*checkentry)(const char *tablename, - const struct arpt_entry *e, - void *targinfo, - unsigned int targinfosize, - unsigned int hook_mask); - - /* Called when entry of this type deleted. */ - void (*destroy)(void *targinfo, unsigned int targinfosize); - - /* Set this to THIS_MODULE if you are a module, otherwise NULL */ - struct module *me; -}; - -extern int arpt_register_target(struct arpt_target *target); -extern void arpt_unregister_target(struct arpt_target *target); - -/* Furniture shopping... */ -struct arpt_table -{ - struct list_head list; - - /* A unique name... */ - char name[ARPT_TABLE_MAXNAMELEN]; - - /* What hooks you will enter on */ - unsigned int valid_hooks; - - /* Lock for the curtain */ - rwlock_t lock; - - /* Man behind the curtain... */ - struct arpt_table_info *private; - - /* Set this to THIS_MODULE if you are a module, otherwise NULL */ - struct module *me; -}; +#define arpt_register_target(tgt) xt_register_target(NF_ARP, tgt) +#define arpt_unregister_target(tgt) xt_unregister_target(NF_ARP, tgt) extern int arpt_register_table(struct arpt_table *table, const struct arpt_replace *repl); diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h index b3432ab59a1..215765f043e 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack.h +++ b/include/linux/netfilter_ipv4/ip_conntrack.h @@ -199,9 +199,6 @@ ip_conntrack_put(struct ip_conntrack *ct) nf_conntrack_put(&ct->ct_general); } -/* call to create an explicit dependency on ip_conntrack. */ -extern void need_ip_conntrack(void); - extern int invert_tuplepr(struct ip_conntrack_tuple *inverse, const struct ip_conntrack_tuple *orig); diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h index d19d65cf453..76ba24b6851 100644 --- a/include/linux/netfilter_ipv4/ip_tables.h +++ b/include/linux/netfilter_ipv4/ip_tables.h @@ -25,8 +25,14 @@ #include #include -#define IPT_FUNCTION_MAXNAMELEN 30 -#define IPT_TABLE_MAXNAMELEN 32 +#include + +#define IPT_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN +#define IPT_TABLE_MAXNAMELEN XT_FUNCTION_MAXNAMELEN +#define ipt_match xt_match +#define ipt_target xt_target +#define ipt_table xt_table +#define ipt_get_revision xt_get_revision /* Yes, Virginia, you have to zero the padding. */ struct ipt_ip { @@ -102,10 +108,7 @@ struct ipt_standard_target int verdict; }; -struct ipt_counters -{ - u_int64_t pcnt, bcnt; /* Packet and byte counters */ -}; +#define ipt_counters xt_counters /* Values for "flag" field in struct ipt_ip (general ip structure). */ #define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */ @@ -119,7 +122,7 @@ struct ipt_counters #define IPT_INV_SRCIP 0x08 /* Invert the sense of SRC IP. */ #define IPT_INV_DSTIP 0x10 /* Invert the sense of DST OP. */ #define IPT_INV_FRAG 0x20 /* Invert the sense of FRAG. */ -#define IPT_INV_PROTO 0x40 /* Invert the sense of PROTO. */ +#define IPT_INV_PROTO XT_INV_PROTO #define IPT_INV_MASK 0x7F /* All possible flag bits mask. */ /* This structure defines each of the firewall rules. Consists of 3 @@ -141,7 +144,7 @@ struct ipt_entry unsigned int comefrom; /* Packet and byte counters. */ - struct ipt_counters counters; + struct xt_counters counters; /* The matches (if any), then the target. */ unsigned char elems[0]; @@ -151,54 +154,34 @@ struct ipt_entry * New IP firewall options for [gs]etsockopt at the RAW IP level. * Unlike BSD Linux inherits IP options so you don't have to use a raw * socket for this. Instead we check rights in the calls. */ -#define IPT_BASE_CTL 64 /* base for firewall socket options */ +#define IPT_BASE_CTL XT_BASE_CTL -#define IPT_SO_SET_REPLACE (IPT_BASE_CTL) -#define IPT_SO_SET_ADD_COUNTERS (IPT_BASE_CTL + 1) -#define IPT_SO_SET_MAX IPT_SO_SET_ADD_COUNTERS +#define IPT_SO_SET_REPLACE XT_SO_SET_REPLACE +#define IPT_SO_SET_ADD_COUNTERS XT_SO_SET_ADD_COUNTERS +#define IPT_SO_SET_MAX XT_SO_SET_MAX -#define IPT_SO_GET_INFO (IPT_BASE_CTL) -#define IPT_SO_GET_ENTRIES (IPT_BASE_CTL + 1) -#define IPT_SO_GET_REVISION_MATCH (IPT_BASE_CTL + 2) -#define IPT_SO_GET_REVISION_TARGET (IPT_BASE_CTL + 3) -#define IPT_SO_GET_MAX IPT_SO_GET_REVISION_TARGET +#define IPT_SO_GET_INFO XT_SO_GET_INFO +#define IPT_SO_GET_ENTRIES XT_SO_GET_ENTRIES +#define IPT_SO_GET_REVISION_MATCH XT_SO_GET_REVISION_MATCH +#define IPT_SO_GET_REVISION_TARGET XT_SO_GET_REVISION_TARGET +#define IPT_SO_GET_MAX XT_SO_GET_REVISION_TARGET -/* CONTINUE verdict for targets */ -#define IPT_CONTINUE 0xFFFFFFFF +#define IPT_CONTINUE XT_CONTINUE +#define IPT_RETURN XT_RETURN -/* For standard target */ -#define IPT_RETURN (-NF_REPEAT - 1) +#include +#define ipt_udp xt_udp +#define ipt_tcp xt_tcp -/* TCP matching stuff */ -struct ipt_tcp -{ - u_int16_t spts[2]; /* Source port range. */ - u_int16_t dpts[2]; /* Destination port range. */ - u_int8_t option; /* TCP Option iff non-zero*/ - u_int8_t flg_mask; /* TCP flags mask byte */ - u_int8_t flg_cmp; /* TCP flags compare byte */ - u_int8_t invflags; /* Inverse flags */ -}; - -/* Values for "inv" field in struct ipt_tcp. */ -#define IPT_TCP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ -#define IPT_TCP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ -#define IPT_TCP_INV_FLAGS 0x04 /* Invert the sense of TCP flags. */ -#define IPT_TCP_INV_OPTION 0x08 /* Invert the sense of option test. */ -#define IPT_TCP_INV_MASK 0x0F /* All possible flags. */ - -/* UDP matching stuff */ -struct ipt_udp -{ - u_int16_t spts[2]; /* Source port range. */ - u_int16_t dpts[2]; /* Destination port range. */ - u_int8_t invflags; /* Inverse flags */ -}; +#define IPT_TCP_INV_SRCPT XT_TCP_INV_SRCPT +#define IPT_TCP_INV_DSTPT XT_TCP_INV_DSTPT +#define IPT_TCP_INV_FLAGS XT_TCP_INV_FLAGS +#define IPT_TCP_INV_OPTION XT_TCP_INV_OPTION +#define IPT_TCP_INV_MASK XT_TCP_INV_MASK -/* Values for "invflags" field in struct ipt_udp. */ -#define IPT_UDP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ -#define IPT_UDP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ -#define IPT_UDP_INV_MASK 0x03 /* All possible flags. */ +#define IPT_UDP_INV_SRCPT XT_UDP_INV_SRCPT +#define IPT_UDP_INV_DSTPT XT_UDP_INV_DSTPT +#define IPT_UDP_INV_MASK XT_UDP_INV_MASK /* ICMP matching stuff */ struct ipt_icmp @@ -260,23 +243,14 @@ struct ipt_replace /* Number of counters (must be equal to current number of entries). */ unsigned int num_counters; /* The old entries' counters. */ - struct ipt_counters __user *counters; + struct xt_counters __user *counters; /* The entries (hang off end: not really an array). */ struct ipt_entry entries[0]; }; /* The argument to IPT_SO_ADD_COUNTERS. */ -struct ipt_counters_info -{ - /* Which table. */ - char name[IPT_TABLE_MAXNAMELEN]; - - unsigned int num_counters; - - /* The counters (actually `number' of these). */ - struct ipt_counters counters[0]; -}; +#define ipt_counters_info xt_counters_info /* The argument to IPT_SO_GET_ENTRIES. */ struct ipt_get_entries @@ -291,19 +265,10 @@ struct ipt_get_entries struct ipt_entry entrytable[0]; }; -/* The argument to IPT_SO_GET_REVISION_*. Returns highest revision - * kernel supports, if >= revision. */ -struct ipt_get_revision -{ - char name[IPT_FUNCTION_MAXNAMELEN-1]; - - u_int8_t revision; -}; - /* Standard return verdict, or do jump. */ -#define IPT_STANDARD_TARGET "" +#define IPT_STANDARD_TARGET XT_STANDARD_TARGET /* Error verdict. */ -#define IPT_ERROR_TARGET "ERROR" +#define IPT_ERROR_TARGET XT_ERROR_TARGET /* Helper functions */ static __inline__ struct ipt_entry_target * @@ -356,103 +321,18 @@ ipt_get_target(struct ipt_entry *e) #include extern void ipt_init(void) __init; -struct ipt_match -{ - struct list_head list; - - const char name[IPT_FUNCTION_MAXNAMELEN-1]; - - u_int8_t revision; - - /* Return true or false: return FALSE and set *hotdrop = 1 to - force immediate packet drop. */ - /* Arguments changed since 2.4, as this must now handle - non-linear skbs, using skb_copy_bits and - skb_ip_make_writable. */ - int (*match)(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const void *matchinfo, - int offset, - int *hotdrop); - - /* Called when user tries to insert an entry of this type. */ - /* Should return true or false. */ - int (*checkentry)(const char *tablename, - const struct ipt_ip *ip, - void *matchinfo, - unsigned int matchinfosize, - unsigned int hook_mask); - - /* Called when entry of this type deleted. */ - void (*destroy)(void *matchinfo, unsigned int matchinfosize); - - /* Set this to THIS_MODULE. */ - struct module *me; -}; - -/* Registration hooks for targets. */ -struct ipt_target -{ - struct list_head list; - - const char name[IPT_FUNCTION_MAXNAMELEN-1]; - - u_int8_t revision; - - /* Called when user tries to insert an entry of this type: - hook_mask is a bitmask of hooks from which it can be - called. */ - /* Should return true or false. */ - int (*checkentry)(const char *tablename, - const struct ipt_entry *e, - void *targinfo, - unsigned int targinfosize, - unsigned int hook_mask); - - /* Called when entry of this type deleted. */ - void (*destroy)(void *targinfo, unsigned int targinfosize); - - /* Returns verdict. Argument order changed since 2.4, as this - must now handle non-linear skbs, using skb_copy_bits and - skb_ip_make_writable. */ - unsigned int (*target)(struct sk_buff **pskb, - const struct net_device *in, - const struct net_device *out, - unsigned int hooknum, - const void *targinfo, - void *userdata); - - /* Set this to THIS_MODULE. */ - struct module *me; -}; +#define ipt_register_target(tgt) xt_register_target(AF_INET, tgt) +#define ipt_unregister_target(tgt) xt_unregister_target(AF_INET, tgt) -extern int ipt_register_target(struct ipt_target *target); -extern void ipt_unregister_target(struct ipt_target *target); +#define ipt_register_match(mtch) xt_register_match(AF_INET, mtch) +#define ipt_unregister_match(mtch) xt_unregister_match(AF_INET, mtch) -extern int ipt_register_match(struct ipt_match *match); -extern void ipt_unregister_match(struct ipt_match *match); +//#define ipt_register_table(tbl, repl) xt_register_table(AF_INET, tbl, repl) +//#define ipt_unregister_table(tbl) xt_unregister_table(AF_INET, tbl) -/* Furniture shopping... */ -struct ipt_table -{ - struct list_head list; - - /* A unique name... */ - char name[IPT_TABLE_MAXNAMELEN]; - - /* What hooks you will enter on */ - unsigned int valid_hooks; - - /* Lock for the curtain */ - rwlock_t lock; - - /* Man behind the curtain... */ - struct ipt_table_info *private; - - /* Set to THIS_MODULE. */ - struct module *me; -}; +extern int ipt_register_table(struct ipt_table *table, + const struct ipt_replace *repl); +extern void ipt_unregister_table(struct ipt_table *table); /* net/sched/ipt.c: Gimme access to your targets! Gets target->me. */ extern struct ipt_target *ipt_find_target(const char *name, u8 revision); @@ -476,9 +356,6 @@ struct ipt_error struct ipt_error_target target; }; -extern int ipt_register_table(struct ipt_table *table, - const struct ipt_replace *repl); -extern void ipt_unregister_table(struct ipt_table *table); extern unsigned int ipt_do_table(struct sk_buff **pskb, unsigned int hook, const struct net_device *in, @@ -486,6 +363,6 @@ extern unsigned int ipt_do_table(struct sk_buff **pskb, struct ipt_table *table, void *userdata); -#define IPT_ALIGN(s) (((s) + (__alignof__(struct ipt_entry)-1)) & ~(__alignof__(struct ipt_entry)-1)) +#define IPT_ALIGN(s) XT_ALIGN(s) #endif /*__KERNEL__*/ #endif /* _IPTABLES_H */ diff --git a/include/linux/netfilter_ipv4/ipt_CLASSIFY.h b/include/linux/netfilter_ipv4/ipt_CLASSIFY.h index 7596e3dd00c..a46d511b5c3 100644 --- a/include/linux/netfilter_ipv4/ipt_CLASSIFY.h +++ b/include/linux/netfilter_ipv4/ipt_CLASSIFY.h @@ -1,8 +1,7 @@ #ifndef _IPT_CLASSIFY_H #define _IPT_CLASSIFY_H -struct ipt_classify_target_info { - u_int32_t priority; -}; +#include +#define ipt_classify_target_info xt_classify_target_info #endif /*_IPT_CLASSIFY_H */ diff --git a/include/linux/netfilter_ipv4/ipt_CONNMARK.h b/include/linux/netfilter_ipv4/ipt_CONNMARK.h index d3c02536fc4..9ecfee0a9e3 100644 --- a/include/linux/netfilter_ipv4/ipt_CONNMARK.h +++ b/include/linux/netfilter_ipv4/ipt_CONNMARK.h @@ -9,17 +9,11 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ +#include +#define IPT_CONNMARK_SET XT_CONNMARK_SET +#define IPT_CONNMARK_SAVE XT_CONNMARK_SAVE +#define IPT_CONNMARK_RESTORE XT_CONNMARK_RESTORE -enum { - IPT_CONNMARK_SET = 0, - IPT_CONNMARK_SAVE, - IPT_CONNMARK_RESTORE -}; - -struct ipt_connmark_target_info { - unsigned long mark; - unsigned long mask; - u_int8_t mode; -}; +#define ipt_connmark_target_info xt_connmark_target_info #endif /*_IPT_CONNMARK_H_target*/ diff --git a/include/linux/netfilter_ipv4/ipt_MARK.h b/include/linux/netfilter_ipv4/ipt_MARK.h index f47485790ed..697a486a96d 100644 --- a/include/linux/netfilter_ipv4/ipt_MARK.h +++ b/include/linux/netfilter_ipv4/ipt_MARK.h @@ -1,20 +1,18 @@ #ifndef _IPT_MARK_H_target #define _IPT_MARK_H_target +/* Backwards compatibility for old userspace */ + +#include + /* Version 0 */ -struct ipt_mark_target_info { - unsigned long mark; -}; +#define ipt_mark_target_info xt_mark_target_info /* Version 1 */ -enum { - IPT_MARK_SET=0, - IPT_MARK_AND, - IPT_MARK_OR -}; +#define IPT_MARK_SET XT_MARK_SET +#define IPT_MARK_AND XT_MARK_AND +#define IPT_MARK_OR XT_MARK_OR + +#define ipt_mark_target_info_v1 xt_mark_target_info_v1 -struct ipt_mark_target_info_v1 { - unsigned long mark; - u_int8_t mode; -}; #endif /*_IPT_MARK_H_target*/ diff --git a/include/linux/netfilter_ipv4/ipt_NFQUEUE.h b/include/linux/netfilter_ipv4/ipt_NFQUEUE.h index b5b2943b0c6..97a2a7557cb 100644 --- a/include/linux/netfilter_ipv4/ipt_NFQUEUE.h +++ b/include/linux/netfilter_ipv4/ipt_NFQUEUE.h @@ -8,9 +8,9 @@ #ifndef _IPT_NFQ_TARGET_H #define _IPT_NFQ_TARGET_H -/* target info */ -struct ipt_NFQ_info { - u_int16_t queuenum; -}; +/* Backwards compatibility for old userspace */ +#include + +#define ipt_NFQ_info xt_NFQ_info #endif /* _IPT_DSCP_TARGET_H */ diff --git a/include/linux/netfilter_ipv4/ipt_comment.h b/include/linux/netfilter_ipv4/ipt_comment.h index 85c1123c29c..ae2afc2f748 100644 --- a/include/linux/netfilter_ipv4/ipt_comment.h +++ b/include/linux/netfilter_ipv4/ipt_comment.h @@ -1,10 +1,10 @@ #ifndef _IPT_COMMENT_H #define _IPT_COMMENT_H -#define IPT_MAX_COMMENT_LEN 256 +#include -struct ipt_comment_info { - unsigned char comment[IPT_MAX_COMMENT_LEN]; -}; +#define IPT_MAX_COMMENT_LEN XT_MAX_COMMENT_LEN + +#define ipt_comment_info xt_comment_info #endif /* _IPT_COMMENT_H */ diff --git a/include/linux/netfilter_ipv4/ipt_connbytes.h b/include/linux/netfilter_ipv4/ipt_connbytes.h index 9e5532f8d8a..b04dfa3083c 100644 --- a/include/linux/netfilter_ipv4/ipt_connbytes.h +++ b/include/linux/netfilter_ipv4/ipt_connbytes.h @@ -1,25 +1,18 @@ #ifndef _IPT_CONNBYTES_H #define _IPT_CONNBYTES_H -enum ipt_connbytes_what { - IPT_CONNBYTES_PKTS, - IPT_CONNBYTES_BYTES, - IPT_CONNBYTES_AVGPKT, -}; +#include +#define ipt_connbytes_what xt_connbytes_what -enum ipt_connbytes_direction { - IPT_CONNBYTES_DIR_ORIGINAL, - IPT_CONNBYTES_DIR_REPLY, - IPT_CONNBYTES_DIR_BOTH, -}; +#define IPT_CONNBYTES_PKTS XT_CONNBYTES_PACKETS +#define IPT_CONNBYTES_BYTES XT_CONNBYTES_BYTES +#define IPT_CONNBYTES_AVGPKT XT_CONNBYTES_AVGPKT + +#define ipt_connbytes_direction xt_connbytes_direction +#define IPT_CONNBYTES_DIR_ORIGINAL XT_CONNBYTES_DIR_ORIGINAL +#define IPT_CONNBYTES_DIR_REPLY XT_CONNBYTES_DIR_REPLY +#define IPT_CONNBYTES_DIR_BOTH XT_CONNBYTES_DIR_BOTH + +#define ipt_connbytes_info xt_connbytes_info -struct ipt_connbytes_info -{ - struct { - aligned_u64 from; /* count to be matched */ - aligned_u64 to; /* count to be matched */ - } count; - u_int8_t what; /* ipt_connbytes_what */ - u_int8_t direction; /* ipt_connbytes_direction */ -}; #endif diff --git a/include/linux/netfilter_ipv4/ipt_connmark.h b/include/linux/netfilter_ipv4/ipt_connmark.h index 46573270d9a..c7ba6560d44 100644 --- a/include/linux/netfilter_ipv4/ipt_connmark.h +++ b/include/linux/netfilter_ipv4/ipt_connmark.h @@ -1,18 +1,7 @@ #ifndef _IPT_CONNMARK_H #define _IPT_CONNMARK_H -/* Copyright (C) 2002,2004 MARA Systems AB - * by Henrik Nordstrom - * - * 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. - */ - -struct ipt_connmark_info { - unsigned long mark, mask; - u_int8_t invert; -}; +#include +#define ipt_connmark_info xt_connmark_info #endif /*_IPT_CONNMARK_H*/ diff --git a/include/linux/netfilter_ipv4/ipt_conntrack.h b/include/linux/netfilter_ipv4/ipt_conntrack.h index 413c5658bd3..cde6762949c 100644 --- a/include/linux/netfilter_ipv4/ipt_conntrack.h +++ b/include/linux/netfilter_ipv4/ipt_conntrack.h @@ -5,56 +5,24 @@ #ifndef _IPT_CONNTRACK_H #define _IPT_CONNTRACK_H -#define IPT_CONNTRACK_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1)) -#define IPT_CONNTRACK_STATE_INVALID (1 << 0) +#include -#define IPT_CONNTRACK_STATE_SNAT (1 << (IP_CT_NUMBER + 1)) -#define IPT_CONNTRACK_STATE_DNAT (1 << (IP_CT_NUMBER + 2)) -#define IPT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3)) +#define IPT_CONNTRACK_STATE_BIT(ctinfo) XT_CONNTRACK_STATE_BIT(ctinfo) +#define IPT_CONNTRACK_STATE_INVALID XT_CONNTRACK_STATE_INVALID -/* flags, invflags: */ -#define IPT_CONNTRACK_STATE 0x01 -#define IPT_CONNTRACK_PROTO 0x02 -#define IPT_CONNTRACK_ORIGSRC 0x04 -#define IPT_CONNTRACK_ORIGDST 0x08 -#define IPT_CONNTRACK_REPLSRC 0x10 -#define IPT_CONNTRACK_REPLDST 0x20 -#define IPT_CONNTRACK_STATUS 0x40 -#define IPT_CONNTRACK_EXPIRES 0x80 - -/* This is exposed to userspace, so remains frozen in time. */ -struct ip_conntrack_old_tuple -{ - struct { - __u32 ip; - union { - __u16 all; - } u; - } src; - - struct { - __u32 ip; - union { - __u16 all; - } u; - - /* The protocol. */ - u16 protonum; - } dst; -}; +#define IPT_CONNTRACK_STATE_SNAT XT_CONNTRACK_STATE_SNAT +#define IPT_CONNTRACK_STATE_DNAT XT_CONNTRACK_STATE_DNAT +#define IPT_CONNTRACK_STATE_UNTRACKED XT_CONNTRACK_STATE_UNTRACKED -struct ipt_conntrack_info -{ - unsigned int statemask, statusmask; - - struct ip_conntrack_old_tuple tuple[IP_CT_DIR_MAX]; - struct in_addr sipmsk[IP_CT_DIR_MAX], dipmsk[IP_CT_DIR_MAX]; - - unsigned long expires_min, expires_max; - - /* Flags word */ - u_int8_t flags; - /* Inverse flags */ - u_int8_t invflags; -}; +/* flags, invflags: */ +#define IPT_CONNTRACK_STATE XT_CONNTRACK_STATE +#define IPT_CONNTRACK_PROTO XT_CONNTRACK_PROTO +#define IPT_CONNTRACK_ORIGSRC XT_CONNTRACK_ORIGSRC +#define IPT_CONNTRACK_ORIGDST XT_CONNTRACK_ORIGDST +#define IPT_CONNTRACK_REPLSRC XT_CONNTRACK_REPLSRC +#define IPT_CONNTRACK_REPLDST XT_CONNTRACK_REPLDST +#define IPT_CONNTRACK_STATUS XT_CONNTRACK_STATUS +#define IPT_CONNTRACK_EXPIRES XT_CONNTRACK_EXPIRES + +#define ipt_conntrack_info xt_conntrack_info #endif /*_IPT_CONNTRACK_H*/ diff --git a/include/linux/netfilter_ipv4/ipt_dccp.h b/include/linux/netfilter_ipv4/ipt_dccp.h index 3cb3a522e62..e70d11e1f53 100644 --- a/include/linux/netfilter_ipv4/ipt_dccp.h +++ b/include/linux/netfilter_ipv4/ipt_dccp.h @@ -1,23 +1,15 @@ #ifndef _IPT_DCCP_H_ #define _IPT_DCCP_H_ -#define IPT_DCCP_SRC_PORTS 0x01 -#define IPT_DCCP_DEST_PORTS 0x02 -#define IPT_DCCP_TYPE 0x04 -#define IPT_DCCP_OPTION 0x08 +#include +#define IPT_DCCP_SRC_PORTS XT_DCCP_SRC_PORTS +#define IPT_DCCP_DEST_PORTS XT_DCCP_DEST_PORTS +#define IPT_DCCP_TYPE XT_DCCP_TYPE +#define IPT_DCCP_OPTION XT_DCCP_OPTION -#define IPT_DCCP_VALID_FLAGS 0x0f +#define IPT_DCCP_VALID_FLAGS XT_DCCP_VALID_FLAGS -struct ipt_dccp_info { - u_int16_t dpts[2]; /* Min, Max */ - u_int16_t spts[2]; /* Min, Max */ - - u_int16_t flags; - u_int16_t invflags; - - u_int16_t typemask; - u_int8_t option; -}; +#define ipt_dccp_info xt_dccp_info #endif /* _IPT_DCCP_H_ */ diff --git a/include/linux/netfilter_ipv4/ipt_helper.h b/include/linux/netfilter_ipv4/ipt_helper.h index 6f12ecb8c93..80452c21855 100644 --- a/include/linux/netfilter_ipv4/ipt_helper.h +++ b/include/linux/netfilter_ipv4/ipt_helper.h @@ -1,8 +1,7 @@ #ifndef _IPT_HELPER_H #define _IPT_HELPER_H -struct ipt_helper_info { - int invert; - char name[30]; -}; +#include +#define ipt_helper_info xt_helper_info + #endif /* _IPT_HELPER_H */ diff --git a/include/linux/netfilter_ipv4/ipt_length.h b/include/linux/netfilter_ipv4/ipt_length.h index 6e088522961..9b45206ffce 100644 --- a/include/linux/netfilter_ipv4/ipt_length.h +++ b/include/linux/netfilter_ipv4/ipt_length.h @@ -1,9 +1,7 @@ #ifndef _IPT_LENGTH_H #define _IPT_LENGTH_H -struct ipt_length_info { - u_int16_t min, max; - u_int8_t invert; -}; +#include +#define ipt_length_info xt_length_info #endif /*_IPT_LENGTH_H*/ diff --git a/include/linux/netfilter_ipv4/ipt_limit.h b/include/linux/netfilter_ipv4/ipt_limit.h index 256453409e2..92f5cd07bbc 100644 --- a/include/linux/netfilter_ipv4/ipt_limit.h +++ b/include/linux/netfilter_ipv4/ipt_limit.h @@ -1,21 +1,8 @@ #ifndef _IPT_RATE_H #define _IPT_RATE_H -/* timings are in milliseconds. */ -#define IPT_LIMIT_SCALE 10000 +#include +#define IPT_LIMIT_SCALE XT_LIMIT_SCALE +#define ipt_rateinfo xt_rateinfo -/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490 - seconds, or one every 59 hours. */ -struct ipt_rateinfo { - u_int32_t avg; /* Average secs between packets * scale */ - u_int32_t burst; /* Period multiplier for upper limit. */ - - /* Used internally by the kernel */ - unsigned long prev; - u_int32_t credit; - u_int32_t credit_cap, cost; - - /* Ugly, ugly fucker. */ - struct ipt_rateinfo *master; -}; #endif /*_IPT_RATE_H*/ diff --git a/include/linux/netfilter_ipv4/ipt_mac.h b/include/linux/netfilter_ipv4/ipt_mac.h index f8d5b8e7ccd..b186008a3c4 100644 --- a/include/linux/netfilter_ipv4/ipt_mac.h +++ b/include/linux/netfilter_ipv4/ipt_mac.h @@ -1,8 +1,7 @@ #ifndef _IPT_MAC_H #define _IPT_MAC_H -struct ipt_mac_info { - unsigned char srcaddr[ETH_ALEN]; - int invert; -}; +#include +#define ipt_mac_info xt_mac_info + #endif /*_IPT_MAC_H*/ diff --git a/include/linux/netfilter_ipv4/ipt_mark.h b/include/linux/netfilter_ipv4/ipt_mark.h index f3952b563d4..bfde67c6122 100644 --- a/include/linux/netfilter_ipv4/ipt_mark.h +++ b/include/linux/netfilter_ipv4/ipt_mark.h @@ -1,9 +1,9 @@ #ifndef _IPT_MARK_H #define _IPT_MARK_H -struct ipt_mark_info { - unsigned long mark, mask; - u_int8_t invert; -}; +/* Backwards compatibility for old userspace */ +#include + +#define ipt_mark_info xt_mark_info #endif /*_IPT_MARK_H*/ diff --git a/include/linux/netfilter_ipv4/ipt_physdev.h b/include/linux/netfilter_ipv4/ipt_physdev.h index 7538c8655ec..2400e7140f2 100644 --- a/include/linux/netfilter_ipv4/ipt_physdev.h +++ b/include/linux/netfilter_ipv4/ipt_physdev.h @@ -1,24 +1,17 @@ #ifndef _IPT_PHYSDEV_H #define _IPT_PHYSDEV_H -#ifdef __KERNEL__ -#include -#endif +/* Backwards compatibility for old userspace */ -#define IPT_PHYSDEV_OP_IN 0x01 -#define IPT_PHYSDEV_OP_OUT 0x02 -#define IPT_PHYSDEV_OP_BRIDGED 0x04 -#define IPT_PHYSDEV_OP_ISIN 0x08 -#define IPT_PHYSDEV_OP_ISOUT 0x10 -#define IPT_PHYSDEV_OP_MASK (0x20 - 1) +#include -struct ipt_physdev_info { - char physindev[IFNAMSIZ]; - char in_mask[IFNAMSIZ]; - char physoutdev[IFNAMSIZ]; - char out_mask[IFNAMSIZ]; - u_int8_t invert; - u_int8_t bitmask; -}; +#define IPT_PHYSDEV_OP_IN XT_PHYSDEV_OP_IN +#define IPT_PHYSDEV_OP_OUT XT_PHYSDEV_OP_OUT +#define IPT_PHYSDEV_OP_BRIDGED XT_PHYSDEV_OP_BRIDGED +#define IPT_PHYSDEV_OP_ISIN XT_PHYSDEV_OP_ISIN +#define IPT_PHYSDEV_OP_ISOUT XT_PHYSDEV_OP_ISOUT +#define IPT_PHYSDEV_OP_MASK XT_PHYSDEV_OP_MASK + +#define ipt_physdev_info xt_physdev_info #endif /*_IPT_PHYSDEV_H*/ diff --git a/include/linux/netfilter_ipv4/ipt_pkttype.h b/include/linux/netfilter_ipv4/ipt_pkttype.h index d53a6584868..ff1fbc949a0 100644 --- a/include/linux/netfilter_ipv4/ipt_pkttype.h +++ b/include/linux/netfilter_ipv4/ipt_pkttype.h @@ -1,8 +1,7 @@ #ifndef _IPT_PKTTYPE_H #define _IPT_PKTTYPE_H -struct ipt_pkttype_info { - int pkttype; - int invert; -}; +#include +#define ipt_pkttype_info xt_pkttype_info + #endif /*_IPT_PKTTYPE_H*/ diff --git a/include/linux/netfilter_ipv4/ipt_realm.h b/include/linux/netfilter_ipv4/ipt_realm.h index a4d6698723a..b3996eaa018 100644 --- a/include/linux/netfilter_ipv4/ipt_realm.h +++ b/include/linux/netfilter_ipv4/ipt_realm.h @@ -1,10 +1,7 @@ #ifndef _IPT_REALM_H #define _IPT_REALM_H -struct ipt_realm_info { - u_int32_t id; - u_int32_t mask; - u_int8_t invert; -}; +#include +#define ipt_realm_info xt_realm_info #endif /* _IPT_REALM_H */ diff --git a/include/linux/netfilter_ipv4/ipt_state.h b/include/linux/netfilter_ipv4/ipt_state.h index 5df37868933..a44a99cc28c 100644 --- a/include/linux/netfilter_ipv4/ipt_state.h +++ b/include/linux/netfilter_ipv4/ipt_state.h @@ -1,13 +1,15 @@ #ifndef _IPT_STATE_H #define _IPT_STATE_H -#define IPT_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1)) -#define IPT_STATE_INVALID (1 << 0) +/* Backwards compatibility for old userspace */ -#define IPT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1)) +#include + +#define IPT_STATE_BIT XT_STATE_BIT +#define IPT_STATE_INVALID XT_STATE_INVALID + +#define IPT_STATE_UNTRACKED XT_STATE_UNTRACKED + +#define ipt_state_info xt_state_info -struct ipt_state_info -{ - unsigned int statemask; -}; #endif /*_IPT_STATE_H*/ diff --git a/include/linux/netfilter_ipv4/ipt_string.h b/include/linux/netfilter_ipv4/ipt_string.h index a265f6e44ea..c26de305990 100644 --- a/include/linux/netfilter_ipv4/ipt_string.h +++ b/include/linux/netfilter_ipv4/ipt_string.h @@ -1,18 +1,10 @@ #ifndef _IPT_STRING_H #define _IPT_STRING_H -#define IPT_STRING_MAX_PATTERN_SIZE 128 -#define IPT_STRING_MAX_ALGO_NAME_SIZE 16 +#include -struct ipt_string_info -{ - u_int16_t from_offset; - u_int16_t to_offset; - char algo[IPT_STRING_MAX_ALGO_NAME_SIZE]; - char pattern[IPT_STRING_MAX_PATTERN_SIZE]; - u_int8_t patlen; - u_int8_t invert; - struct ts_config __attribute__((aligned(8))) *config; -}; +#define IPT_STRING_MAX_PATTERN_SIZE XT_STRING_MAX_PATTERN_SIZE +#define IPT_STRING_MAX_ALGO_NAME_SIZE XT_STRING_MAX_ALGO_NAME_SIZE +#define ipt_string_info xt_string_info #endif /*_IPT_STRING_H*/ diff --git a/include/linux/netfilter_ipv4/ipt_tcpmss.h b/include/linux/netfilter_ipv4/ipt_tcpmss.h index e2b14397f70..18bbc8e8e00 100644 --- a/include/linux/netfilter_ipv4/ipt_tcpmss.h +++ b/include/linux/netfilter_ipv4/ipt_tcpmss.h @@ -1,9 +1,7 @@ #ifndef _IPT_TCPMSS_MATCH_H #define _IPT_TCPMSS_MATCH_H -struct ipt_tcpmss_match_info { - u_int16_t mss_min, mss_max; - u_int8_t invert; -}; +#include +#define ipt_tcpmss_match_info xt_tcpmss_match_info #endif /*_IPT_TCPMSS_MATCH_H*/ diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h index c163ba31aab..f249b574f0f 100644 --- a/include/linux/netfilter_ipv6/ip6_tables.h +++ b/include/linux/netfilter_ipv6/ip6_tables.h @@ -25,8 +25,15 @@ #include #include -#define IP6T_FUNCTION_MAXNAMELEN 30 -#define IP6T_TABLE_MAXNAMELEN 32 +#include + +#define IP6T_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN +#define IP6T_TABLE_MAXNAMELEN XT_TABLE_MAXNAMELEN + +#define ip6t_match xt_match +#define ip6t_target xt_target +#define ip6t_table xt_table +#define ip6t_get_revision xt_get_revision /* Yes, Virginia, you have to zero the padding. */ struct ip6t_ip6 { @@ -104,10 +111,7 @@ struct ip6t_standard_target int verdict; }; -struct ip6t_counters -{ - u_int64_t pcnt, bcnt; /* Packet and byte counters */ -}; +#define ip6t_counters xt_counters /* Values for "flag" field in struct ip6t_ip6 (general ip6 structure). */ #define IP6T_F_PROTO 0x01 /* Set if rule cares about upper @@ -123,7 +127,7 @@ struct ip6t_counters #define IP6T_INV_SRCIP 0x08 /* Invert the sense of SRC IP. */ #define IP6T_INV_DSTIP 0x10 /* Invert the sense of DST OP. */ #define IP6T_INV_FRAG 0x20 /* Invert the sense of FRAG. */ -#define IP6T_INV_PROTO 0x40 /* Invert the sense of PROTO. */ +#define IP6T_INV_PROTO XT_INV_PROTO #define IP6T_INV_MASK 0x7F /* All possible flag bits mask. */ /* This structure defines each of the firewall rules. Consists of 3 @@ -145,7 +149,7 @@ struct ip6t_entry unsigned int comefrom; /* Packet and byte counters. */ - struct ip6t_counters counters; + struct xt_counters counters; /* The matches (if any), then the target. */ unsigned char elems[0]; @@ -155,54 +159,41 @@ struct ip6t_entry * New IP firewall options for [gs]etsockopt at the RAW IP level. * Unlike BSD Linux inherits IP options so you don't have to use * a raw socket for this. Instead we check rights in the calls. */ -#define IP6T_BASE_CTL 64 /* base for firewall socket options */ +#define IP6T_BASE_CTL XT_BASE_CTL -#define IP6T_SO_SET_REPLACE (IP6T_BASE_CTL) -#define IP6T_SO_SET_ADD_COUNTERS (IP6T_BASE_CTL + 1) -#define IP6T_SO_SET_MAX IP6T_SO_SET_ADD_COUNTERS +#define IP6T_SO_SET_REPLACE XT_SO_SET_REPLACE +#define IP6T_SO_SET_ADD_COUNTERS XT_SO_SET_ADD_COUNTERS +#define IP6T_SO_SET_MAX XT_SO_SET_MAX -#define IP6T_SO_GET_INFO (IP6T_BASE_CTL) -#define IP6T_SO_GET_ENTRIES (IP6T_BASE_CTL + 1) -#define IP6T_SO_GET_REVISION_MATCH (IP6T_BASE_CTL + 2) -#define IP6T_SO_GET_REVISION_TARGET (IP6T_BASE_CTL + 3) -#define IP6T_SO_GET_MAX IP6T_SO_GET_REVISION_TARGET +#define IP6T_SO_GET_INFO XT_SO_GET_INFO +#define IP6T_SO_GET_ENTRIES XT_SO_GET_ENTRIES +#define IP6T_SO_GET_REVISION_MATCH XT_SO_GET_REVISION_MATCH +#define IP6T_SO_GET_REVISION_TARGET XT_SO_GET_REVISION_TARGET +#define IP6T_SO_GET_MAX XT_SO_GET_REVISION_TARGET /* CONTINUE verdict for targets */ -#define IP6T_CONTINUE 0xFFFFFFFF +#define IP6T_CONTINUE XT_CONTINUE /* For standard target */ -#define IP6T_RETURN (-NF_REPEAT - 1) +#define IP6T_RETURN XT_RETURN -/* TCP matching stuff */ -struct ip6t_tcp -{ - u_int16_t spts[2]; /* Source port range. */ - u_int16_t dpts[2]; /* Destination port range. */ - u_int8_t option; /* TCP Option iff non-zero*/ - u_int8_t flg_mask; /* TCP flags mask byte */ - u_int8_t flg_cmp; /* TCP flags compare byte */ - u_int8_t invflags; /* Inverse flags */ -}; +/* TCP/UDP matching stuff */ +#include + +#define ip6t_tcp xt_tcp +#define ip6t_udp xt_udp /* Values for "inv" field in struct ipt_tcp. */ -#define IP6T_TCP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ -#define IP6T_TCP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ -#define IP6T_TCP_INV_FLAGS 0x04 /* Invert the sense of TCP flags. */ -#define IP6T_TCP_INV_OPTION 0x08 /* Invert the sense of option test. */ -#define IP6T_TCP_INV_MASK 0x0F /* All possible flags. */ - -/* UDP matching stuff */ -struct ip6t_udp -{ - u_int16_t spts[2]; /* Source port range. */ - u_int16_t dpts[2]; /* Destination port range. */ - u_int8_t invflags; /* Inverse flags */ -}; +#define IP6T_TCP_INV_SRCPT XT_TCP_INV_SRCPT +#define IP6T_TCP_INV_DSTPT XT_TCP_INV_DSTPT +#define IP6T_TCP_INV_FLAGS XT_TCP_INV_FLAGS +#define IP6T_TCP_INV_OPTION XT_TCP_INV_OPTION +#define IP6T_TCP_INV_MASK XT_TCP_INV_MASK /* Values for "invflags" field in struct ipt_udp. */ -#define IP6T_UDP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ -#define IP6T_UDP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ -#define IP6T_UDP_INV_MASK 0x03 /* All possible flags. */ +#define IP6T_UDP_INV_SRCPT XT_UDP_INV_SRCPT +#define IP6T_UDP_INV_DSTPT XT_UDP_INV_DSTPT +#define IP6T_UDP_INV_MASK XT_UDP_INV_MASK /* ICMP matching stuff */ struct ip6t_icmp @@ -264,23 +255,14 @@ struct ip6t_replace /* Number of counters (must be equal to current number of entries). */ unsigned int num_counters; /* The old entries' counters. */ - struct ip6t_counters __user *counters; + struct xt_counters __user *counters; /* The entries (hang off end: not really an array). */ struct ip6t_entry entries[0]; }; /* The argument to IP6T_SO_ADD_COUNTERS. */ -struct ip6t_counters_info -{ - /* Which table. */ - char name[IP6T_TABLE_MAXNAMELEN]; - - unsigned int num_counters; - - /* The counters (actually `number' of these). */ - struct ip6t_counters counters[0]; -}; +#define ip6t_counters_info xt_counters_info /* The argument to IP6T_SO_GET_ENTRIES. */ struct ip6t_get_entries @@ -295,19 +277,10 @@ struct ip6t_get_entries struct ip6t_entry entrytable[0]; }; -/* The argument to IP6T_SO_GET_REVISION_*. Returns highest revision - * kernel supports, if >= revision. */ -struct ip6t_get_revision -{ - char name[IP6T_FUNCTION_MAXNAMELEN-1]; - - u_int8_t revision; -}; - /* Standard return verdict, or do jump. */ -#define IP6T_STANDARD_TARGET "" +#define IP6T_STANDARD_TARGET XT_STANDARD_TARGET /* Error verdict. */ -#define IP6T_ERROR_TARGET "ERROR" +#define IP6T_ERROR_TARGET XT_ERROR_TARGET /* Helper functions */ static __inline__ struct ip6t_entry_target * @@ -361,104 +334,11 @@ ip6t_get_target(struct ip6t_entry *e) #include extern void ip6t_init(void) __init; -struct ip6t_match -{ - struct list_head list; - - const char name[IP6T_FUNCTION_MAXNAMELEN-1]; - - u_int8_t revision; - - /* Return true or false: return FALSE and set *hotdrop = 1 to - force immediate packet drop. */ - /* Arguments changed since 2.6.9, as this must now handle - non-linear skb, using skb_header_pointer and - skb_ip_make_writable. */ - int (*match)(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const void *matchinfo, - int offset, - unsigned int protoff, - int *hotdrop); - - /* Called when user tries to insert an entry of this type. */ - /* Should return true or false. */ - int (*checkentry)(const char *tablename, - const struct ip6t_ip6 *ip, - void *matchinfo, - unsigned int matchinfosize, - unsigned int hook_mask); - - /* Called when entry of this type deleted. */ - void (*destroy)(void *matchinfo, unsigned int matchinfosize); - - /* Set this to THIS_MODULE if you are a module, otherwise NULL */ - struct module *me; -}; - -/* Registration hooks for targets. */ -struct ip6t_target -{ - struct list_head list; - - const char name[IP6T_FUNCTION_MAXNAMELEN-1]; - - u_int8_t revision; - - /* Returns verdict. Argument order changed since 2.6.9, as this - must now handle non-linear skbs, using skb_copy_bits and - skb_ip_make_writable. */ - unsigned int (*target)(struct sk_buff **pskb, - const struct net_device *in, - const struct net_device *out, - unsigned int hooknum, - const void *targinfo, - void *userdata); - - /* Called when user tries to insert an entry of this type: - hook_mask is a bitmask of hooks from which it can be - called. */ - /* Should return true or false. */ - int (*checkentry)(const char *tablename, - const struct ip6t_entry *e, - void *targinfo, - unsigned int targinfosize, - unsigned int hook_mask); - - /* Called when entry of this type deleted. */ - void (*destroy)(void *targinfo, unsigned int targinfosize); - - /* Set this to THIS_MODULE if you are a module, otherwise NULL */ - struct module *me; -}; - -extern int ip6t_register_target(struct ip6t_target *target); -extern void ip6t_unregister_target(struct ip6t_target *target); - -extern int ip6t_register_match(struct ip6t_match *match); -extern void ip6t_unregister_match(struct ip6t_match *match); +#define ip6t_register_target(tgt) xt_register_target(AF_INET6, tgt) +#define ip6t_unregister_target(tgt) xt_unregister_target(AF_INET6, tgt) -/* Furniture shopping... */ -struct ip6t_table -{ - struct list_head list; - - /* A unique name... */ - char name[IP6T_TABLE_MAXNAMELEN]; - - /* What hooks you will enter on */ - unsigned int valid_hooks; - - /* Lock for the curtain */ - rwlock_t lock; - - /* Man behind the curtain... */ - struct ip6t_table_info *private; - - /* Set this to THIS_MODULE if you are a module, otherwise NULL */ - struct module *me; -}; +#define ip6t_register_match(match) xt_register_match(AF_INET6, match) +#define ip6t_unregister_match(match) xt_unregister_match(AF_INET6, match) extern int ip6t_register_table(struct ip6t_table *table, const struct ip6t_replace *repl); diff --git a/include/linux/netfilter_ipv6/ip6t_MARK.h b/include/linux/netfilter_ipv6/ip6t_MARK.h index 7ade8d8f524..7cf629a8ab9 100644 --- a/include/linux/netfilter_ipv6/ip6t_MARK.h +++ b/include/linux/netfilter_ipv6/ip6t_MARK.h @@ -1,8 +1,9 @@ #ifndef _IP6T_MARK_H_target #define _IP6T_MARK_H_target -struct ip6t_mark_target_info { - unsigned long mark; -}; +/* Backwards compatibility for old userspace */ +#include -#endif /*_IPT_MARK_H_target*/ +#define ip6t_mark_target_info xt_mark_target_info + +#endif /*_IP6T_MARK_H_target*/ diff --git a/include/linux/netfilter_ipv6/ip6t_length.h b/include/linux/netfilter_ipv6/ip6t_length.h index 7fc09f9f9d6..9e9689d03ed 100644 --- a/include/linux/netfilter_ipv6/ip6t_length.h +++ b/include/linux/netfilter_ipv6/ip6t_length.h @@ -1,10 +1,8 @@ #ifndef _IP6T_LENGTH_H #define _IP6T_LENGTH_H -struct ip6t_length_info { - u_int16_t min, max; - u_int8_t invert; -}; +#include +#define ip6t_length_info xt_length_info #endif /*_IP6T_LENGTH_H*/ diff --git a/include/linux/netfilter_ipv6/ip6t_limit.h b/include/linux/netfilter_ipv6/ip6t_limit.h index f2866e50f3b..487e5ea342c 100644 --- a/include/linux/netfilter_ipv6/ip6t_limit.h +++ b/include/linux/netfilter_ipv6/ip6t_limit.h @@ -1,21 +1,8 @@ #ifndef _IP6T_RATE_H #define _IP6T_RATE_H -/* timings are in milliseconds. */ -#define IP6T_LIMIT_SCALE 10000 +#include +#define IP6T_LIMIT_SCALE XT_LIMIT_SCALE +#define ip6t_rateinfo xt_rateinfo -/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490 - seconds, or one every 59 hours. */ -struct ip6t_rateinfo { - u_int32_t avg; /* Average secs between packets * scale */ - u_int32_t burst; /* Period multiplier for upper limit. */ - - /* Used internally by the kernel */ - unsigned long prev; - u_int32_t credit; - u_int32_t credit_cap, cost; - - /* Ugly, ugly fucker. */ - struct ip6t_rateinfo *master; -}; -#endif /*_IPT_RATE_H*/ +#endif /*_IP6T_RATE_H*/ diff --git a/include/linux/netfilter_ipv6/ip6t_mac.h b/include/linux/netfilter_ipv6/ip6t_mac.h index 87c088c2184..ac58e83e942 100644 --- a/include/linux/netfilter_ipv6/ip6t_mac.h +++ b/include/linux/netfilter_ipv6/ip6t_mac.h @@ -1,8 +1,7 @@ #ifndef _IP6T_MAC_H #define _IP6T_MAC_H -struct ip6t_mac_info { - unsigned char srcaddr[ETH_ALEN]; - int invert; -}; -#endif /*_IPT_MAC_H*/ +#include +#define ip6t_mac_info xt_mac_info + +#endif /*_IP6T_MAC_H*/ diff --git a/include/linux/netfilter_ipv6/ip6t_mark.h b/include/linux/netfilter_ipv6/ip6t_mark.h index a734441e1c1..ff204951ddc 100644 --- a/include/linux/netfilter_ipv6/ip6t_mark.h +++ b/include/linux/netfilter_ipv6/ip6t_mark.h @@ -1,9 +1,9 @@ #ifndef _IP6T_MARK_H #define _IP6T_MARK_H -struct ip6t_mark_info { - unsigned long mark, mask; - u_int8_t invert; -}; +/* Backwards compatibility for old userspace */ +#include + +#define ip6t_mark_info xt_mark_info #endif /*_IPT_MARK_H*/ diff --git a/include/linux/netfilter_ipv6/ip6t_physdev.h b/include/linux/netfilter_ipv6/ip6t_physdev.h index c234731cd66..c161c0a81b5 100644 --- a/include/linux/netfilter_ipv6/ip6t_physdev.h +++ b/include/linux/netfilter_ipv6/ip6t_physdev.h @@ -1,24 +1,17 @@ #ifndef _IP6T_PHYSDEV_H #define _IP6T_PHYSDEV_H -#ifdef __KERNEL__ -#include -#endif +/* Backwards compatibility for old userspace */ -#define IP6T_PHYSDEV_OP_IN 0x01 -#define IP6T_PHYSDEV_OP_OUT 0x02 -#define IP6T_PHYSDEV_OP_BRIDGED 0x04 -#define IP6T_PHYSDEV_OP_ISIN 0x08 -#define IP6T_PHYSDEV_OP_ISOUT 0x10 -#define IP6T_PHYSDEV_OP_MASK (0x20 - 1) +#include -struct ip6t_physdev_info { - char physindev[IFNAMSIZ]; - char in_mask[IFNAMSIZ]; - char physoutdev[IFNAMSIZ]; - char out_mask[IFNAMSIZ]; - u_int8_t invert; - u_int8_t bitmask; -}; +#define IP6T_PHYSDEV_OP_IN XT_PHYSDEV_OP_IN +#define IP6T_PHYSDEV_OP_OUT XT_PHYSDEV_OP_OUT +#define IP6T_PHYSDEV_OP_BRIDGED XT_PHYSDEV_OP_BRIDGED +#define IP6T_PHYSDEV_OP_ISIN XT_PHYSDEV_OP_ISIN +#define IP6T_PHYSDEV_OP_ISOUT XT_PHYSDEV_OP_ISOUT +#define IP6T_PHYSDEV_OP_MASK XT_PHYSDEV_OP_MASK + +#define ip6t_physdev_info xt_physdev_info #endif /*_IP6T_PHYSDEV_H*/ diff --git a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h index 25b081a730e..91684436af8 100644 --- a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h +++ b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h @@ -37,7 +37,4 @@ struct nf_conntrack_ipv4 { struct sk_buff * nf_ct_ipv4_ct_gather_frags(struct sk_buff *skb); -/* call to create an explicit dependency on nf_conntrack_l3proto_ipv4. */ -extern void need_ip_conntrack(void); - #endif /*_NF_CONNTRACK_IPV4_H*/ diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 64b82b74a65..6d075ca16e6 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -221,9 +221,6 @@ extern void nf_ct_helper_put(struct nf_conntrack_helper *helper); extern struct nf_conntrack_helper * __nf_conntrack_helper_find_byname(const char *name); -/* call to create an explicit dependency on nf_conntrack. */ -extern void need_nf_conntrack(void); - extern int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse, const struct nf_conntrack_tuple *orig); diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c index 9f6e0193ae1..a29c1232c42 100644 --- a/net/bridge/netfilter/ebt_log.c +++ b/net/bridge/netfilter/ebt_log.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index a9893ec03e0..db783036e4d 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -182,6 +182,7 @@ config IP_NF_QUEUE config IP_NF_IPTABLES tristate "IP tables support (required for filtering/masq/NAT)" + depends on NETFILTER_XTABLES help iptables is a general, extensible packet identification framework. The packet filtering and full NAT (masquerading, port forwarding, @@ -191,16 +192,6 @@ config IP_NF_IPTABLES To compile it as a module, choose M here. If unsure, say N. # The matches. -config IP_NF_MATCH_LIMIT - tristate "limit match support" - depends on IP_NF_IPTABLES - help - limit matching allows you to control the rate at which a rule can be - matched: mainly useful in combination with the LOG target ("LOG - target support", below) and to avoid some Denial of Service attacks. - - To compile it as a module, choose M here. If unsure, say N. - config IP_NF_MATCH_IPRANGE tristate "IP range match support" depends on IP_NF_IPTABLES @@ -210,37 +201,6 @@ config IP_NF_MATCH_IPRANGE To compile it as a module, choose M here. If unsure, say N. -config IP_NF_MATCH_MAC - tristate "MAC address match support" - depends on IP_NF_IPTABLES - help - MAC matching allows you to match packets based on the source - Ethernet address of the packet. - - To compile it as a module, choose M here. If unsure, say N. - -config IP_NF_MATCH_PKTTYPE - tristate "Packet type match support" - depends on IP_NF_IPTABLES - help - Packet type matching allows you to match a packet by - its "class", eg. BROADCAST, MULTICAST, ... - - Typical usage: - iptables -A INPUT -m pkttype --pkt-type broadcast -j LOG - - To compile it as a module, choose M here. If unsure, say N. - -config IP_NF_MATCH_MARK - tristate "netfilter MARK match support" - depends on IP_NF_IPTABLES - help - Netfilter mark matching allows you to match packets based on the - `nfmark' value in the packet. This can be set by the MARK target - (see below). - - To compile it as a module, choose M here. If unsure, say N. - config IP_NF_MATCH_MULTIPORT tristate "Multiple port match support" depends on IP_NF_IPTABLES @@ -301,15 +261,6 @@ config IP_NF_MATCH_AH_ESP To compile it as a module, choose M here. If unsure, say N. -config IP_NF_MATCH_LENGTH - tristate "LENGTH match support" - depends on IP_NF_IPTABLES - help - This option allows you to match the length of a packet against a - specific value or range of values. - - To compile it as a module, choose M here. If unsure, say N. - config IP_NF_MATCH_TTL tristate "TTL match support" depends on IP_NF_IPTABLES @@ -319,50 +270,6 @@ config IP_NF_MATCH_TTL To compile it as a module, choose M here. If unsure, say N. -config IP_NF_MATCH_TCPMSS - tristate "tcpmss match support" - depends on IP_NF_IPTABLES - help - This option adds a `tcpmss' match, which allows you to examine the - MSS value of TCP SYN packets, which control the maximum packet size - for that connection. - - To compile it as a module, choose M here. If unsure, say N. - -config IP_NF_MATCH_HELPER - tristate "Helper match support" - depends on IP_NF_IPTABLES - depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4 - help - Helper matching allows you to match packets in dynamic connections - tracked by a conntrack-helper, ie. ip_conntrack_ftp - - To compile it as a module, choose M here. If unsure, say Y. - -config IP_NF_MATCH_STATE - tristate "Connection state match support" - depends on IP_NF_IPTABLES - depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4 - help - Connection state matching allows you to match packets based on their - relationship to a tracked connection (ie. previous packets). This - is a powerful tool for packet classification. - - To compile it as a module, choose M here. If unsure, say N. - -config IP_NF_MATCH_CONNTRACK - tristate "Connection tracking match support" - depends on IP_NF_IPTABLES - depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4 - help - This is a general conntrack match module, a superset of the state match. - - It allows matching on additional conntrack information, which is - useful in complex configurations, such as NAT gateways with multiple - internet links or tunnels. - - To compile it as a module, choose M here. If unsure, say N. - config IP_NF_MATCH_OWNER tristate "Owner match support" depends on IP_NF_IPTABLES @@ -372,15 +279,6 @@ config IP_NF_MATCH_OWNER To compile it as a module, choose M here. If unsure, say N. -config IP_NF_MATCH_PHYSDEV - tristate "Physdev match support" - depends on IP_NF_IPTABLES && BRIDGE_NETFILTER - help - Physdev packet matching matches against the physical bridge ports - the IP packet arrived on or will leave by. - - To compile it as a module, choose M here. If unsure, say N. - config IP_NF_MATCH_ADDRTYPE tristate 'address type match support' depends on IP_NF_IPTABLES @@ -391,75 +289,6 @@ config IP_NF_MATCH_ADDRTYPE If you want to compile it as a module, say M here and read . If unsure, say `N'. -config IP_NF_MATCH_REALM - tristate 'realm match support' - depends on IP_NF_IPTABLES - select NET_CLS_ROUTE - help - This option adds a `realm' match, which allows you to use the realm - key from the routing subsystem inside iptables. - - This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option - in tc world. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -config IP_NF_MATCH_SCTP - tristate 'SCTP protocol match support' - depends on IP_NF_IPTABLES - help - With this option enabled, you will be able to use the iptables - `sctp' match in order to match on SCTP source/destination ports - and SCTP chunk types. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -config IP_NF_MATCH_DCCP - tristate 'DCCP protocol match support' - depends on IP_NF_IPTABLES - help - With this option enabled, you will be able to use the iptables - `dccp' match in order to match on DCCP source/destination ports - and DCCP flags. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -config IP_NF_MATCH_COMMENT - tristate 'comment match support' - depends on IP_NF_IPTABLES - help - This option adds a `comment' dummy-match, which allows you to put - comments in your iptables ruleset. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - -config IP_NF_MATCH_CONNMARK - tristate 'Connection mark match support' - depends on IP_NF_IPTABLES - depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4) - help - This option adds a `connmark' match, which allows you to match the - connection mark value previously set for the session by `CONNMARK'. - - If you want to compile it as a module, say M here and read - . The module will be called - ipt_connmark.o. If unsure, say `N'. - -config IP_NF_MATCH_CONNBYTES - tristate 'Connection byte/packet counter match support' - depends on IP_NF_IPTABLES - depends on (IP_NF_CONNTRACK && IP_NF_CT_ACCT) || (NF_CT_ACCT && NF_CONNTRACK_IPV4) - help - This option adds a `connbytes' match, which allows you to match the - number of bytes and/or packets for each direction within a connection. - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - config IP_NF_MATCH_HASHLIMIT tristate 'hashlimit match support' depends on IP_NF_IPTABLES @@ -474,19 +303,6 @@ config IP_NF_MATCH_HASHLIMIT destination IP' or `500pps from any given source IP' with a single IPtables rule. -config IP_NF_MATCH_STRING - tristate 'string match support' - depends on IP_NF_IPTABLES - select TEXTSEARCH - select TEXTSEARCH_KMP - select TEXTSEARCH_BM - select TEXTSEARCH_FSM - help - This option adds a `string' match, which allows you to look for - pattern matchings in packets. - - To compile it as a module, choose M here. If unsure, say N. - config IP_NF_MATCH_POLICY tristate "IPsec policy match support" depends on IP_NF_IPTABLES && XFRM @@ -572,17 +388,6 @@ config IP_NF_TARGET_TCPMSS To compile it as a module, choose M here. If unsure, say N. -config IP_NF_TARGET_NFQUEUE - tristate "NFQUEUE Target Support" - depends on IP_NF_IPTABLES - help - This Target replaced the old obsolete QUEUE target. - - As opposed to QUEUE, it supports 65535 different queues, - not just one. - - To compile it as a module, choose M here. If unsure, say N. - # NAT + specific targets config IP_NF_NAT tristate "Full NAT" @@ -735,31 +540,6 @@ config IP_NF_TARGET_DSCP To compile it as a module, choose M here. If unsure, say N. -config IP_NF_TARGET_MARK - tristate "MARK target support" - depends on IP_NF_MANGLE - help - This option adds a `MARK' target, which allows you to create rules - in the `mangle' table which alter the netfilter mark (nfmark) field - associated with the packet prior to routing. This can change - the routing method (see `Use netfilter MARK value as routing - key') and can also be used by other subsystems to change their - behavior. - - To compile it as a module, choose M here. If unsure, say N. - -config IP_NF_TARGET_CLASSIFY - tristate "CLASSIFY target support" - depends on IP_NF_MANGLE - help - This option adds a `CLASSIFY' target, which enables the user to set - the priority of a packet. Some qdiscs can use this value for - classification, among these are: - - atm, cbq, dsmark, pfifo_fast, htb, prio - - To compile it as a module, choose M here. If unsure, say N. - config IP_NF_TARGET_TTL tristate 'TTL target support' depends on IP_NF_MANGLE @@ -774,19 +554,6 @@ config IP_NF_TARGET_TTL To compile it as a module, choose M here. If unsure, say N. -config IP_NF_TARGET_CONNMARK - tristate 'CONNMARK target support' - depends on IP_NF_MANGLE - depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4) - help - This option adds a `CONNMARK' target, which allows one to manipulate - the connection mark value. Similar to the MARK target, but - affects the connection mark value rather than the packet mark value. - - If you want to compile it as a module, say M here and read - . The module will be called - ipt_CONNMARK.o. If unsure, say `N'. - config IP_NF_TARGET_CLUSTERIP tristate "CLUSTERIP target support (EXPERIMENTAL)" depends on IP_NF_MANGLE && EXPERIMENTAL @@ -810,23 +577,10 @@ config IP_NF_RAW If you want to compile it as a module, say M here and read . If unsure, say `N'. -config IP_NF_TARGET_NOTRACK - tristate 'NOTRACK target support' - depends on IP_NF_RAW - depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4 - help - The NOTRACK target allows a select rule to specify - which packets *not* to enter the conntrack/NAT - subsystem with all the consequences (no ICMP error tracking, - no protocol helpers for the selected packets). - - If you want to compile it as a module, say M here and read - . If unsure, say `N'. - - # ARP tables config IP_NF_ARPTABLES tristate "ARP tables support" + depends on NETFILTER_XTABLES help arptables is a general, extensible packet identification framework. The ARP packet filtering and mangling (manipulation)subsystems diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index 549b01a648b..bcefe64b931 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile @@ -47,14 +47,8 @@ obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o # matches obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o -obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o -obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o -obj-$(CONFIG_IP_NF_MATCH_DCCP) += ipt_dccp.o -obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o -obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o -obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o @@ -62,40 +56,25 @@ obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o -obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o -obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o -obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o -obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o -obj-$(CONFIG_IP_NF_MATCH_CONNBYTES) += ipt_connbytes.o -obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o -obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o -obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o -obj-$(CONFIG_IP_NF_MATCH_COMMENT) += ipt_comment.o -obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o # targets obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o -obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o -obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o -obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o -obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o -obj-$(CONFIG_IP_NF_TARGET_NFQUEUE) += ipt_NFQUEUE.o # generic ARP tables obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index b6d5284c802..afe3d8f8177 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -24,6 +24,7 @@ #include #include +#include #include MODULE_LICENSE("GPL"); @@ -55,28 +56,9 @@ do { \ #else #define ARP_NF_ASSERT(x) #endif -#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) -static DECLARE_MUTEX(arpt_mutex); - -#define ASSERT_READ_LOCK(x) ARP_NF_ASSERT(down_trylock(&arpt_mutex) != 0) -#define ASSERT_WRITE_LOCK(x) ARP_NF_ASSERT(down_trylock(&arpt_mutex) != 0) #include -struct arpt_table_info { - unsigned int size; - unsigned int number; - unsigned int initial_entries; - unsigned int hook_entry[NF_ARP_NUMHOOKS]; - unsigned int underflow[NF_ARP_NUMHOOKS]; - void *entries[NR_CPUS]; -}; - -static LIST_HEAD(arpt_target); -static LIST_HEAD(arpt_tables); -#define SET_COUNTER(c,b,p) do { (c).bcnt = (b); (c).pcnt = (p); } while(0) -#define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0) - static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap, char *hdr_addr, int len) { @@ -223,9 +205,9 @@ static inline int arp_checkentry(const struct arpt_arp *arp) } static unsigned int arpt_error(struct sk_buff **pskb, - unsigned int hooknum, const struct net_device *in, const struct net_device *out, + unsigned int hooknum, const void *targinfo, void *userinfo) { @@ -254,6 +236,7 @@ unsigned int arpt_do_table(struct sk_buff **pskb, struct arpt_entry *e, *back; const char *indev, *outdev; void *table_base; + struct xt_table_info *private = table->private; /* ARP header, plus 2 device addresses, plus 2 IP addresses. */ if (!pskb_may_pull((*pskb), (sizeof(struct arphdr) + @@ -265,9 +248,9 @@ unsigned int arpt_do_table(struct sk_buff **pskb, outdev = out ? out->name : nulldevname; read_lock_bh(&table->lock); - table_base = (void *)table->private->entries[smp_processor_id()]; - e = get_entry(table_base, table->private->hook_entry[hook]); - back = get_entry(table_base, table->private->underflow[hook]); + table_base = (void *)private->entries[smp_processor_id()]; + e = get_entry(table_base, private->hook_entry[hook]); + back = get_entry(table_base, private->underflow[hook]); arp = (*pskb)->nh.arph; do { @@ -315,8 +298,8 @@ unsigned int arpt_do_table(struct sk_buff **pskb, * abs. verdicts */ verdict = t->u.kernel.target->target(pskb, - hook, in, out, + hook, t->data, userdata); @@ -341,106 +324,6 @@ unsigned int arpt_do_table(struct sk_buff **pskb, return verdict; } -/* - * These are weird, but module loading must not be done with mutex - * held (since they will register), and we have to have a single - * function to use try_then_request_module(). - */ - -/* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */ -static inline struct arpt_table *find_table_lock(const char *name) -{ - struct arpt_table *t; - - if (down_interruptible(&arpt_mutex) != 0) - return ERR_PTR(-EINTR); - - list_for_each_entry(t, &arpt_tables, list) - if (strcmp(t->name, name) == 0 && try_module_get(t->me)) - return t; - up(&arpt_mutex); - return NULL; -} - - -/* Find target, grabs ref. Returns ERR_PTR() on error. */ -static inline struct arpt_target *find_target(const char *name, u8 revision) -{ - struct arpt_target *t; - int err = 0; - - if (down_interruptible(&arpt_mutex) != 0) - return ERR_PTR(-EINTR); - - list_for_each_entry(t, &arpt_target, list) { - if (strcmp(t->name, name) == 0) { - if (t->revision == revision) { - if (try_module_get(t->me)) { - up(&arpt_mutex); - return t; - } - } else - err = -EPROTOTYPE; /* Found something. */ - } - } - up(&arpt_mutex); - return ERR_PTR(err); -} - -struct arpt_target *arpt_find_target(const char *name, u8 revision) -{ - struct arpt_target *target; - - target = try_then_request_module(find_target(name, revision), - "arpt_%s", name); - if (IS_ERR(target) || !target) - return NULL; - return target; -} - -static int target_revfn(const char *name, u8 revision, int *bestp) -{ - struct arpt_target *t; - int have_rev = 0; - - list_for_each_entry(t, &arpt_target, list) { - if (strcmp(t->name, name) == 0) { - if (t->revision > *bestp) - *bestp = t->revision; - if (t->revision == revision) - have_rev =1; - } - } - return have_rev; -} - -/* Returns true or false (if no such extension at all) */ -static inline int find_revision(const char *name, u8 revision, - int (*revfn)(const char *, u8, int *), - int *err) -{ - int have_rev, best = -1; - - if (down_interruptible(&arpt_mutex) != 0) { - *err = -EINTR; - return 1; - } - have_rev = revfn(name, revision, &best); - up(&arpt_mutex); - - /* Nothing at all? Return 0 to try loading module. */ - if (best == -1) { - *err = -ENOENT; - return 0; - } - - *err = best; - if (!have_rev) - *err = -EPROTONOSUPPORT; - return 1; -} - - /* All zeroes == unconditional rule. */ static inline int unconditional(const struct arpt_arp *arp) { @@ -456,7 +339,7 @@ static inline int unconditional(const struct arpt_arp *arp) /* Figures out from what hook each rule can be called: returns 0 if * there are loops. Puts hook bitmask in comefrom. */ -static int mark_source_chains(struct arpt_table_info *newinfo, +static int mark_source_chains(struct xt_table_info *newinfo, unsigned int valid_hooks, void *entry0) { unsigned int hook; @@ -587,8 +470,8 @@ static inline int check_entry(struct arpt_entry *e, const char *name, unsigned i } t = arpt_get_target(e); - target = try_then_request_module(find_target(t->u.user.name, - t->u.user.revision), + target = try_then_request_module(xt_find_target(NF_ARP, t->u.user.name, + t->u.user.revision), "arpt_%s", t->u.user.name); if (IS_ERR(target) || !target) { duprintf("check_entry: `%s' not found\n", t->u.user.name); @@ -622,7 +505,7 @@ out: } static inline int check_entry_size_and_hooks(struct arpt_entry *e, - struct arpt_table_info *newinfo, + struct xt_table_info *newinfo, unsigned char *base, unsigned char *limit, const unsigned int *hook_entries, @@ -656,7 +539,7 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e, < 0 (not ARPT_RETURN). --RR */ /* Clear counters and comefrom */ - e->counters = ((struct arpt_counters) { 0, 0 }); + e->counters = ((struct xt_counters) { 0, 0 }); e->comefrom = 0; (*i)++; @@ -683,7 +566,7 @@ static inline int cleanup_entry(struct arpt_entry *e, unsigned int *i) */ static int translate_table(const char *name, unsigned int valid_hooks, - struct arpt_table_info *newinfo, + struct xt_table_info *newinfo, void *entry0, unsigned int size, unsigned int number, @@ -764,34 +647,9 @@ static int translate_table(const char *name, return ret; } -static struct arpt_table_info *replace_table(struct arpt_table *table, - unsigned int num_counters, - struct arpt_table_info *newinfo, - int *error) -{ - struct arpt_table_info *oldinfo; - - /* Do the substitution. */ - write_lock_bh(&table->lock); - /* Check inside lock: is the old number correct? */ - if (num_counters != table->private->number) { - duprintf("num_counters != table->private->number (%u/%u)\n", - num_counters, table->private->number); - write_unlock_bh(&table->lock); - *error = -EAGAIN; - return NULL; - } - oldinfo = table->private; - table->private = newinfo; - newinfo->initial_entries = oldinfo->initial_entries; - write_unlock_bh(&table->lock); - - return oldinfo; -} - /* Gets counters. */ static inline int add_entry_to_counter(const struct arpt_entry *e, - struct arpt_counters total[], + struct xt_counters total[], unsigned int *i) { ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); @@ -801,7 +659,7 @@ static inline int add_entry_to_counter(const struct arpt_entry *e, } static inline int set_entry_to_counter(const struct arpt_entry *e, - struct arpt_counters total[], + struct xt_counters total[], unsigned int *i) { SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); @@ -810,8 +668,8 @@ static inline int set_entry_to_counter(const struct arpt_entry *e, return 0; } -static void get_counters(const struct arpt_table_info *t, - struct arpt_counters counters[]) +static void get_counters(const struct xt_table_info *t, + struct xt_counters counters[]) { unsigned int cpu; unsigned int i; @@ -849,7 +707,8 @@ static int copy_entries_to_user(unsigned int total_size, { unsigned int off, num, countersize; struct arpt_entry *e; - struct arpt_counters *counters; + struct xt_counters *counters; + struct xt_table_info *private = table->private; int ret = 0; void *loc_cpu_entry; @@ -857,18 +716,18 @@ static int copy_entries_to_user(unsigned int total_size, * (other than comefrom, which userspace doesn't care * about). */ - countersize = sizeof(struct arpt_counters) * table->private->number; - counters = vmalloc(countersize); + countersize = sizeof(struct xt_counters) * private->number; + counters = vmalloc_node(countersize, numa_node_id()); if (counters == NULL) return -ENOMEM; /* First, sum counters... */ write_lock_bh(&table->lock); - get_counters(table->private, counters); + get_counters(private, counters); write_unlock_bh(&table->lock); - loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; + loc_cpu_entry = private->entries[raw_smp_processor_id()]; /* ... then copy entire thing ... */ if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) { ret = -EFAULT; @@ -911,75 +770,34 @@ static int get_entries(const struct arpt_get_entries *entries, int ret; struct arpt_table *t; - t = find_table_lock(entries->name); + t = xt_find_table_lock(NF_ARP, entries->name); if (t || !IS_ERR(t)) { + struct xt_table_info *private = t->private; duprintf("t->private->number = %u\n", - t->private->number); - if (entries->size == t->private->size) - ret = copy_entries_to_user(t->private->size, + private->number); + if (entries->size == private->size) + ret = copy_entries_to_user(private->size, t, uptr->entrytable); else { duprintf("get_entries: I've got %u not %u!\n", - t->private->size, - entries->size); + private->size, entries->size); ret = -EINVAL; } module_put(t->me); - up(&arpt_mutex); + xt_table_unlock(t); } else ret = t ? PTR_ERR(t) : -ENOENT; return ret; } -static void free_table_info(struct arpt_table_info *info) -{ - int cpu; - for_each_cpu(cpu) { - if (info->size <= PAGE_SIZE) - kfree(info->entries[cpu]); - else - vfree(info->entries[cpu]); - } - kfree(info); -} - -static struct arpt_table_info *alloc_table_info(unsigned int size) -{ - struct arpt_table_info *newinfo; - int cpu; - - newinfo = kzalloc(sizeof(struct arpt_table_info), GFP_KERNEL); - if (!newinfo) - return NULL; - - newinfo->size = size; - - for_each_cpu(cpu) { - if (size <= PAGE_SIZE) - newinfo->entries[cpu] = kmalloc_node(size, - GFP_KERNEL, - cpu_to_node(cpu)); - else - newinfo->entries[cpu] = vmalloc_node(size, - cpu_to_node(cpu)); - - if (newinfo->entries[cpu] == NULL) { - free_table_info(newinfo); - return NULL; - } - } - - return newinfo; -} - static int do_replace(void __user *user, unsigned int len) { int ret; struct arpt_replace tmp; struct arpt_table *t; - struct arpt_table_info *newinfo, *oldinfo; - struct arpt_counters *counters; + struct xt_table_info *newinfo, *oldinfo; + struct xt_counters *counters; void *loc_cpu_entry, *loc_cpu_old_entry; if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) @@ -989,11 +807,7 @@ static int do_replace(void __user *user, unsigned int len) if (len != sizeof(tmp) + tmp.size) return -ENOPROTOOPT; - /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ - if ((SMP_ALIGN(tmp.size) >> PAGE_SHIFT) + 2 > num_physpages) - return -ENOMEM; - - newinfo = alloc_table_info(tmp.size); + newinfo = xt_alloc_table_info(tmp.size); if (!newinfo) return -ENOMEM; @@ -1005,7 +819,7 @@ static int do_replace(void __user *user, unsigned int len) goto free_newinfo; } - counters = vmalloc(tmp.num_counters * sizeof(struct arpt_counters)); + counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters)); if (!counters) { ret = -ENOMEM; goto free_newinfo; @@ -1019,7 +833,7 @@ static int do_replace(void __user *user, unsigned int len) duprintf("arp_tables: Translated table\n"); - t = try_then_request_module(find_table_lock(tmp.name), + t = try_then_request_module(xt_find_table_lock(NF_ARP, tmp.name), "arptable_%s", tmp.name); if (!t || IS_ERR(t)) { ret = t ? PTR_ERR(t) : -ENOENT; @@ -1034,7 +848,7 @@ static int do_replace(void __user *user, unsigned int len) goto put_module; } - oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); + oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret); if (!oldinfo) goto put_module; @@ -1054,23 +868,23 @@ static int do_replace(void __user *user, unsigned int len) loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; ARPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); - free_table_info(oldinfo); + xt_free_table_info(oldinfo); if (copy_to_user(tmp.counters, counters, - sizeof(struct arpt_counters) * tmp.num_counters) != 0) + sizeof(struct xt_counters) * tmp.num_counters) != 0) ret = -EFAULT; vfree(counters); - up(&arpt_mutex); + xt_table_unlock(t); return ret; put_module: module_put(t->me); - up(&arpt_mutex); + xt_table_unlock(t); free_newinfo_counters_untrans: ARPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL); free_newinfo_counters: vfree(counters); free_newinfo: - free_table_info(newinfo); + xt_free_table_info(newinfo); return ret; } @@ -1078,7 +892,7 @@ static int do_replace(void __user *user, unsigned int len) * and everything is OK. */ static inline int add_counter_to_entry(struct arpt_entry *e, - const struct arpt_counters addme[], + const struct xt_counters addme[], unsigned int *i) { @@ -1091,15 +905,16 @@ static inline int add_counter_to_entry(struct arpt_entry *e, static int do_add_counters(void __user *user, unsigned int len) { unsigned int i; - struct arpt_counters_info tmp, *paddc; + struct xt_counters_info tmp, *paddc; struct arpt_table *t; + struct xt_table_info *private; int ret = 0; void *loc_cpu_entry; if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) return -EFAULT; - if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct arpt_counters)) + if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters)) return -EINVAL; paddc = vmalloc(len); @@ -1111,29 +926,30 @@ static int do_add_counters(void __user *user, unsigned int len) goto free; } - t = find_table_lock(tmp.name); + t = xt_find_table_lock(NF_ARP, tmp.name); if (!t || IS_ERR(t)) { ret = t ? PTR_ERR(t) : -ENOENT; goto free; } write_lock_bh(&t->lock); - if (t->private->number != paddc->num_counters) { + private = t->private; + if (private->number != paddc->num_counters) { ret = -EINVAL; goto unlock_up_free; } i = 0; /* Choose the copy that is on our node */ - loc_cpu_entry = t->private->entries[smp_processor_id()]; + loc_cpu_entry = private->entries[smp_processor_id()]; ARPT_ENTRY_ITERATE(loc_cpu_entry, - t->private->size, + private->size, add_counter_to_entry, paddc->counters, &i); unlock_up_free: write_unlock_bh(&t->lock); - up(&arpt_mutex); + xt_table_unlock(t); module_put(t->me); free: vfree(paddc); @@ -1190,25 +1006,26 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len } name[ARPT_TABLE_MAXNAMELEN-1] = '\0'; - t = try_then_request_module(find_table_lock(name), + t = try_then_request_module(xt_find_table_lock(NF_ARP, name), "arptable_%s", name); if (t && !IS_ERR(t)) { struct arpt_getinfo info; + struct xt_table_info *private = t->private; info.valid_hooks = t->valid_hooks; - memcpy(info.hook_entry, t->private->hook_entry, + memcpy(info.hook_entry, private->hook_entry, sizeof(info.hook_entry)); - memcpy(info.underflow, t->private->underflow, + memcpy(info.underflow, private->underflow, sizeof(info.underflow)); - info.num_entries = t->private->number; - info.size = t->private->size; + info.num_entries = private->number; + info.size = private->size; strcpy(info.name, name); if (copy_to_user(user, &info, *len) != 0) ret = -EFAULT; else ret = 0; - up(&arpt_mutex); + xt_table_unlock(t); module_put(t->me); } else ret = t ? PTR_ERR(t) : -ENOENT; @@ -1233,7 +1050,7 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len } case ARPT_SO_GET_REVISION_TARGET: { - struct arpt_get_revision rev; + struct xt_get_revision rev; if (*len != sizeof(rev)) { ret = -EINVAL; @@ -1244,8 +1061,8 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len break; } - try_then_request_module(find_revision(rev.name, rev.revision, - target_revfn, &ret), + try_then_request_module(xt_find_revision(NF_ARP, rev.name, + rev.revision, 1, &ret), "arpt_%s", rev.name); break; } @@ -1258,38 +1075,16 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len return ret; } -/* Registration hooks for targets. */ -int arpt_register_target(struct arpt_target *target) -{ - int ret; - - ret = down_interruptible(&arpt_mutex); - if (ret != 0) - return ret; - - list_add(&target->list, &arpt_target); - up(&arpt_mutex); - - return ret; -} - -void arpt_unregister_target(struct arpt_target *target) -{ - down(&arpt_mutex); - LIST_DELETE(&arpt_target, target); - up(&arpt_mutex); -} - int arpt_register_table(struct arpt_table *table, const struct arpt_replace *repl) { int ret; - struct arpt_table_info *newinfo; - static struct arpt_table_info bootstrap + struct xt_table_info *newinfo; + static struct xt_table_info bootstrap = { 0, 0, 0, { 0 }, { 0 }, { } }; void *loc_cpu_entry; - newinfo = alloc_table_info(repl->size); + newinfo = xt_alloc_table_info(repl->size); if (!newinfo) { ret = -ENOMEM; return ret; @@ -1304,60 +1099,33 @@ int arpt_register_table(struct arpt_table *table, repl->num_entries, repl->hook_entry, repl->underflow); + duprintf("arpt_register_table: translate table gives %d\n", ret); if (ret != 0) { - free_table_info(newinfo); + xt_free_table_info(newinfo); return ret; } - ret = down_interruptible(&arpt_mutex); - if (ret != 0) { - free_table_info(newinfo); + if (xt_register_table(table, &bootstrap, newinfo) != 0) { + xt_free_table_info(newinfo); return ret; } - /* Don't autoload: we'd eat our tail... */ - if (list_named_find(&arpt_tables, table->name)) { - ret = -EEXIST; - goto free_unlock; - } - - /* Simplifies replace_table code. */ - table->private = &bootstrap; - if (!replace_table(table, 0, newinfo, &ret)) - goto free_unlock; - - duprintf("table->private->number = %u\n", - table->private->number); - - /* save number of initial entries */ - table->private->initial_entries = table->private->number; - - rwlock_init(&table->lock); - list_prepend(&arpt_tables, table); - - unlock: - up(&arpt_mutex); - return ret; - - free_unlock: - free_table_info(newinfo); - goto unlock; + return 0; } void arpt_unregister_table(struct arpt_table *table) { + struct xt_table_info *private; void *loc_cpu_entry; - down(&arpt_mutex); - LIST_DELETE(&arpt_tables, table); - up(&arpt_mutex); + private = xt_unregister_table(table); /* Decrease module usage counts and free resources */ - loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; - ARPT_ENTRY_ITERATE(loc_cpu_entry, table->private->size, + loc_cpu_entry = private->entries[raw_smp_processor_id()]; + ARPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL); - free_table_info(table->private); + xt_free_table_info(private); } /* The built-in targets: standard (NULL) and error. */ @@ -1380,52 +1148,15 @@ static struct nf_sockopt_ops arpt_sockopts = { .get = do_arpt_get_ctl, }; -#ifdef CONFIG_PROC_FS -static inline int print_name(const struct arpt_table *t, - off_t start_offset, char *buffer, int length, - off_t *pos, unsigned int *count) -{ - if ((*count)++ >= start_offset) { - unsigned int namelen; - - namelen = sprintf(buffer + *pos, "%s\n", t->name); - if (*pos + namelen > length) { - /* Stop iterating */ - return 1; - } - *pos += namelen; - } - return 0; -} - -static int arpt_get_tables(char *buffer, char **start, off_t offset, int length) -{ - off_t pos = 0; - unsigned int count = 0; - - if (down_interruptible(&arpt_mutex) != 0) - return 0; - - LIST_FIND(&arpt_tables, print_name, struct arpt_table *, - offset, buffer, length, &pos, &count); - - up(&arpt_mutex); - - /* `start' hack - see fs/proc/generic.c line ~105 */ - *start=(char *)((unsigned long)count-offset); - return pos; -} -#endif /*CONFIG_PROC_FS*/ - static int __init init(void) { int ret; + xt_proto_init(NF_ARP); + /* Noone else will be downing sem now, so we won't sleep */ - down(&arpt_mutex); - list_append(&arpt_target, &arpt_standard_target); - list_append(&arpt_target, &arpt_error_target); - up(&arpt_mutex); + xt_register_target(NF_ARP, &arpt_standard_target); + xt_register_target(NF_ARP, &arpt_error_target); /* Register setsockopt */ ret = nf_register_sockopt(&arpt_sockopts); @@ -1434,19 +1165,6 @@ static int __init init(void) return ret; } -#ifdef CONFIG_PROC_FS - { - struct proc_dir_entry *proc; - - proc = proc_net_create("arp_tables_names", 0, arpt_get_tables); - if (!proc) { - nf_unregister_sockopt(&arpt_sockopts); - return -ENOMEM; - } - proc->owner = THIS_MODULE; - } -#endif - printk("arp_tables: (C) 2002 David S. Miller\n"); return 0; } @@ -1454,16 +1172,12 @@ static int __init init(void) static void __exit fini(void) { nf_unregister_sockopt(&arpt_sockopts); -#ifdef CONFIG_PROC_FS - proc_net_remove("arp_tables_names"); -#endif + xt_proto_fini(NF_ARP); } EXPORT_SYMBOL(arpt_register_table); EXPORT_SYMBOL(arpt_unregister_table); EXPORT_SYMBOL(arpt_do_table); -EXPORT_SYMBOL(arpt_register_target); -EXPORT_SYMBOL(arpt_unregister_target); module_init(init); module_exit(fini); diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c index 3e592ec8648..c97650a16a5 100644 --- a/net/ipv4/netfilter/arpt_mangle.c +++ b/net/ipv4/netfilter/arpt_mangle.c @@ -8,8 +8,9 @@ MODULE_AUTHOR("Bart De Schuymer "); MODULE_DESCRIPTION("arptables arp payload mangle target"); static unsigned int -target(struct sk_buff **pskb, unsigned int hooknum, const struct net_device *in, - const struct net_device *out, const void *targinfo, void *userinfo) +target(struct sk_buff **pskb, const struct net_device *in, + const struct net_device *out, unsigned int hooknum, const void *targinfo, + void *userinfo) { const struct arpt_mangle *mangle = targinfo; struct arphdr *arp; @@ -64,7 +65,7 @@ target(struct sk_buff **pskb, unsigned int hooknum, const struct net_device *in, } static int -checkentry(const char *tablename, const struct arpt_entry *e, void *targinfo, +checkentry(const char *tablename, const void *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { const struct arpt_mangle *mangle = targinfo; diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c index 0d759f5a4ef..f6ab45f4868 100644 --- a/net/ipv4/netfilter/arptable_filter.c +++ b/net/ipv4/netfilter/arptable_filter.c @@ -145,6 +145,7 @@ static struct arpt_table packet_filter = { .lock = RW_LOCK_UNLOCKED, .private = NULL, .me = THIS_MODULE, + .af = NF_ARP, }; /* The work comes in here from netfilter.c */ diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c index 9dec1293f67..833fcb4be5e 100644 --- a/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/net/ipv4/netfilter/ip_conntrack_standalone.c @@ -944,7 +944,7 @@ module_exit(fini); /* Some modules need us, but don't depend directly on any symbol. They should call this. */ -void need_ip_conntrack(void) +void need_conntrack(void) { } @@ -962,7 +962,7 @@ EXPORT_SYMBOL(ip_ct_get_tuple); EXPORT_SYMBOL(invert_tuplepr); EXPORT_SYMBOL(ip_conntrack_alter_reply); EXPORT_SYMBOL(ip_conntrack_destroyed); -EXPORT_SYMBOL(need_ip_conntrack); +EXPORT_SYMBOL(need_conntrack); EXPORT_SYMBOL(ip_conntrack_helper_register); EXPORT_SYMBOL(ip_conntrack_helper_unregister); EXPORT_SYMBOL(ip_ct_iterate_cleanup); diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c index cb66b8bddeb..1de86282d23 100644 --- a/net/ipv4/netfilter/ip_nat_rule.c +++ b/net/ipv4/netfilter/ip_nat_rule.c @@ -95,6 +95,7 @@ static struct ipt_table nat_table = { .valid_hooks = NAT_VALID_HOOKS, .lock = RW_LOCK_UNLOCKED, .me = THIS_MODULE, + .af = AF_INET, }; /* Source NAT */ @@ -168,7 +169,7 @@ static unsigned int ipt_dnat_target(struct sk_buff **pskb, } static int ipt_snat_checkentry(const char *tablename, - const struct ipt_entry *e, + const void *entry, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) @@ -201,7 +202,7 @@ static int ipt_snat_checkentry(const char *tablename, } static int ipt_dnat_checkentry(const char *tablename, - const struct ipt_entry *e, + const void *entry, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index 8b8a1f00bbf..ad438fb185b 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c @@ -364,7 +364,7 @@ static int init_or_cleanup(int init) { int ret = 0; - need_ip_conntrack(); + need_conntrack(); if (!init) goto cleanup; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 877bc96d333..2371b2062c2 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -2,7 +2,7 @@ * Packet matching code. * * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling - * Copyright (C) 2000-2004 Netfilter Core Team + * Copyright (C) 2000-2005 Netfilter Core Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -11,6 +11,8 @@ * 19 Jan 2002 Harald Welte * - increase module usage count as soon as we have rules inside * a table + * 08 Oct 2005 Harald Welte + * - Generalize into "x_tables" layer and "{ip,ip6,arp}_tables" */ #include #include @@ -20,8 +22,6 @@ #include #include #include -#include -#include #include #include #include @@ -30,6 +30,7 @@ #include #include +#include #include MODULE_LICENSE("GPL"); @@ -62,14 +63,6 @@ do { \ #else #define IP_NF_ASSERT(x) #endif -#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) - -static DECLARE_MUTEX(ipt_mutex); - -/* Must have mutex */ -#define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0) -#define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0) -#include #if 0 /* All the better to debug you with... */ @@ -86,36 +79,6 @@ static DECLARE_MUTEX(ipt_mutex); Hence the start of any table is given by get_table() below. */ -/* The table itself */ -struct ipt_table_info -{ - /* Size per table */ - unsigned int size; - /* Number of entries: FIXME. --RR */ - unsigned int number; - /* Initial number of entries. Needed for module usage count */ - unsigned int initial_entries; - - /* Entry points and underflows */ - unsigned int hook_entry[NF_IP_NUMHOOKS]; - unsigned int underflow[NF_IP_NUMHOOKS]; - - /* ipt_entry tables: one per CPU */ - void *entries[NR_CPUS]; -}; - -static LIST_HEAD(ipt_target); -static LIST_HEAD(ipt_match); -static LIST_HEAD(ipt_tables); -#define SET_COUNTER(c,b,p) do { (c).bcnt = (b); (c).pcnt = (p); } while(0) -#define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0) - -#if 0 -#define down(x) do { printk("DOWN:%u:" #x "\n", __LINE__); down(x); } while(0) -#define down_interruptible(x) ({ int __r; printk("DOWNi:%u:" #x "\n", __LINE__); __r = down_interruptible(x); if (__r != 0) printk("ABORT-DOWNi:%u\n", __LINE__); __r; }) -#define up(x) do { printk("UP:%u:" #x "\n", __LINE__); up(x); } while(0) -#endif - /* Returns whether matches rule or not. */ static inline int ip_packet_match(const struct iphdr *ip, @@ -234,7 +197,8 @@ int do_match(struct ipt_entry_match *m, int *hotdrop) { /* Stop iteration if it doesn't match */ - if (!m->u.kernel.match->match(skb, in, out, m->data, offset, hotdrop)) + if (!m->u.kernel.match->match(skb, in, out, m->data, offset, + skb->nh.iph->ihl*4, hotdrop)) return 1; else return 0; @@ -265,6 +229,7 @@ ipt_do_table(struct sk_buff **pskb, const char *indev, *outdev; void *table_base; struct ipt_entry *e, *back; + struct xt_table_info *private = table->private; /* Initialization */ ip = (*pskb)->nh.iph; @@ -281,24 +246,11 @@ ipt_do_table(struct sk_buff **pskb, read_lock_bh(&table->lock); IP_NF_ASSERT(table->valid_hooks & (1 << hook)); - table_base = (void *)table->private->entries[smp_processor_id()]; - e = get_entry(table_base, table->private->hook_entry[hook]); - -#ifdef CONFIG_NETFILTER_DEBUG - /* Check noone else using our table */ - if (((struct ipt_entry *)table_base)->comefrom != 0xdead57ac - && ((struct ipt_entry *)table_base)->comefrom != 0xeeeeeeec) { - printk("ASSERT: CPU #%u, %s comefrom(%p) = %X\n", - smp_processor_id(), - table->name, - &((struct ipt_entry *)table_base)->comefrom, - ((struct ipt_entry *)table_base)->comefrom); - } - ((struct ipt_entry *)table_base)->comefrom = 0x57acc001; -#endif + table_base = (void *)private->entries[smp_processor_id()]; + e = get_entry(table_base, private->hook_entry[hook]); /* For return from builtin chain */ - back = get_entry(table_base, table->private->underflow[hook]); + back = get_entry(table_base, private->underflow[hook]); do { IP_NF_ASSERT(e); @@ -384,9 +336,6 @@ ipt_do_table(struct sk_buff **pskb, } } while (!hotdrop); -#ifdef CONFIG_NETFILTER_DEBUG - ((struct ipt_entry *)table_base)->comefrom = 0xdead57ac; -#endif read_unlock_bh(&table->lock); #ifdef DEBUG_ALLOW_ALL @@ -398,145 +347,6 @@ ipt_do_table(struct sk_buff **pskb, #endif } -/* - * These are weird, but module loading must not be done with mutex - * held (since they will register), and we have to have a single - * function to use try_then_request_module(). - */ - -/* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */ -static inline struct ipt_table *find_table_lock(const char *name) -{ - struct ipt_table *t; - - if (down_interruptible(&ipt_mutex) != 0) - return ERR_PTR(-EINTR); - - list_for_each_entry(t, &ipt_tables, list) - if (strcmp(t->name, name) == 0 && try_module_get(t->me)) - return t; - up(&ipt_mutex); - return NULL; -} - -/* Find match, grabs ref. Returns ERR_PTR() on error. */ -static inline struct ipt_match *find_match(const char *name, u8 revision) -{ - struct ipt_match *m; - int err = 0; - - if (down_interruptible(&ipt_mutex) != 0) - return ERR_PTR(-EINTR); - - list_for_each_entry(m, &ipt_match, list) { - if (strcmp(m->name, name) == 0) { - if (m->revision == revision) { - if (try_module_get(m->me)) { - up(&ipt_mutex); - return m; - } - } else - err = -EPROTOTYPE; /* Found something. */ - } - } - up(&ipt_mutex); - return ERR_PTR(err); -} - -/* Find target, grabs ref. Returns ERR_PTR() on error. */ -static inline struct ipt_target *find_target(const char *name, u8 revision) -{ - struct ipt_target *t; - int err = 0; - - if (down_interruptible(&ipt_mutex) != 0) - return ERR_PTR(-EINTR); - - list_for_each_entry(t, &ipt_target, list) { - if (strcmp(t->name, name) == 0) { - if (t->revision == revision) { - if (try_module_get(t->me)) { - up(&ipt_mutex); - return t; - } - } else - err = -EPROTOTYPE; /* Found something. */ - } - } - up(&ipt_mutex); - return ERR_PTR(err); -} - -struct ipt_target *ipt_find_target(const char *name, u8 revision) -{ - struct ipt_target *target; - - target = try_then_request_module(find_target(name, revision), - "ipt_%s", name); - if (IS_ERR(target) || !target) - return NULL; - return target; -} - -static int match_revfn(const char *name, u8 revision, int *bestp) -{ - struct ipt_match *m; - int have_rev = 0; - - list_for_each_entry(m, &ipt_match, list) { - if (strcmp(m->name, name) == 0) { - if (m->revision > *bestp) - *bestp = m->revision; - if (m->revision == revision) - have_rev = 1; - } - } - return have_rev; -} - -static int target_revfn(const char *name, u8 revision, int *bestp) -{ - struct ipt_target *t; - int have_rev = 0; - - list_for_each_entry(t, &ipt_target, list) { - if (strcmp(t->name, name) == 0) { - if (t->revision > *bestp) - *bestp = t->revision; - if (t->revision == revision) - have_rev = 1; - } - } - return have_rev; -} - -/* Returns true or false (if no such extension at all) */ -static inline int find_revision(const char *name, u8 revision, - int (*revfn)(const char *, u8, int *), - int *err) -{ - int have_rev, best = -1; - - if (down_interruptible(&ipt_mutex) != 0) { - *err = -EINTR; - return 1; - } - have_rev = revfn(name, revision, &best); - up(&ipt_mutex); - - /* Nothing at all? Return 0 to try loading module. */ - if (best == -1) { - *err = -ENOENT; - return 0; - } - - *err = best; - if (!have_rev) - *err = -EPROTONOSUPPORT; - return 1; -} - - /* All zeroes == unconditional rule. */ static inline int unconditional(const struct ipt_ip *ip) @@ -553,7 +363,7 @@ unconditional(const struct ipt_ip *ip) /* Figures out from what hook each rule can be called: returns 0 if there are loops. Puts hook bitmask in comefrom. */ static int -mark_source_chains(struct ipt_table_info *newinfo, +mark_source_chains(struct xt_table_info *newinfo, unsigned int valid_hooks, void *entry0) { unsigned int hook; @@ -699,7 +509,7 @@ check_match(struct ipt_entry_match *m, { struct ipt_match *match; - match = try_then_request_module(find_match(m->u.user.name, + match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name, m->u.user.revision), "ipt_%s", m->u.user.name); if (IS_ERR(match) || !match) { @@ -744,7 +554,8 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size, goto cleanup_matches; t = ipt_get_target(e); - target = try_then_request_module(find_target(t->u.user.name, + target = try_then_request_module(xt_find_target(AF_INET, + t->u.user.name, t->u.user.revision), "ipt_%s", t->u.user.name); if (IS_ERR(target) || !target) { @@ -781,7 +592,7 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size, static inline int check_entry_size_and_hooks(struct ipt_entry *e, - struct ipt_table_info *newinfo, + struct xt_table_info *newinfo, unsigned char *base, unsigned char *limit, const unsigned int *hook_entries, @@ -815,7 +626,7 @@ check_entry_size_and_hooks(struct ipt_entry *e, < 0 (not IPT_RETURN). --RR */ /* Clear counters and comefrom */ - e->counters = ((struct ipt_counters) { 0, 0 }); + e->counters = ((struct xt_counters) { 0, 0 }); e->comefrom = 0; (*i)++; @@ -845,7 +656,7 @@ cleanup_entry(struct ipt_entry *e, unsigned int *i) static int translate_table(const char *name, unsigned int valid_hooks, - struct ipt_table_info *newinfo, + struct xt_table_info *newinfo, void *entry0, unsigned int size, unsigned int number, @@ -922,48 +733,10 @@ translate_table(const char *name, return ret; } -static struct ipt_table_info * -replace_table(struct ipt_table *table, - unsigned int num_counters, - struct ipt_table_info *newinfo, - int *error) -{ - struct ipt_table_info *oldinfo; - -#ifdef CONFIG_NETFILTER_DEBUG - { - int cpu; - - for_each_cpu(cpu) { - struct ipt_entry *table_base = newinfo->entries[cpu]; - if (table_base) - table_base->comefrom = 0xdead57ac; - } - } -#endif - - /* Do the substitution. */ - write_lock_bh(&table->lock); - /* Check inside lock: is the old number correct? */ - if (num_counters != table->private->number) { - duprintf("num_counters != table->private->number (%u/%u)\n", - num_counters, table->private->number); - write_unlock_bh(&table->lock); - *error = -EAGAIN; - return NULL; - } - oldinfo = table->private; - table->private = newinfo; - newinfo->initial_entries = oldinfo->initial_entries; - write_unlock_bh(&table->lock); - - return oldinfo; -} - /* Gets counters. */ static inline int add_entry_to_counter(const struct ipt_entry *e, - struct ipt_counters total[], + struct xt_counters total[], unsigned int *i) { ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); @@ -984,8 +757,8 @@ set_entry_to_counter(const struct ipt_entry *e, } static void -get_counters(const struct ipt_table_info *t, - struct ipt_counters counters[]) +get_counters(const struct xt_table_info *t, + struct xt_counters counters[]) { unsigned int cpu; unsigned int i; @@ -1024,14 +797,15 @@ copy_entries_to_user(unsigned int total_size, { unsigned int off, num, countersize; struct ipt_entry *e; - struct ipt_counters *counters; + struct xt_counters *counters; + struct xt_table_info *private = table->private; int ret = 0; void *loc_cpu_entry; /* We need atomic snapshot of counters: rest doesn't change (other than comefrom, which userspace doesn't care about). */ - countersize = sizeof(struct ipt_counters) * table->private->number; + countersize = sizeof(struct xt_counters) * private->number; counters = vmalloc_node(countersize, numa_node_id()); if (counters == NULL) @@ -1039,14 +813,14 @@ copy_entries_to_user(unsigned int total_size, /* First, sum counters... */ write_lock_bh(&table->lock); - get_counters(table->private, counters); + get_counters(private, counters); write_unlock_bh(&table->lock); /* choose the copy that is on our node/cpu, ... * This choice is lazy (because current thread is * allowed to migrate to another cpu) */ - loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; + loc_cpu_entry = private->entries[raw_smp_processor_id()]; /* ... then copy entire thing ... */ if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) { ret = -EFAULT; @@ -1108,74 +882,36 @@ get_entries(const struct ipt_get_entries *entries, int ret; struct ipt_table *t; - t = find_table_lock(entries->name); + t = xt_find_table_lock(AF_INET, entries->name); if (t && !IS_ERR(t)) { + struct xt_table_info *private = t->private; duprintf("t->private->number = %u\n", - t->private->number); - if (entries->size == t->private->size) - ret = copy_entries_to_user(t->private->size, + private->number); + if (entries->size == private->size) + ret = copy_entries_to_user(private->size, t, uptr->entrytable); else { duprintf("get_entries: I've got %u not %u!\n", - t->private->size, + private->size, entries->size); ret = -EINVAL; } module_put(t->me); - up(&ipt_mutex); + xt_table_unlock(t); } else ret = t ? PTR_ERR(t) : -ENOENT; return ret; } -static void free_table_info(struct ipt_table_info *info) -{ - int cpu; - for_each_cpu(cpu) { - if (info->size <= PAGE_SIZE) - kfree(info->entries[cpu]); - else - vfree(info->entries[cpu]); - } - kfree(info); -} - -static struct ipt_table_info *alloc_table_info(unsigned int size) -{ - struct ipt_table_info *newinfo; - int cpu; - - newinfo = kzalloc(sizeof(struct ipt_table_info), GFP_KERNEL); - if (!newinfo) - return NULL; - - newinfo->size = size; - - for_each_cpu(cpu) { - if (size <= PAGE_SIZE) - newinfo->entries[cpu] = kmalloc_node(size, - GFP_KERNEL, - cpu_to_node(cpu)); - else - newinfo->entries[cpu] = vmalloc_node(size, cpu_to_node(cpu)); - if (newinfo->entries[cpu] == 0) { - free_table_info(newinfo); - return NULL; - } - } - - return newinfo; -} - static int do_replace(void __user *user, unsigned int len) { int ret; struct ipt_replace tmp; struct ipt_table *t; - struct ipt_table_info *newinfo, *oldinfo; - struct ipt_counters *counters; + struct xt_table_info *newinfo, *oldinfo; + struct xt_counters *counters; void *loc_cpu_entry, *loc_cpu_old_entry; if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) @@ -1185,11 +921,7 @@ do_replace(void __user *user, unsigned int len) if (len != sizeof(tmp) + tmp.size) return -ENOPROTOOPT; - /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ - if ((SMP_ALIGN(tmp.size) >> PAGE_SHIFT) + 2 > num_physpages) - return -ENOMEM; - - newinfo = alloc_table_info(tmp.size); + newinfo = xt_alloc_table_info(tmp.size); if (!newinfo) return -ENOMEM; @@ -1201,7 +933,7 @@ do_replace(void __user *user, unsigned int len) goto free_newinfo; } - counters = vmalloc(tmp.num_counters * sizeof(struct ipt_counters)); + counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters)); if (!counters) { ret = -ENOMEM; goto free_newinfo; @@ -1215,7 +947,7 @@ do_replace(void __user *user, unsigned int len) duprintf("ip_tables: Translated table\n"); - t = try_then_request_module(find_table_lock(tmp.name), + t = try_then_request_module(xt_find_table_lock(AF_INET, tmp.name), "iptable_%s", tmp.name); if (!t || IS_ERR(t)) { ret = t ? PTR_ERR(t) : -ENOENT; @@ -1230,7 +962,7 @@ do_replace(void __user *user, unsigned int len) goto put_module; } - oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); + oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret); if (!oldinfo) goto put_module; @@ -1249,23 +981,23 @@ do_replace(void __user *user, unsigned int len) /* Decrease module usage counts and free resource */ loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); - free_table_info(oldinfo); + xt_free_table_info(oldinfo); if (copy_to_user(tmp.counters, counters, - sizeof(struct ipt_counters) * tmp.num_counters) != 0) + sizeof(struct xt_counters) * tmp.num_counters) != 0) ret = -EFAULT; vfree(counters); - up(&ipt_mutex); + xt_table_unlock(t); return ret; put_module: module_put(t->me); - up(&ipt_mutex); + xt_table_unlock(t); free_newinfo_counters_untrans: IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL); free_newinfo_counters: vfree(counters); free_newinfo: - free_table_info(newinfo); + xt_free_table_info(newinfo); return ret; } @@ -1273,7 +1005,7 @@ do_replace(void __user *user, unsigned int len) * and everything is OK. */ static inline int add_counter_to_entry(struct ipt_entry *e, - const struct ipt_counters addme[], + const struct xt_counters addme[], unsigned int *i) { #if 0 @@ -1295,15 +1027,16 @@ static int do_add_counters(void __user *user, unsigned int len) { unsigned int i; - struct ipt_counters_info tmp, *paddc; + struct xt_counters_info tmp, *paddc; struct ipt_table *t; + struct xt_table_info *private; int ret = 0; void *loc_cpu_entry; if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) return -EFAULT; - if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct ipt_counters)) + if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters)) return -EINVAL; paddc = vmalloc_node(len, numa_node_id()); @@ -1315,29 +1048,30 @@ do_add_counters(void __user *user, unsigned int len) goto free; } - t = find_table_lock(tmp.name); + t = xt_find_table_lock(AF_INET, tmp.name); if (!t || IS_ERR(t)) { ret = t ? PTR_ERR(t) : -ENOENT; goto free; } write_lock_bh(&t->lock); - if (t->private->number != paddc->num_counters) { + private = t->private; + if (private->number != paddc->num_counters) { ret = -EINVAL; goto unlock_up_free; } i = 0; /* Choose the copy that is on our node */ - loc_cpu_entry = t->private->entries[raw_smp_processor_id()]; + loc_cpu_entry = private->entries[raw_smp_processor_id()]; IPT_ENTRY_ITERATE(loc_cpu_entry, - t->private->size, + private->size, add_counter_to_entry, paddc->counters, &i); unlock_up_free: write_unlock_bh(&t->lock); - up(&ipt_mutex); + xt_table_unlock(t); module_put(t->me); free: vfree(paddc); @@ -1396,25 +1130,26 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) } name[IPT_TABLE_MAXNAMELEN-1] = '\0'; - t = try_then_request_module(find_table_lock(name), + t = try_then_request_module(xt_find_table_lock(AF_INET, name), "iptable_%s", name); if (t && !IS_ERR(t)) { struct ipt_getinfo info; + struct xt_table_info *private = t->private; info.valid_hooks = t->valid_hooks; - memcpy(info.hook_entry, t->private->hook_entry, + memcpy(info.hook_entry, private->hook_entry, sizeof(info.hook_entry)); - memcpy(info.underflow, t->private->underflow, + memcpy(info.underflow, private->underflow, sizeof(info.underflow)); - info.num_entries = t->private->number; - info.size = t->private->size; + info.num_entries = private->number; + info.size = private->size; memcpy(info.name, name, sizeof(info.name)); if (copy_to_user(user, &info, *len) != 0) ret = -EFAULT; else ret = 0; - up(&ipt_mutex); + xt_table_unlock(t); module_put(t->me); } else ret = t ? PTR_ERR(t) : -ENOENT; @@ -1441,7 +1176,7 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) case IPT_SO_GET_REVISION_MATCH: case IPT_SO_GET_REVISION_TARGET: { struct ipt_get_revision rev; - int (*revfn)(const char *, u8, int *); + int target; if (*len != sizeof(rev)) { ret = -EINVAL; @@ -1453,12 +1188,13 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) } if (cmd == IPT_SO_GET_REVISION_TARGET) - revfn = target_revfn; + target = 1; else - revfn = match_revfn; + target = 0; - try_then_request_module(find_revision(rev.name, rev.revision, - revfn, &ret), + try_then_request_module(xt_find_revision(AF_INET, rev.name, + rev.revision, + target, &ret), "ipt_%s", rev.name); break; } @@ -1471,60 +1207,15 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) return ret; } -/* Registration hooks for targets. */ -int -ipt_register_target(struct ipt_target *target) +int ipt_register_table(struct xt_table *table, const struct ipt_replace *repl) { int ret; - - ret = down_interruptible(&ipt_mutex); - if (ret != 0) - return ret; - list_add(&target->list, &ipt_target); - up(&ipt_mutex); - return ret; -} - -void -ipt_unregister_target(struct ipt_target *target) -{ - down(&ipt_mutex); - LIST_DELETE(&ipt_target, target); - up(&ipt_mutex); -} - -int -ipt_register_match(struct ipt_match *match) -{ - int ret; - - ret = down_interruptible(&ipt_mutex); - if (ret != 0) - return ret; - - list_add(&match->list, &ipt_match); - up(&ipt_mutex); - - return ret; -} - -void -ipt_unregister_match(struct ipt_match *match) -{ - down(&ipt_mutex); - LIST_DELETE(&ipt_match, match); - up(&ipt_mutex); -} - -int ipt_register_table(struct ipt_table *table, const struct ipt_replace *repl) -{ - int ret; - struct ipt_table_info *newinfo; - static struct ipt_table_info bootstrap + struct xt_table_info *newinfo; + static struct xt_table_info bootstrap = { 0, 0, 0, { 0 }, { 0 }, { } }; void *loc_cpu_entry; - newinfo = alloc_table_info(repl->size); + newinfo = xt_alloc_table_info(repl->size); if (!newinfo) return -ENOMEM; @@ -1540,246 +1231,29 @@ int ipt_register_table(struct ipt_table *table, const struct ipt_replace *repl) repl->hook_entry, repl->underflow); if (ret != 0) { - free_table_info(newinfo); + xt_free_table_info(newinfo); return ret; } - ret = down_interruptible(&ipt_mutex); - if (ret != 0) { - free_table_info(newinfo); + if (xt_register_table(table, &bootstrap, newinfo) != 0) { + xt_free_table_info(newinfo); return ret; } - /* Don't autoload: we'd eat our tail... */ - if (list_named_find(&ipt_tables, table->name)) { - ret = -EEXIST; - goto free_unlock; - } - - /* Simplifies replace_table code. */ - table->private = &bootstrap; - if (!replace_table(table, 0, newinfo, &ret)) - goto free_unlock; - - duprintf("table->private->number = %u\n", - table->private->number); - - /* save number of initial entries */ - table->private->initial_entries = table->private->number; - - rwlock_init(&table->lock); - list_prepend(&ipt_tables, table); - - unlock: - up(&ipt_mutex); - return ret; - - free_unlock: - free_table_info(newinfo); - goto unlock; + return 0; } void ipt_unregister_table(struct ipt_table *table) { + struct xt_table_info *private; void *loc_cpu_entry; - down(&ipt_mutex); - LIST_DELETE(&ipt_tables, table); - up(&ipt_mutex); + private = xt_unregister_table(table); /* Decrease module usage counts and free resources */ - loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; - IPT_ENTRY_ITERATE(loc_cpu_entry, table->private->size, - cleanup_entry, NULL); - free_table_info(table->private); -} - -/* Returns 1 if the port is matched by the range, 0 otherwise */ -static inline int -port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert) -{ - int ret; - - ret = (port >= min && port <= max) ^ invert; - return ret; -} - -static int -tcp_find_option(u_int8_t option, - const struct sk_buff *skb, - unsigned int optlen, - int invert, - int *hotdrop) -{ - /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */ - u_int8_t _opt[60 - sizeof(struct tcphdr)], *op; - unsigned int i; - - duprintf("tcp_match: finding option\n"); - - if (!optlen) - return invert; - - /* If we don't have the whole header, drop packet. */ - op = skb_header_pointer(skb, - skb->nh.iph->ihl*4 + sizeof(struct tcphdr), - optlen, _opt); - if (op == NULL) { - *hotdrop = 1; - return 0; - } - - for (i = 0; i < optlen; ) { - if (op[i] == option) return !invert; - if (op[i] < 2) i++; - else i += op[i+1]?:1; - } - - return invert; -} - -static int -tcp_match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const void *matchinfo, - int offset, - int *hotdrop) -{ - struct tcphdr _tcph, *th; - const struct ipt_tcp *tcpinfo = matchinfo; - - if (offset) { - /* To quote Alan: - - Don't allow a fragment of TCP 8 bytes in. Nobody normal - causes this. Its a cracker trying to break in by doing a - flag overwrite to pass the direction checks. - */ - if (offset == 1) { - duprintf("Dropping evil TCP offset=1 frag.\n"); - *hotdrop = 1; - } - /* Must not be a fragment. */ - return 0; - } - -#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg)) - - th = skb_header_pointer(skb, skb->nh.iph->ihl*4, - sizeof(_tcph), &_tcph); - if (th == NULL) { - /* We've been asked to examine this packet, and we - can't. Hence, no choice but to drop. */ - duprintf("Dropping evil TCP offset=0 tinygram.\n"); - *hotdrop = 1; - return 0; - } - - if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1], - ntohs(th->source), - !!(tcpinfo->invflags & IPT_TCP_INV_SRCPT))) - return 0; - if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1], - ntohs(th->dest), - !!(tcpinfo->invflags & IPT_TCP_INV_DSTPT))) - return 0; - if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask) - == tcpinfo->flg_cmp, - IPT_TCP_INV_FLAGS)) - return 0; - if (tcpinfo->option) { - if (th->doff * 4 < sizeof(_tcph)) { - *hotdrop = 1; - return 0; - } - if (!tcp_find_option(tcpinfo->option, skb, - th->doff*4 - sizeof(_tcph), - tcpinfo->invflags & IPT_TCP_INV_OPTION, - hotdrop)) - return 0; - } - return 1; -} - -/* Called when user tries to insert an entry of this type. */ -static int -tcp_checkentry(const char *tablename, - const struct ipt_ip *ip, - void *matchinfo, - unsigned int matchsize, - unsigned int hook_mask) -{ - const struct ipt_tcp *tcpinfo = matchinfo; - - /* Must specify proto == TCP, and no unknown invflags */ - return ip->proto == IPPROTO_TCP - && !(ip->invflags & IPT_INV_PROTO) - && matchsize == IPT_ALIGN(sizeof(struct ipt_tcp)) - && !(tcpinfo->invflags & ~IPT_TCP_INV_MASK); -} - -static int -udp_match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const void *matchinfo, - int offset, - int *hotdrop) -{ - struct udphdr _udph, *uh; - const struct ipt_udp *udpinfo = matchinfo; - - /* Must not be a fragment. */ - if (offset) - return 0; - - uh = skb_header_pointer(skb, skb->nh.iph->ihl*4, - sizeof(_udph), &_udph); - if (uh == NULL) { - /* We've been asked to examine this packet, and we - can't. Hence, no choice but to drop. */ - duprintf("Dropping evil UDP tinygram.\n"); - *hotdrop = 1; - return 0; - } - - return port_match(udpinfo->spts[0], udpinfo->spts[1], - ntohs(uh->source), - !!(udpinfo->invflags & IPT_UDP_INV_SRCPT)) - && port_match(udpinfo->dpts[0], udpinfo->dpts[1], - ntohs(uh->dest), - !!(udpinfo->invflags & IPT_UDP_INV_DSTPT)); -} - -/* Called when user tries to insert an entry of this type. */ -static int -udp_checkentry(const char *tablename, - const struct ipt_ip *ip, - void *matchinfo, - unsigned int matchinfosize, - unsigned int hook_mask) -{ - const struct ipt_udp *udpinfo = matchinfo; - - /* Must specify proto == UDP, and no unknown invflags */ - if (ip->proto != IPPROTO_UDP || (ip->invflags & IPT_INV_PROTO)) { - duprintf("ipt_udp: Protocol %u != %u\n", ip->proto, - IPPROTO_UDP); - return 0; - } - if (matchinfosize != IPT_ALIGN(sizeof(struct ipt_udp))) { - duprintf("ipt_udp: matchsize %u != %u\n", - matchinfosize, IPT_ALIGN(sizeof(struct ipt_udp))); - return 0; - } - if (udpinfo->invflags & ~IPT_UDP_INV_MASK) { - duprintf("ipt_udp: unknown flags %X\n", - udpinfo->invflags); - return 0; - } - - return 1; + loc_cpu_entry = private->entries[raw_smp_processor_id()]; + IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL); + xt_free_table_info(private); } /* Returns 1 if the type and code is matched by the range, 0 otherwise */ @@ -1798,6 +1272,7 @@ icmp_match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { struct icmphdr _icmph, *ic; @@ -1807,8 +1282,7 @@ icmp_match(const struct sk_buff *skb, if (offset) return 0; - ic = skb_header_pointer(skb, skb->nh.iph->ihl*4, - sizeof(_icmph), &_icmph); + ic = skb_header_pointer(skb, protoff, sizeof(_icmph), &_icmph); if (ic == NULL) { /* We've been asked to examine this packet, and we * can't. Hence, no choice but to drop. @@ -1828,11 +1302,12 @@ icmp_match(const struct sk_buff *skb, /* Called when user tries to insert an entry of this type. */ static int icmp_checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *info, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { + const struct ipt_ip *ip = info; const struct ipt_icmp *icmpinfo = matchinfo; /* Must specify proto == ICMP, and no unknown invflags */ @@ -1862,123 +1337,22 @@ static struct nf_sockopt_ops ipt_sockopts = { .get = do_ipt_get_ctl, }; -static struct ipt_match tcp_matchstruct = { - .name = "tcp", - .match = &tcp_match, - .checkentry = &tcp_checkentry, -}; - -static struct ipt_match udp_matchstruct = { - .name = "udp", - .match = &udp_match, - .checkentry = &udp_checkentry, -}; - static struct ipt_match icmp_matchstruct = { .name = "icmp", .match = &icmp_match, .checkentry = &icmp_checkentry, }; -#ifdef CONFIG_PROC_FS -static inline int print_name(const char *i, - off_t start_offset, char *buffer, int length, - off_t *pos, unsigned int *count) -{ - if ((*count)++ >= start_offset) { - unsigned int namelen; - - namelen = sprintf(buffer + *pos, "%s\n", - i + sizeof(struct list_head)); - if (*pos + namelen > length) { - /* Stop iterating */ - return 1; - } - *pos += namelen; - } - return 0; -} - -static inline int print_target(const struct ipt_target *t, - off_t start_offset, char *buffer, int length, - off_t *pos, unsigned int *count) -{ - if (t == &ipt_standard_target || t == &ipt_error_target) - return 0; - return print_name((char *)t, start_offset, buffer, length, pos, count); -} - -static int ipt_get_tables(char *buffer, char **start, off_t offset, int length) -{ - off_t pos = 0; - unsigned int count = 0; - - if (down_interruptible(&ipt_mutex) != 0) - return 0; - - LIST_FIND(&ipt_tables, print_name, void *, - offset, buffer, length, &pos, &count); - - up(&ipt_mutex); - - /* `start' hack - see fs/proc/generic.c line ~105 */ - *start=(char *)((unsigned long)count-offset); - return pos; -} - -static int ipt_get_targets(char *buffer, char **start, off_t offset, int length) -{ - off_t pos = 0; - unsigned int count = 0; - - if (down_interruptible(&ipt_mutex) != 0) - return 0; - - LIST_FIND(&ipt_target, print_target, struct ipt_target *, - offset, buffer, length, &pos, &count); - - up(&ipt_mutex); - - *start = (char *)((unsigned long)count - offset); - return pos; -} - -static int ipt_get_matches(char *buffer, char **start, off_t offset, int length) -{ - off_t pos = 0; - unsigned int count = 0; - - if (down_interruptible(&ipt_mutex) != 0) - return 0; - - LIST_FIND(&ipt_match, print_name, void *, - offset, buffer, length, &pos, &count); - - up(&ipt_mutex); - - *start = (char *)((unsigned long)count - offset); - return pos; -} - -static const struct { char *name; get_info_t *get_info; } ipt_proc_entry[] = -{ { "ip_tables_names", ipt_get_tables }, - { "ip_tables_targets", ipt_get_targets }, - { "ip_tables_matches", ipt_get_matches }, - { NULL, NULL} }; -#endif /*CONFIG_PROC_FS*/ - static int __init init(void) { int ret; + xt_proto_init(AF_INET); + /* Noone else will be downing sem now, so we won't sleep */ - down(&ipt_mutex); - list_append(&ipt_target, &ipt_standard_target); - list_append(&ipt_target, &ipt_error_target); - list_append(&ipt_match, &tcp_matchstruct); - list_append(&ipt_match, &udp_matchstruct); - list_append(&ipt_match, &icmp_matchstruct); - up(&ipt_mutex); + xt_register_target(AF_INET, &ipt_standard_target); + xt_register_target(AF_INET, &ipt_error_target); + xt_register_match(AF_INET, &icmp_matchstruct); /* Register setsockopt */ ret = nf_register_sockopt(&ipt_sockopts); @@ -1987,49 +1361,23 @@ static int __init init(void) return ret; } -#ifdef CONFIG_PROC_FS - { - struct proc_dir_entry *proc; - int i; - - for (i = 0; ipt_proc_entry[i].name; i++) { - proc = proc_net_create(ipt_proc_entry[i].name, 0, - ipt_proc_entry[i].get_info); - if (!proc) { - while (--i >= 0) - proc_net_remove(ipt_proc_entry[i].name); - nf_unregister_sockopt(&ipt_sockopts); - return -ENOMEM; - } - proc->owner = THIS_MODULE; - } - } -#endif - - printk("ip_tables: (C) 2000-2002 Netfilter core team\n"); + printk("ip_tables: (C) 2000-2006 Netfilter Core Team\n"); return 0; } static void __exit fini(void) { nf_unregister_sockopt(&ipt_sockopts); -#ifdef CONFIG_PROC_FS - { - int i; - for (i = 0; ipt_proc_entry[i].name; i++) - proc_net_remove(ipt_proc_entry[i].name); - } -#endif + + xt_unregister_match(AF_INET, &icmp_matchstruct); + xt_unregister_target(AF_INET, &ipt_error_target); + xt_unregister_target(AF_INET, &ipt_standard_target); + + xt_proto_fini(AF_INET); } EXPORT_SYMBOL(ipt_register_table); EXPORT_SYMBOL(ipt_unregister_table); -EXPORT_SYMBOL(ipt_register_match); -EXPORT_SYMBOL(ipt_unregister_match); EXPORT_SYMBOL(ipt_do_table); -EXPORT_SYMBOL(ipt_register_target); -EXPORT_SYMBOL(ipt_unregister_target); -EXPORT_SYMBOL(ipt_find_target); - module_init(init); module_exit(fini); diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 45c52d8f4d9..d9bc971f03a 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -379,12 +379,13 @@ target(struct sk_buff **pskb, static int checkentry(const char *tablename, - const struct ipt_entry *e, + const void *e_void, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { struct ipt_clusterip_tgt_info *cipinfo = targinfo; + const struct ipt_entry *e = e_void; struct clusterip_config *config; diff --git a/net/ipv4/netfilter/ipt_DSCP.c b/net/ipv4/netfilter/ipt_DSCP.c index 6e319570a28..898cdf79ce1 100644 --- a/net/ipv4/netfilter/ipt_DSCP.c +++ b/net/ipv4/netfilter/ipt_DSCP.c @@ -57,7 +57,7 @@ target(struct sk_buff **pskb, static int checkentry(const char *tablename, - const struct ipt_entry *e, + const void *e_void, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c index a1319693f64..706445426a6 100644 --- a/net/ipv4/netfilter/ipt_ECN.c +++ b/net/ipv4/netfilter/ipt_ECN.c @@ -113,12 +113,13 @@ target(struct sk_buff **pskb, static int checkentry(const char *tablename, - const struct ipt_entry *e, + const void *e_void, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { const struct ipt_ECN_info *einfo = (struct ipt_ECN_info *)targinfo; + const struct ipt_entry *e = e_void; if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ECN_info))) { printk(KERN_WARNING "ECN: targinfosize %u != %Zu\n", diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c index 30be0f1dae3..6606ddb66a2 100644 --- a/net/ipv4/netfilter/ipt_LOG.c +++ b/net/ipv4/netfilter/ipt_LOG.c @@ -431,7 +431,7 @@ ipt_log_target(struct sk_buff **pskb, } static int ipt_log_checkentry(const char *tablename, - const struct ipt_entry *e, + const void *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c index 27860510ca6..12c56d3343c 100644 --- a/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c @@ -40,7 +40,7 @@ static DEFINE_RWLOCK(masq_lock); /* FIXME: Multiple targets. --RR */ static int masquerade_check(const char *tablename, - const struct ipt_entry *e, + const void *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c index e6e7b609536..b074467fe67 100644 --- a/net/ipv4/netfilter/ipt_NETMAP.c +++ b/net/ipv4/netfilter/ipt_NETMAP.c @@ -31,7 +31,7 @@ MODULE_DESCRIPTION("iptables 1:1 NAT mapping of IP networks target"); static int check(const char *tablename, - const struct ipt_entry *e, + const void *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ipt_NFQUEUE.c b/net/ipv4/netfilter/ipt_NFQUEUE.c deleted file mode 100644 index 3cedc9be880..00000000000 --- a/net/ipv4/netfilter/ipt_NFQUEUE.c +++ /dev/null @@ -1,70 +0,0 @@ -/* iptables module for using new netfilter netlink queue - * - * (C) 2005 by Harald Welte - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include - -#include -#include -#include - -MODULE_AUTHOR("Harald Welte "); -MODULE_DESCRIPTION("iptables NFQUEUE target"); -MODULE_LICENSE("GPL"); - -static unsigned int -target(struct sk_buff **pskb, - const struct net_device *in, - const struct net_device *out, - unsigned int hooknum, - const void *targinfo, - void *userinfo) -{ - const struct ipt_NFQ_info *tinfo = targinfo; - - return NF_QUEUE_NR(tinfo->queuenum); -} - -static int -checkentry(const char *tablename, - const struct ipt_entry *e, - void *targinfo, - unsigned int targinfosize, - unsigned int hook_mask) -{ - if (targinfosize != IPT_ALIGN(sizeof(struct ipt_NFQ_info))) { - printk(KERN_WARNING "NFQUEUE: targinfosize %u != %Zu\n", - targinfosize, - IPT_ALIGN(sizeof(struct ipt_NFQ_info))); - return 0; - } - - return 1; -} - -static struct ipt_target ipt_NFQ_reg = { - .name = "NFQUEUE", - .target = target, - .checkentry = checkentry, - .me = THIS_MODULE, -}; - -static int __init init(void) -{ - return ipt_register_target(&ipt_NFQ_reg); -} - -static void __exit fini(void) -{ - ipt_unregister_target(&ipt_NFQ_reg); -} - -module_init(init); -module_exit(fini); diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c index 5245bfd33d5..140be51f2f0 100644 --- a/net/ipv4/netfilter/ipt_REDIRECT.c +++ b/net/ipv4/netfilter/ipt_REDIRECT.c @@ -33,7 +33,7 @@ MODULE_DESCRIPTION("iptables REDIRECT target module"); /* FIXME: Take multiple ranges --RR */ static int redirect_check(const char *tablename, - const struct ipt_entry *e, + const void *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index 6693526ae12..3eb47aae78c 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c @@ -282,12 +282,13 @@ static unsigned int reject(struct sk_buff **pskb, } static int check(const char *tablename, - const struct ipt_entry *e, + const void *e_void, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { const struct ipt_reject_info *rejinfo = targinfo; + const struct ipt_entry *e = e_void; if (targinfosize != IPT_ALIGN(sizeof(struct ipt_reject_info))) { DEBUGP("REJECT: targinfosize %u != 0\n", targinfosize); diff --git a/net/ipv4/netfilter/ipt_SAME.c b/net/ipv4/netfilter/ipt_SAME.c index 7a0536d864a..a22de59bba0 100644 --- a/net/ipv4/netfilter/ipt_SAME.c +++ b/net/ipv4/netfilter/ipt_SAME.c @@ -49,7 +49,7 @@ MODULE_DESCRIPTION("iptables special SNAT module for consistent sourceip"); static int same_check(const char *tablename, - const struct ipt_entry *e, + const void *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ipt_TCPMSS.c b/net/ipv4/netfilter/ipt_TCPMSS.c index 8db70d6908c..c122841e182 100644 --- a/net/ipv4/netfilter/ipt_TCPMSS.c +++ b/net/ipv4/netfilter/ipt_TCPMSS.c @@ -210,12 +210,13 @@ static inline int find_syn_match(const struct ipt_entry_match *m) /* Must specify -p tcp --syn/--tcp-flags SYN */ static int ipt_tcpmss_checkentry(const char *tablename, - const struct ipt_entry *e, + const void *e_void, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { const struct ipt_tcpmss_info *tcpmssinfo = targinfo; + const struct ipt_entry *e = e_void; if (targinfosize != IPT_ALIGN(sizeof(struct ipt_tcpmss_info))) { DEBUGP("ipt_tcpmss_checkentry: targinfosize %u != %u\n", diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c index deadb36d442..3a44a56db23 100644 --- a/net/ipv4/netfilter/ipt_TOS.c +++ b/net/ipv4/netfilter/ipt_TOS.c @@ -52,7 +52,7 @@ target(struct sk_buff **pskb, static int checkentry(const char *tablename, - const struct ipt_entry *e, + const void *e_void, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c index b9ae6a9382f..b769eb23197 100644 --- a/net/ipv4/netfilter/ipt_TTL.c +++ b/net/ipv4/netfilter/ipt_TTL.c @@ -66,7 +66,7 @@ ipt_ttl_target(struct sk_buff **pskb, const struct net_device *in, } static int ipt_ttl_checkentry(const char *tablename, - const struct ipt_entry *e, + const void *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index 38641cd0612..641dbc47765 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c @@ -330,7 +330,7 @@ static void ipt_logfn(unsigned int pf, } static int ipt_ulog_checkentry(const char *tablename, - const struct ipt_entry *e, + const void *e, void *targinfo, unsigned int targinfosize, unsigned int hookmask) diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c index e19c2a52d00..d6b83a97651 100644 --- a/net/ipv4/netfilter/ipt_addrtype.c +++ b/net/ipv4/netfilter/ipt_addrtype.c @@ -29,7 +29,7 @@ static inline int match_type(u_int32_t addr, u_int16_t mask) static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *matchinfo, - int offset, int *hotdrop) + int offset, unsigned int protoff, int *hotdrop) { const struct ipt_addrtype_info *info = matchinfo; const struct iphdr *iph = skb->nh.iph; @@ -43,7 +43,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in, return ret; } -static int checkentry(const char *tablename, const struct ipt_ip *ip, +static int checkentry(const char *tablename, const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { diff --git a/net/ipv4/netfilter/ipt_ah.c b/net/ipv4/netfilter/ipt_ah.c index a0fea847cb7..144adfec13c 100644 --- a/net/ipv4/netfilter/ipt_ah.c +++ b/net/ipv4/netfilter/ipt_ah.c @@ -41,6 +41,7 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { struct ip_auth_hdr _ahdr, *ah; @@ -50,7 +51,7 @@ match(const struct sk_buff *skb, if (offset) return 0; - ah = skb_header_pointer(skb, skb->nh.iph->ihl * 4, + ah = skb_header_pointer(skb, protoff, sizeof(_ahdr), &_ahdr); if (ah == NULL) { /* We've been asked to examine this packet, and we @@ -69,12 +70,13 @@ match(const struct sk_buff *skb, /* Called when user tries to insert an entry of this type. */ static int checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *ip_void, void *matchinfo, unsigned int matchinfosize, unsigned int hook_mask) { const struct ipt_ah *ahinfo = matchinfo; + const struct ipt_ip *ip = ip_void; /* Must specify proto == AH, and no unknown invflags */ if (ip->proto != IPPROTO_AH || (ip->invflags & IPT_INV_PROTO)) { diff --git a/net/ipv4/netfilter/ipt_dscp.c b/net/ipv4/netfilter/ipt_dscp.c index 5df52a64a5d..92063b4f860 100644 --- a/net/ipv4/netfilter/ipt_dscp.c +++ b/net/ipv4/netfilter/ipt_dscp.c @@ -21,7 +21,7 @@ MODULE_LICENSE("GPL"); static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *matchinfo, - int offset, int *hotdrop) + int offset, unsigned int protoff, int *hotdrop) { const struct ipt_dscp_info *info = matchinfo; const struct iphdr *iph = skb->nh.iph; @@ -31,7 +31,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in, return ((iph->tos&IPT_DSCP_MASK) == sh_dscp) ^ info->invert; } -static int checkentry(const char *tablename, const struct ipt_ip *ip, +static int checkentry(const char *tablename, const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { diff --git a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c index b6f7181e89c..e68b0c7981f 100644 --- a/net/ipv4/netfilter/ipt_ecn.c +++ b/net/ipv4/netfilter/ipt_ecn.c @@ -67,7 +67,7 @@ static inline int match_tcp(const struct sk_buff *skb, static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *matchinfo, - int offset, int *hotdrop) + int offset, unsigned int protoff, int *hotdrop) { const struct ipt_ecn_info *info = matchinfo; @@ -85,11 +85,12 @@ static int match(const struct sk_buff *skb, const struct net_device *in, return 1; } -static int checkentry(const char *tablename, const struct ipt_ip *ip, +static int checkentry(const char *tablename, const void *ip_void, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { const struct ipt_ecn_info *info = matchinfo; + const struct ipt_ip *ip = ip_void; if (matchsize != IPT_ALIGN(sizeof(struct ipt_ecn_info))) return 0; diff --git a/net/ipv4/netfilter/ipt_esp.c b/net/ipv4/netfilter/ipt_esp.c index e1d0dd31e11..9de191a8162 100644 --- a/net/ipv4/netfilter/ipt_esp.c +++ b/net/ipv4/netfilter/ipt_esp.c @@ -42,6 +42,7 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { struct ip_esp_hdr _esp, *eh; @@ -51,7 +52,7 @@ match(const struct sk_buff *skb, if (offset) return 0; - eh = skb_header_pointer(skb, skb->nh.iph->ihl * 4, + eh = skb_header_pointer(skb, protoff, sizeof(_esp), &_esp); if (eh == NULL) { /* We've been asked to examine this packet, and we @@ -70,12 +71,13 @@ match(const struct sk_buff *skb, /* Called when user tries to insert an entry of this type. */ static int checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *ip_void, void *matchinfo, unsigned int matchinfosize, unsigned int hook_mask) { const struct ipt_esp *espinfo = matchinfo; + const struct ipt_ip *ip = ip_void; /* Must specify proto == ESP, and no unknown invflags */ if (ip->proto != IPPROTO_ESP || (ip->invflags & IPT_INV_PROTO)) { diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c index 2dd1cccbdab..4fe48c1bd5f 100644 --- a/net/ipv4/netfilter/ipt_hashlimit.c +++ b/net/ipv4/netfilter/ipt_hashlimit.c @@ -429,6 +429,7 @@ hashlimit_match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { struct ipt_hashlimit_info *r = @@ -504,7 +505,7 @@ hashlimit_match(const struct sk_buff *skb, static int hashlimit_checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *inf, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ipt_iprange.c b/net/ipv4/netfilter/ipt_iprange.c index b835b7b2e56..13fb16fb789 100644 --- a/net/ipv4/netfilter/ipt_iprange.c +++ b/net/ipv4/netfilter/ipt_iprange.c @@ -28,7 +28,7 @@ match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *matchinfo, - int offset, int *hotdrop) + int offset, unsigned int protoff, int *hotdrop) { const struct ipt_iprange_info *info = matchinfo; const struct iphdr *iph = skb->nh.iph; @@ -63,7 +63,7 @@ match(const struct sk_buff *skb, } static int check(const char *tablename, - const struct ipt_ip *ip, + const void *inf, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ipt_length.c b/net/ipv4/netfilter/ipt_length.c deleted file mode 100644 index 4eabcfbda9d..00000000000 --- a/net/ipv4/netfilter/ipt_length.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Kernel module to match packet length. */ -/* (C) 1999-2001 James Morris - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include - -#include -#include - -MODULE_AUTHOR("James Morris "); -MODULE_DESCRIPTION("IP tables packet length matching module"); -MODULE_LICENSE("GPL"); - -static int -match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const void *matchinfo, - int offset, - int *hotdrop) -{ - const struct ipt_length_info *info = matchinfo; - u_int16_t pktlen = ntohs(skb->nh.iph->tot_len); - - return (pktlen >= info->min && pktlen <= info->max) ^ info->invert; -} - -static int -checkentry(const char *tablename, - const struct ipt_ip *ip, - void *matchinfo, - unsigned int matchsize, - unsigned int hook_mask) -{ - if (matchsize != IPT_ALIGN(sizeof(struct ipt_length_info))) - return 0; - - return 1; -} - -static struct ipt_match length_match = { - .name = "length", - .match = &match, - .checkentry = &checkentry, - .me = THIS_MODULE, -}; - -static int __init init(void) -{ - return ipt_register_match(&length_match); -} - -static void __exit fini(void) -{ - ipt_unregister_match(&length_match); -} - -module_init(init); -module_exit(fini); diff --git a/net/ipv4/netfilter/ipt_multiport.c b/net/ipv4/netfilter/ipt_multiport.c index 99e8188162e..2d52326553f 100644 --- a/net/ipv4/netfilter/ipt_multiport.c +++ b/net/ipv4/netfilter/ipt_multiport.c @@ -97,6 +97,7 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { u16 _ports[2], *pptr; @@ -105,7 +106,7 @@ match(const struct sk_buff *skb, if (offset) return 0; - pptr = skb_header_pointer(skb, skb->nh.iph->ihl * 4, + pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports); if (pptr == NULL) { /* We've been asked to examine this packet, and we @@ -128,6 +129,7 @@ match_v1(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { u16 _ports[2], *pptr; @@ -136,7 +138,7 @@ match_v1(const struct sk_buff *skb, if (offset) return 0; - pptr = skb_header_pointer(skb, skb->nh.iph->ihl * 4, + pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports); if (pptr == NULL) { /* We've been asked to examine this packet, and we @@ -154,7 +156,7 @@ match_v1(const struct sk_buff *skb, /* Called when user tries to insert an entry of this type. */ static int checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) @@ -164,7 +166,7 @@ checkentry(const char *tablename, static int checkentry_v1(const char *tablename, - const struct ipt_ip *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ipt_owner.c b/net/ipv4/netfilter/ipt_owner.c index 0cee2862ed8..4843d0c9734 100644 --- a/net/ipv4/netfilter/ipt_owner.c +++ b/net/ipv4/netfilter/ipt_owner.c @@ -27,6 +27,7 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { const struct ipt_owner_info *info = matchinfo; @@ -51,7 +52,7 @@ match(const struct sk_buff *skb, static int checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ipt_physdev.c b/net/ipv4/netfilter/ipt_physdev.c deleted file mode 100644 index 03f554857a4..00000000000 --- a/net/ipv4/netfilter/ipt_physdev.c +++ /dev/null @@ -1,135 +0,0 @@ -/* Kernel module to match the bridge port in and - * out device for IP packets coming into contact with a bridge. */ - -/* (C) 2001-2003 Bart De Schuymer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#define MATCH 1 -#define NOMATCH 0 - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Bart De Schuymer "); -MODULE_DESCRIPTION("iptables bridge physical device match module"); - -static int -match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const void *matchinfo, - int offset, - int *hotdrop) -{ - int i; - static const char nulldevname[IFNAMSIZ]; - const struct ipt_physdev_info *info = matchinfo; - unsigned int ret; - const char *indev, *outdev; - struct nf_bridge_info *nf_bridge; - - /* Not a bridged IP packet or no info available yet: - * LOCAL_OUT/mangle and LOCAL_OUT/nat don't know if - * the destination device will be a bridge. */ - if (!(nf_bridge = skb->nf_bridge)) { - /* Return MATCH if the invert flags of the used options are on */ - if ((info->bitmask & IPT_PHYSDEV_OP_BRIDGED) && - !(info->invert & IPT_PHYSDEV_OP_BRIDGED)) - return NOMATCH; - if ((info->bitmask & IPT_PHYSDEV_OP_ISIN) && - !(info->invert & IPT_PHYSDEV_OP_ISIN)) - return NOMATCH; - if ((info->bitmask & IPT_PHYSDEV_OP_ISOUT) && - !(info->invert & IPT_PHYSDEV_OP_ISOUT)) - return NOMATCH; - if ((info->bitmask & IPT_PHYSDEV_OP_IN) && - !(info->invert & IPT_PHYSDEV_OP_IN)) - return NOMATCH; - if ((info->bitmask & IPT_PHYSDEV_OP_OUT) && - !(info->invert & IPT_PHYSDEV_OP_OUT)) - return NOMATCH; - return MATCH; - } - - /* This only makes sense in the FORWARD and POSTROUTING chains */ - if ((info->bitmask & IPT_PHYSDEV_OP_BRIDGED) && - (!!(nf_bridge->mask & BRNF_BRIDGED) ^ - !(info->invert & IPT_PHYSDEV_OP_BRIDGED))) - return NOMATCH; - - if ((info->bitmask & IPT_PHYSDEV_OP_ISIN && - (!nf_bridge->physindev ^ !!(info->invert & IPT_PHYSDEV_OP_ISIN))) || - (info->bitmask & IPT_PHYSDEV_OP_ISOUT && - (!nf_bridge->physoutdev ^ !!(info->invert & IPT_PHYSDEV_OP_ISOUT)))) - return NOMATCH; - - if (!(info->bitmask & IPT_PHYSDEV_OP_IN)) - goto match_outdev; - indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname; - for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) { - ret |= (((const unsigned int *)indev)[i] - ^ ((const unsigned int *)info->physindev)[i]) - & ((const unsigned int *)info->in_mask)[i]; - } - - if ((ret == 0) ^ !(info->invert & IPT_PHYSDEV_OP_IN)) - return NOMATCH; - -match_outdev: - if (!(info->bitmask & IPT_PHYSDEV_OP_OUT)) - return MATCH; - outdev = nf_bridge->physoutdev ? - nf_bridge->physoutdev->name : nulldevname; - for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) { - ret |= (((const unsigned int *)outdev)[i] - ^ ((const unsigned int *)info->physoutdev)[i]) - & ((const unsigned int *)info->out_mask)[i]; - } - - return (ret != 0) ^ !(info->invert & IPT_PHYSDEV_OP_OUT); -} - -static int -checkentry(const char *tablename, - const struct ipt_ip *ip, - void *matchinfo, - unsigned int matchsize, - unsigned int hook_mask) -{ - const struct ipt_physdev_info *info = matchinfo; - - if (matchsize != IPT_ALIGN(sizeof(struct ipt_physdev_info))) - return 0; - if (!(info->bitmask & IPT_PHYSDEV_OP_MASK) || - info->bitmask & ~IPT_PHYSDEV_OP_MASK) - return 0; - return 1; -} - -static struct ipt_match physdev_match = { - .name = "physdev", - .match = &match, - .checkentry = &checkentry, - .me = THIS_MODULE, -}; - -static int __init init(void) -{ - return ipt_register_match(&physdev_match); -} - -static void __exit fini(void) -{ - ipt_unregister_match(&physdev_match); -} - -module_init(init); -module_exit(fini); diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c index 5ddccb18c65..44611d6d14f 100644 --- a/net/ipv4/netfilter/ipt_recent.c +++ b/net/ipv4/netfilter/ipt_recent.c @@ -104,6 +104,7 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop); /* Function to hash a given address into the hash table of table_size size */ @@ -317,7 +318,7 @@ static int ip_recent_ctrl(struct file *file, const char __user *input, unsigned skb->nh.iph->daddr = 0; /* Clear ttl since we have no way of knowing it */ skb->nh.iph->ttl = 0; - match(skb,NULL,NULL,info,0,NULL); + match(skb,NULL,NULL,info,0,0,NULL); kfree(skb->nh.iph); out_free_skb: @@ -357,6 +358,7 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { int pkt_count, hits_found, ans; @@ -654,7 +656,7 @@ match(const struct sk_buff *skb, */ static int checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ipt_tos.c b/net/ipv4/netfilter/ipt_tos.c index 086a1bb61e3..9ab765e126f 100644 --- a/net/ipv4/netfilter/ipt_tos.c +++ b/net/ipv4/netfilter/ipt_tos.c @@ -23,6 +23,7 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { const struct ipt_tos_info *info = matchinfo; @@ -32,7 +33,7 @@ match(const struct sk_buff *skb, static int checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) diff --git a/net/ipv4/netfilter/ipt_ttl.c b/net/ipv4/netfilter/ipt_ttl.c index 219aa9de88c..82da53f430a 100644 --- a/net/ipv4/netfilter/ipt_ttl.c +++ b/net/ipv4/netfilter/ipt_ttl.c @@ -21,7 +21,7 @@ MODULE_LICENSE("GPL"); static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *matchinfo, - int offset, int *hotdrop) + int offset, unsigned int protoff, int *hotdrop) { const struct ipt_ttl_info *info = matchinfo; @@ -47,7 +47,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in, return 0; } -static int checkentry(const char *tablename, const struct ipt_ip *ip, +static int checkentry(const char *tablename, const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c index 260a4f0a2a9..212a3079085 100644 --- a/net/ipv4/netfilter/iptable_filter.c +++ b/net/ipv4/netfilter/iptable_filter.c @@ -78,7 +78,8 @@ static struct ipt_table packet_filter = { .name = "filter", .valid_hooks = FILTER_VALID_HOOKS, .lock = RW_LOCK_UNLOCKED, - .me = THIS_MODULE + .me = THIS_MODULE, + .af = AF_INET, }; /* The work comes in here from netfilter.c. */ diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index 160eb11b6e2..3212a5cc4b6 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c @@ -109,6 +109,7 @@ static struct ipt_table packet_mangler = { .valid_hooks = MANGLE_VALID_HOOKS, .lock = RW_LOCK_UNLOCKED, .me = THIS_MODULE, + .af = AF_INET, }; /* The work comes in here from netfilter.c. */ diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c index 47449ba83eb..fdb9e9c81e8 100644 --- a/net/ipv4/netfilter/iptable_raw.c +++ b/net/ipv4/netfilter/iptable_raw.c @@ -83,7 +83,8 @@ static struct ipt_table packet_raw = { .name = "raw", .valid_hooks = RAW_VALID_HOOKS, .lock = RW_LOCK_UNLOCKED, - .me = THIS_MODULE + .me = THIS_MODULE, + .af = AF_INET, }; /* The work comes in here from netfilter.c. */ diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 0c56c52a383..167619f638c 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -575,7 +575,7 @@ MODULE_LICENSE("GPL"); static int __init init(void) { - need_nf_conntrack(); + need_conntrack(); return init_or_cleanup(1); } @@ -587,9 +587,4 @@ static void __exit fini(void) module_init(init); module_exit(fini); -void need_ip_conntrack(void) -{ -} - -EXPORT_SYMBOL(need_ip_conntrack); EXPORT_SYMBOL(nf_ct_ipv4_gather_frags); diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 105dd69ee9f..2d6f8ecbc27 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig @@ -41,6 +41,7 @@ config IP6_NF_QUEUE config IP6_NF_IPTABLES tristate "IP6 tables support (required for filtering/masq/NAT)" + depends on NETFILTER_XTABLES help ip6tables is a general, extensible packet identification framework. Currently only the packet filtering and packet mangling subsystem @@ -50,25 +51,6 @@ config IP6_NF_IPTABLES To compile it as a module, choose M here. If unsure, say N. # The simple matches. -config IP6_NF_MATCH_LIMIT - tristate "limit match support" - depends on IP6_NF_IPTABLES - help - limit matching allows you to control the rate at which a rule can be - matched: mainly useful in combination with the LOG target ("LOG - target support", below) and to avoid some Denial of Service attacks. - - To compile it as a module, choose M here. If unsure, say N. - -config IP6_NF_MATCH_MAC - tristate "MAC address match support" - depends on IP6_NF_IPTABLES - help - mac matching allows you to match packets based on the source - Ethernet address of the packet. - - To compile it as a module, choose M here. If unsure, say N. - config IP6_NF_MATCH_RT tristate "Routing header match support" depends on IP6_NF_IPTABLES @@ -124,16 +106,6 @@ config IP6_NF_MATCH_OWNER To compile it as a module, choose M here. If unsure, say N. -config IP6_NF_MATCH_MARK - tristate "netfilter MARK match support" - depends on IP6_NF_IPTABLES - help - Netfilter mark matching allows you to match packets based on the - `nfmark' value in the packet. This can be set by the MARK target - (see below). - - To compile it as a module, choose M here. If unsure, say N. - config IP6_NF_MATCH_IPV6HEADER tristate "IPv6 Extension Headers Match" depends on IP6_NF_IPTABLES @@ -151,15 +123,6 @@ config IP6_NF_MATCH_AHESP To compile it as a module, choose M here. If unsure, say N. -config IP6_NF_MATCH_LENGTH - tristate "Packet Length match support" - depends on IP6_NF_IPTABLES - help - This option allows you to match the length of a packet against a - specific value or range of values. - - To compile it as a module, choose M here. If unsure, say N. - config IP6_NF_MATCH_EUI64 tristate "EUI64 address check" depends on IP6_NF_IPTABLES @@ -170,15 +133,6 @@ config IP6_NF_MATCH_EUI64 To compile it as a module, choose M here. If unsure, say N. -config IP6_NF_MATCH_PHYSDEV - tristate "Physdev match support" - depends on IP6_NF_IPTABLES && BRIDGE_NETFILTER - help - Physdev packet matching matches against the physical bridge ports - the IP packet arrived on or will leave by. - - To compile it as a module, choose M here. If unsure, say N. - config IP6_NF_MATCH_POLICY tristate "IPsec policy match support" depends on IP6_NF_IPTABLES && XFRM @@ -219,17 +173,6 @@ config IP6_NF_TARGET_REJECT To compile it as a module, choose M here. If unsure, say N. -config IP6_NF_TARGET_NFQUEUE - tristate "NFQUEUE Target Support" - depends on IP6_NF_IPTABLES - help - This Target replaced the old obsolete QUEUE target. - - As opposed to QUEUE, it supports 65535 different queues, - not just one. - - To compile it as a module, choose M here. If unsure, say N. - config IP6_NF_MANGLE tristate "Packet mangling" depends on IP6_NF_IPTABLES @@ -240,19 +183,6 @@ config IP6_NF_MANGLE To compile it as a module, choose M here. If unsure, say N. -config IP6_NF_TARGET_MARK - tristate "MARK target support" - depends on IP6_NF_MANGLE - help - This option adds a `MARK' target, which allows you to create rules - in the `mangle' table which alter the netfilter mark (nfmark) field - associated with the packet packet prior to routing. This can change - the routing method (see `Use netfilter MARK value as routing - key') and can also be used by other subsystems to change their - behavior. - - To compile it as a module, choose M here. If unsure, say N. - config IP6_NF_TARGET_HL tristate 'HL (hoplimit) target support' depends on IP6_NF_MANGLE diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index c0c809b426e..663b4749820 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile @@ -4,10 +4,7 @@ # Link order matters here. obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o -obj-$(CONFIG_IP6_NF_MATCH_LIMIT) += ip6t_limit.o -obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o -obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o @@ -17,12 +14,9 @@ obj-$(CONFIG_IP6_NF_MATCH_POLICY) += ip6t_policy.o obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o -obj-$(CONFIG_IP6_NF_MATCH_PHYSDEV) += ip6t_physdev.o obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o -obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o -obj-$(CONFIG_IP6_NF_TARGET_NFQUEUE) += ip6t_NFQUEUE.o obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 1390370186d..847068fd336 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -13,6 +13,9 @@ * a table * 06 Jun 2002 Andras Kis-Szabo * - new extension header parser code + * 15 Oct 2005 Harald Welte + * - Unification of {ip,ip6}_tables into x_tables + * - Removed tcp and udp code, since it's not ipv6 specific */ #include @@ -23,8 +26,6 @@ #include #include #include -#include -#include #include #include #include @@ -33,6 +34,7 @@ #include #include +#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Netfilter Core Team "); @@ -67,13 +69,8 @@ do { \ #else #define IP_NF_ASSERT(x) #endif -#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) -static DECLARE_MUTEX(ip6t_mutex); -/* Must have mutex */ -#define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0) -#define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0) #include #if 0 @@ -91,30 +88,6 @@ static DECLARE_MUTEX(ip6t_mutex); Hence the start of any table is given by get_table() below. */ -/* The table itself */ -struct ip6t_table_info -{ - /* Size per table */ - unsigned int size; - /* Number of entries: FIXME. --RR */ - unsigned int number; - /* Initial number of entries. Needed for module usage count */ - unsigned int initial_entries; - - /* Entry points and underflows */ - unsigned int hook_entry[NF_IP6_NUMHOOKS]; - unsigned int underflow[NF_IP6_NUMHOOKS]; - - /* ip6t_entry tables: one per CPU */ - void *entries[NR_CPUS]; -}; - -static LIST_HEAD(ip6t_target); -static LIST_HEAD(ip6t_match); -static LIST_HEAD(ip6t_tables); -#define SET_COUNTER(c,b,p) do { (c).bcnt = (b); (c).pcnt = (p); } while(0) -#define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0) - #if 0 #define down(x) do { printk("DOWN:%u:" #x "\n", __LINE__); down(x); } while(0) #define down_interruptible(x) ({ int __r; printk("DOWNi:%u:" #x "\n", __LINE__); __r = down_interruptible(x); if (__r != 0) printk("ABORT-DOWNi:%u\n", __LINE__); __r; }) @@ -297,7 +270,7 @@ ip6t_do_table(struct sk_buff **pskb, unsigned int hook, const struct net_device *in, const struct net_device *out, - struct ip6t_table *table, + struct xt_table *table, void *userdata) { static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); @@ -309,6 +282,7 @@ ip6t_do_table(struct sk_buff **pskb, const char *indev, *outdev; void *table_base; struct ip6t_entry *e, *back; + struct xt_table_info *private; /* Initialization */ indev = in ? in->name : nulldevname; @@ -321,9 +295,10 @@ ip6t_do_table(struct sk_buff **pskb, * match it. */ read_lock_bh(&table->lock); + private = table->private; IP_NF_ASSERT(table->valid_hooks & (1 << hook)); - table_base = (void *)table->private->entries[smp_processor_id()]; - e = get_entry(table_base, table->private->hook_entry[hook]); + table_base = (void *)private->entries[smp_processor_id()]; + e = get_entry(table_base, private->hook_entry[hook]); #ifdef CONFIG_NETFILTER_DEBUG /* Check noone else using our table */ @@ -339,7 +314,7 @@ ip6t_do_table(struct sk_buff **pskb, #endif /* For return from builtin chain */ - back = get_entry(table_base, table->private->underflow[hook]); + back = get_entry(table_base, private->underflow[hook]); do { IP_NF_ASSERT(e); @@ -439,145 +414,6 @@ ip6t_do_table(struct sk_buff **pskb, #endif } -/* - * These are weird, but module loading must not be done with mutex - * held (since they will register), and we have to have a single - * function to use try_then_request_module(). - */ - -/* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */ -static inline struct ip6t_table *find_table_lock(const char *name) -{ - struct ip6t_table *t; - - if (down_interruptible(&ip6t_mutex) != 0) - return ERR_PTR(-EINTR); - - list_for_each_entry(t, &ip6t_tables, list) - if (strcmp(t->name, name) == 0 && try_module_get(t->me)) - return t; - up(&ip6t_mutex); - return NULL; -} - -/* Find match, grabs ref. Returns ERR_PTR() on error. */ -static inline struct ip6t_match *find_match(const char *name, u8 revision) -{ - struct ip6t_match *m; - int err = 0; - - if (down_interruptible(&ip6t_mutex) != 0) - return ERR_PTR(-EINTR); - - list_for_each_entry(m, &ip6t_match, list) { - if (strcmp(m->name, name) == 0) { - if (m->revision == revision) { - if (try_module_get(m->me)) { - up(&ip6t_mutex); - return m; - } - } else - err = -EPROTOTYPE; /* Found something. */ - } - } - up(&ip6t_mutex); - return ERR_PTR(err); -} - -/* Find target, grabs ref. Returns ERR_PTR() on error. */ -static inline struct ip6t_target *find_target(const char *name, u8 revision) -{ - struct ip6t_target *t; - int err = 0; - - if (down_interruptible(&ip6t_mutex) != 0) - return ERR_PTR(-EINTR); - - list_for_each_entry(t, &ip6t_target, list) { - if (strcmp(t->name, name) == 0) { - if (t->revision == revision) { - if (try_module_get(t->me)) { - up(&ip6t_mutex); - return t; - } - } else - err = -EPROTOTYPE; /* Found something. */ - } - } - up(&ip6t_mutex); - return ERR_PTR(err); -} - -struct ip6t_target *ip6t_find_target(const char *name, u8 revision) -{ - struct ip6t_target *target; - - target = try_then_request_module(find_target(name, revision), - "ip6t_%s", name); - if (IS_ERR(target) || !target) - return NULL; - return target; -} - -static int match_revfn(const char *name, u8 revision, int *bestp) -{ - struct ip6t_match *m; - int have_rev = 0; - - list_for_each_entry(m, &ip6t_match, list) { - if (strcmp(m->name, name) == 0) { - if (m->revision > *bestp) - *bestp = m->revision; - if (m->revision == revision) - have_rev = 1; - } - } - return have_rev; -} - -static int target_revfn(const char *name, u8 revision, int *bestp) -{ - struct ip6t_target *t; - int have_rev = 0; - - list_for_each_entry(t, &ip6t_target, list) { - if (strcmp(t->name, name) == 0) { - if (t->revision > *bestp) - *bestp = t->revision; - if (t->revision == revision) - have_rev = 1; - } - } - return have_rev; -} - -/* Returns true or fals (if no such extension at all) */ -static inline int find_revision(const char *name, u8 revision, - int (*revfn)(const char *, u8, int *), - int *err) -{ - int have_rev, best = -1; - - if (down_interruptible(&ip6t_mutex) != 0) { - *err = -EINTR; - return 1; - } - have_rev = revfn(name, revision, &best); - up(&ip6t_mutex); - - /* Nothing at all? Return 0 to try loading module. */ - if (best == -1) { - *err = -ENOENT; - return 0; - } - - *err = best; - if (!have_rev) - *err = -EPROTONOSUPPORT; - return 1; -} - - /* All zeroes == unconditional rule. */ static inline int unconditional(const struct ip6t_ip6 *ipv6) @@ -594,7 +430,7 @@ unconditional(const struct ip6t_ip6 *ipv6) /* Figures out from what hook each rule can be called: returns 0 if there are loops. Puts hook bitmask in comefrom. */ static int -mark_source_chains(struct ip6t_table_info *newinfo, +mark_source_chains(struct xt_table_info *newinfo, unsigned int valid_hooks, void *entry0) { unsigned int hook; @@ -740,11 +576,11 @@ check_match(struct ip6t_entry_match *m, { struct ip6t_match *match; - match = try_then_request_module(find_match(m->u.user.name, - m->u.user.revision), + match = try_then_request_module(xt_find_match(AF_INET6, m->u.user.name, + m->u.user.revision), "ip6t_%s", m->u.user.name); if (IS_ERR(match) || !match) { - duprintf("check_match: `%s' not found\n", m->u.user.name); + duprintf("check_match: `%s' not found\n", m->u.user.name); return match ? PTR_ERR(match) : -ENOENT; } m->u.kernel.match = match; @@ -785,8 +621,9 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size, goto cleanup_matches; t = ip6t_get_target(e); - target = try_then_request_module(find_target(t->u.user.name, - t->u.user.revision), + target = try_then_request_module(xt_find_target(AF_INET6, + t->u.user.name, + t->u.user.revision), "ip6t_%s", t->u.user.name); if (IS_ERR(target) || !target) { duprintf("check_entry: `%s' not found\n", t->u.user.name); @@ -822,7 +659,7 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size, static inline int check_entry_size_and_hooks(struct ip6t_entry *e, - struct ip6t_table_info *newinfo, + struct xt_table_info *newinfo, unsigned char *base, unsigned char *limit, const unsigned int *hook_entries, @@ -856,7 +693,7 @@ check_entry_size_and_hooks(struct ip6t_entry *e, < 0 (not IP6T_RETURN). --RR */ /* Clear counters and comefrom */ - e->counters = ((struct ip6t_counters) { 0, 0 }); + e->counters = ((struct xt_counters) { 0, 0 }); e->comefrom = 0; (*i)++; @@ -886,7 +723,7 @@ cleanup_entry(struct ip6t_entry *e, unsigned int *i) static int translate_table(const char *name, unsigned int valid_hooks, - struct ip6t_table_info *newinfo, + struct xt_table_info *newinfo, void *entry0, unsigned int size, unsigned int number, @@ -963,48 +800,10 @@ translate_table(const char *name, return ret; } -static struct ip6t_table_info * -replace_table(struct ip6t_table *table, - unsigned int num_counters, - struct ip6t_table_info *newinfo, - int *error) -{ - struct ip6t_table_info *oldinfo; - -#ifdef CONFIG_NETFILTER_DEBUG - { - int cpu; - - for_each_cpu(cpu) { - struct ip6t_entry *table_base = newinfo->entries[cpu]; - if (table_base) - table_base->comefrom = 0xdead57ac; - } - } -#endif - - /* Do the substitution. */ - write_lock_bh(&table->lock); - /* Check inside lock: is the old number correct? */ - if (num_counters != table->private->number) { - duprintf("num_counters != table->private->number (%u/%u)\n", - num_counters, table->private->number); - write_unlock_bh(&table->lock); - *error = -EAGAIN; - return NULL; - } - oldinfo = table->private; - table->private = newinfo; - newinfo->initial_entries = oldinfo->initial_entries; - write_unlock_bh(&table->lock); - - return oldinfo; -} - /* Gets counters. */ static inline int add_entry_to_counter(const struct ip6t_entry *e, - struct ip6t_counters total[], + struct xt_counters total[], unsigned int *i) { ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); @@ -1025,8 +824,8 @@ set_entry_to_counter(const struct ip6t_entry *e, } static void -get_counters(const struct ip6t_table_info *t, - struct ip6t_counters counters[]) +get_counters(const struct xt_table_info *t, + struct xt_counters counters[]) { unsigned int cpu; unsigned int i; @@ -1060,19 +859,20 @@ get_counters(const struct ip6t_table_info *t, static int copy_entries_to_user(unsigned int total_size, - struct ip6t_table *table, + struct xt_table *table, void __user *userptr) { unsigned int off, num, countersize; struct ip6t_entry *e; - struct ip6t_counters *counters; + struct xt_counters *counters; + struct xt_table_info *private = table->private; int ret = 0; void *loc_cpu_entry; /* We need atomic snapshot of counters: rest doesn't change (other than comefrom, which userspace doesn't care about). */ - countersize = sizeof(struct ip6t_counters) * table->private->number; + countersize = sizeof(struct xt_counters) * private->number; counters = vmalloc(countersize); if (counters == NULL) @@ -1080,11 +880,11 @@ copy_entries_to_user(unsigned int total_size, /* First, sum counters... */ write_lock_bh(&table->lock); - get_counters(table->private, counters); + get_counters(private, counters); write_unlock_bh(&table->lock); /* choose the copy that is on ourc node/cpu */ - loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; + loc_cpu_entry = private->entries[raw_smp_processor_id()]; if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) { ret = -EFAULT; goto free_counters; @@ -1143,87 +943,42 @@ get_entries(const struct ip6t_get_entries *entries, struct ip6t_get_entries __user *uptr) { int ret; - struct ip6t_table *t; + struct xt_table *t; - t = find_table_lock(entries->name); + t = xt_find_table_lock(AF_INET6, entries->name); if (t && !IS_ERR(t)) { - duprintf("t->private->number = %u\n", - t->private->number); - if (entries->size == t->private->size) - ret = copy_entries_to_user(t->private->size, + struct xt_table_info *private = t->private; + duprintf("t->private->number = %u\n", private->number); + if (entries->size == private->size) + ret = copy_entries_to_user(private->size, t, uptr->entrytable); else { duprintf("get_entries: I've got %u not %u!\n", - t->private->size, - entries->size); + private->size, entries->size); ret = -EINVAL; } module_put(t->me); - up(&ip6t_mutex); + xt_table_unlock(t); } else ret = t ? PTR_ERR(t) : -ENOENT; return ret; } -static void free_table_info(struct ip6t_table_info *info) -{ - int cpu; - for_each_cpu(cpu) { - if (info->size <= PAGE_SIZE) - kfree(info->entries[cpu]); - else - vfree(info->entries[cpu]); - } - kfree(info); -} - -static struct ip6t_table_info *alloc_table_info(unsigned int size) -{ - struct ip6t_table_info *newinfo; - int cpu; - - newinfo = kzalloc(sizeof(struct ip6t_table_info), GFP_KERNEL); - if (!newinfo) - return NULL; - - newinfo->size = size; - - for_each_cpu(cpu) { - if (size <= PAGE_SIZE) - newinfo->entries[cpu] = kmalloc_node(size, - GFP_KERNEL, - cpu_to_node(cpu)); - else - newinfo->entries[cpu] = vmalloc_node(size, - cpu_to_node(cpu)); - if (newinfo->entries[cpu] == NULL) { - free_table_info(newinfo); - return NULL; - } - } - - return newinfo; -} - static int do_replace(void __user *user, unsigned int len) { int ret; struct ip6t_replace tmp; - struct ip6t_table *t; - struct ip6t_table_info *newinfo, *oldinfo; - struct ip6t_counters *counters; + struct xt_table *t; + struct xt_table_info *newinfo, *oldinfo; + struct xt_counters *counters; void *loc_cpu_entry, *loc_cpu_old_entry; if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) return -EFAULT; - /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ - if ((SMP_ALIGN(tmp.size) >> PAGE_SHIFT) + 2 > num_physpages) - return -ENOMEM; - - newinfo = alloc_table_info(tmp.size); + newinfo = xt_alloc_table_info(tmp.size); if (!newinfo) return -ENOMEM; @@ -1235,7 +990,7 @@ do_replace(void __user *user, unsigned int len) goto free_newinfo; } - counters = vmalloc(tmp.num_counters * sizeof(struct ip6t_counters)); + counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters)); if (!counters) { ret = -ENOMEM; goto free_newinfo; @@ -1249,7 +1004,7 @@ do_replace(void __user *user, unsigned int len) duprintf("ip_tables: Translated table\n"); - t = try_then_request_module(find_table_lock(tmp.name), + t = try_then_request_module(xt_find_table_lock(AF_INET6, tmp.name), "ip6table_%s", tmp.name); if (!t || IS_ERR(t)) { ret = t ? PTR_ERR(t) : -ENOENT; @@ -1264,7 +1019,7 @@ do_replace(void __user *user, unsigned int len) goto put_module; } - oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); + oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret); if (!oldinfo) goto put_module; @@ -1283,23 +1038,23 @@ do_replace(void __user *user, unsigned int len) /* Decrease module usage counts and free resource */ loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; IP6T_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); - free_table_info(oldinfo); + xt_free_table_info(oldinfo); if (copy_to_user(tmp.counters, counters, - sizeof(struct ip6t_counters) * tmp.num_counters) != 0) + sizeof(struct xt_counters) * tmp.num_counters) != 0) ret = -EFAULT; vfree(counters); - up(&ip6t_mutex); + xt_table_unlock(t); return ret; put_module: module_put(t->me); - up(&ip6t_mutex); + xt_table_unlock(t); free_newinfo_counters_untrans: IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL); free_newinfo_counters: vfree(counters); free_newinfo: - free_table_info(newinfo); + xt_free_table_info(newinfo); return ret; } @@ -1307,7 +1062,7 @@ do_replace(void __user *user, unsigned int len) * and everything is OK. */ static inline int add_counter_to_entry(struct ip6t_entry *e, - const struct ip6t_counters addme[], + const struct xt_counters addme[], unsigned int *i) { #if 0 @@ -1329,15 +1084,16 @@ static int do_add_counters(void __user *user, unsigned int len) { unsigned int i; - struct ip6t_counters_info tmp, *paddc; - struct ip6t_table *t; + struct xt_counters_info tmp, *paddc; + struct xt_table_info *private; + struct xt_table *t; int ret = 0; void *loc_cpu_entry; if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) return -EFAULT; - if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct ip6t_counters)) + if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters)) return -EINVAL; paddc = vmalloc(len); @@ -1349,29 +1105,30 @@ do_add_counters(void __user *user, unsigned int len) goto free; } - t = find_table_lock(tmp.name); + t = xt_find_table_lock(AF_INET6, tmp.name); if (!t || IS_ERR(t)) { ret = t ? PTR_ERR(t) : -ENOENT; goto free; } write_lock_bh(&t->lock); - if (t->private->number != paddc->num_counters) { + private = t->private; + if (private->number != paddc->num_counters) { ret = -EINVAL; goto unlock_up_free; } i = 0; /* Choose the copy that is on our node */ - loc_cpu_entry = t->private->entries[smp_processor_id()]; + loc_cpu_entry = private->entries[smp_processor_id()]; IP6T_ENTRY_ITERATE(loc_cpu_entry, - t->private->size, + private->size, add_counter_to_entry, paddc->counters, &i); unlock_up_free: write_unlock_bh(&t->lock); - up(&ip6t_mutex); + xt_table_unlock(t); module_put(t->me); free: vfree(paddc); @@ -1415,7 +1172,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) switch (cmd) { case IP6T_SO_GET_INFO: { char name[IP6T_TABLE_MAXNAMELEN]; - struct ip6t_table *t; + struct xt_table *t; if (*len != sizeof(struct ip6t_getinfo)) { duprintf("length %u != %u\n", *len, @@ -1430,25 +1187,26 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) } name[IP6T_TABLE_MAXNAMELEN-1] = '\0'; - t = try_then_request_module(find_table_lock(name), + t = try_then_request_module(xt_find_table_lock(AF_INET6, name), "ip6table_%s", name); if (t && !IS_ERR(t)) { struct ip6t_getinfo info; + struct xt_table_info *private = t->private; info.valid_hooks = t->valid_hooks; - memcpy(info.hook_entry, t->private->hook_entry, + memcpy(info.hook_entry, private->hook_entry, sizeof(info.hook_entry)); - memcpy(info.underflow, t->private->underflow, + memcpy(info.underflow, private->underflow, sizeof(info.underflow)); - info.num_entries = t->private->number; - info.size = t->private->size; + info.num_entries = private->number; + info.size = private->size; memcpy(info.name, name, sizeof(info.name)); if (copy_to_user(user, &info, *len) != 0) ret = -EFAULT; else ret = 0; - up(&ip6t_mutex); + xt_table_unlock(t); module_put(t->me); } else ret = t ? PTR_ERR(t) : -ENOENT; @@ -1475,7 +1233,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) case IP6T_SO_GET_REVISION_MATCH: case IP6T_SO_GET_REVISION_TARGET: { struct ip6t_get_revision rev; - int (*revfn)(const char *, u8, int *); + int target; if (*len != sizeof(rev)) { ret = -EINVAL; @@ -1487,12 +1245,13 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) } if (cmd == IP6T_SO_GET_REVISION_TARGET) - revfn = target_revfn; + target = 1; else - revfn = match_revfn; + target = 0; - try_then_request_module(find_revision(rev.name, rev.revision, - revfn, &ret), + try_then_request_module(xt_find_revision(AF_INET6, rev.name, + rev.revision, + target, &ret), "ip6t_%s", rev.name); break; } @@ -1505,61 +1264,16 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) return ret; } -/* Registration hooks for targets. */ -int -ip6t_register_target(struct ip6t_target *target) -{ - int ret; - - ret = down_interruptible(&ip6t_mutex); - if (ret != 0) - return ret; - list_add(&target->list, &ip6t_target); - up(&ip6t_mutex); - return ret; -} - -void -ip6t_unregister_target(struct ip6t_target *target) -{ - down(&ip6t_mutex); - LIST_DELETE(&ip6t_target, target); - up(&ip6t_mutex); -} - -int -ip6t_register_match(struct ip6t_match *match) -{ - int ret; - - ret = down_interruptible(&ip6t_mutex); - if (ret != 0) - return ret; - - list_add(&match->list, &ip6t_match); - up(&ip6t_mutex); - - return ret; -} - -void -ip6t_unregister_match(struct ip6t_match *match) -{ - down(&ip6t_mutex); - LIST_DELETE(&ip6t_match, match); - up(&ip6t_mutex); -} - -int ip6t_register_table(struct ip6t_table *table, +int ip6t_register_table(struct xt_table *table, const struct ip6t_replace *repl) { int ret; - struct ip6t_table_info *newinfo; - static struct ip6t_table_info bootstrap + struct xt_table_info *newinfo; + static struct xt_table_info bootstrap = { 0, 0, 0, { 0 }, { 0 }, { } }; void *loc_cpu_entry; - newinfo = alloc_table_info(repl->size); + newinfo = xt_alloc_table_info(repl->size); if (!newinfo) return -ENOMEM; @@ -1573,244 +1287,29 @@ int ip6t_register_table(struct ip6t_table *table, repl->hook_entry, repl->underflow); if (ret != 0) { - free_table_info(newinfo); + xt_free_table_info(newinfo); return ret; } - ret = down_interruptible(&ip6t_mutex); - if (ret != 0) { - free_table_info(newinfo); + if (xt_register_table(table, &bootstrap, newinfo) != 0) { + xt_free_table_info(newinfo); return ret; } - /* Don't autoload: we'd eat our tail... */ - if (list_named_find(&ip6t_tables, table->name)) { - ret = -EEXIST; - goto free_unlock; - } - - /* Simplifies replace_table code. */ - table->private = &bootstrap; - if (!replace_table(table, 0, newinfo, &ret)) - goto free_unlock; - - duprintf("table->private->number = %u\n", - table->private->number); - - /* save number of initial entries */ - table->private->initial_entries = table->private->number; - - rwlock_init(&table->lock); - list_prepend(&ip6t_tables, table); - - unlock: - up(&ip6t_mutex); - return ret; - - free_unlock: - free_table_info(newinfo); - goto unlock; + return 0; } -void ip6t_unregister_table(struct ip6t_table *table) +void ip6t_unregister_table(struct xt_table *table) { + struct xt_table_info *private; void *loc_cpu_entry; - down(&ip6t_mutex); - LIST_DELETE(&ip6t_tables, table); - up(&ip6t_mutex); + private = xt_unregister_table(table); /* Decrease module usage counts and free resources */ - loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; - IP6T_ENTRY_ITERATE(loc_cpu_entry, table->private->size, - cleanup_entry, NULL); - free_table_info(table->private); -} - -/* Returns 1 if the port is matched by the range, 0 otherwise */ -static inline int -port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert) -{ - int ret; - - ret = (port >= min && port <= max) ^ invert; - return ret; -} - -static int -tcp_find_option(u_int8_t option, - const struct sk_buff *skb, - unsigned int tcpoff, - unsigned int optlen, - int invert, - int *hotdrop) -{ - /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */ - u_int8_t _opt[60 - sizeof(struct tcphdr)], *op; - unsigned int i; - - duprintf("tcp_match: finding option\n"); - if (!optlen) - return invert; - /* If we don't have the whole header, drop packet. */ - op = skb_header_pointer(skb, tcpoff + sizeof(struct tcphdr), optlen, - _opt); - if (op == NULL) { - *hotdrop = 1; - return 0; - } - - for (i = 0; i < optlen; ) { - if (op[i] == option) return !invert; - if (op[i] < 2) i++; - else i += op[i+1]?:1; - } - - return invert; -} - -static int -tcp_match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const void *matchinfo, - int offset, - unsigned int protoff, - int *hotdrop) -{ - struct tcphdr _tcph, *th; - const struct ip6t_tcp *tcpinfo = matchinfo; - - if (offset) { - /* To quote Alan: - - Don't allow a fragment of TCP 8 bytes in. Nobody normal - causes this. Its a cracker trying to break in by doing a - flag overwrite to pass the direction checks. - */ - if (offset == 1) { - duprintf("Dropping evil TCP offset=1 frag.\n"); - *hotdrop = 1; - } - /* Must not be a fragment. */ - return 0; - } - -#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg)) - - th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); - if (th == NULL) { - /* We've been asked to examine this packet, and we - can't. Hence, no choice but to drop. */ - duprintf("Dropping evil TCP offset=0 tinygram.\n"); - *hotdrop = 1; - return 0; - } - - if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1], - ntohs(th->source), - !!(tcpinfo->invflags & IP6T_TCP_INV_SRCPT))) - return 0; - if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1], - ntohs(th->dest), - !!(tcpinfo->invflags & IP6T_TCP_INV_DSTPT))) - return 0; - if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask) - == tcpinfo->flg_cmp, - IP6T_TCP_INV_FLAGS)) - return 0; - if (tcpinfo->option) { - if (th->doff * 4 < sizeof(_tcph)) { - *hotdrop = 1; - return 0; - } - if (!tcp_find_option(tcpinfo->option, skb, protoff, - th->doff*4 - sizeof(*th), - tcpinfo->invflags & IP6T_TCP_INV_OPTION, - hotdrop)) - return 0; - } - return 1; -} - -/* Called when user tries to insert an entry of this type. */ -static int -tcp_checkentry(const char *tablename, - const struct ip6t_ip6 *ipv6, - void *matchinfo, - unsigned int matchsize, - unsigned int hook_mask) -{ - const struct ip6t_tcp *tcpinfo = matchinfo; - - /* Must specify proto == TCP, and no unknown invflags */ - return ipv6->proto == IPPROTO_TCP - && !(ipv6->invflags & IP6T_INV_PROTO) - && matchsize == IP6T_ALIGN(sizeof(struct ip6t_tcp)) - && !(tcpinfo->invflags & ~IP6T_TCP_INV_MASK); -} - -static int -udp_match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const void *matchinfo, - int offset, - unsigned int protoff, - int *hotdrop) -{ - struct udphdr _udph, *uh; - const struct ip6t_udp *udpinfo = matchinfo; - - /* Must not be a fragment. */ - if (offset) - return 0; - - uh = skb_header_pointer(skb, protoff, sizeof(_udph), &_udph); - if (uh == NULL) { - /* We've been asked to examine this packet, and we - can't. Hence, no choice but to drop. */ - duprintf("Dropping evil UDP tinygram.\n"); - *hotdrop = 1; - return 0; - } - - return port_match(udpinfo->spts[0], udpinfo->spts[1], - ntohs(uh->source), - !!(udpinfo->invflags & IP6T_UDP_INV_SRCPT)) - && port_match(udpinfo->dpts[0], udpinfo->dpts[1], - ntohs(uh->dest), - !!(udpinfo->invflags & IP6T_UDP_INV_DSTPT)); -} - -/* Called when user tries to insert an entry of this type. */ -static int -udp_checkentry(const char *tablename, - const struct ip6t_ip6 *ipv6, - void *matchinfo, - unsigned int matchinfosize, - unsigned int hook_mask) -{ - const struct ip6t_udp *udpinfo = matchinfo; - - /* Must specify proto == UDP, and no unknown invflags */ - if (ipv6->proto != IPPROTO_UDP || (ipv6->invflags & IP6T_INV_PROTO)) { - duprintf("ip6t_udp: Protocol %u != %u\n", ipv6->proto, - IPPROTO_UDP); - return 0; - } - if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_udp))) { - duprintf("ip6t_udp: matchsize %u != %u\n", - matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_udp))); - return 0; - } - if (udpinfo->invflags & ~IP6T_UDP_INV_MASK) { - duprintf("ip6t_udp: unknown flags %X\n", - udpinfo->invflags); - return 0; - } - - return 1; + loc_cpu_entry = private->entries[raw_smp_processor_id()]; + IP6T_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL); + xt_free_table_info(private); } /* Returns 1 if the type and code is matched by the range, 0 otherwise */ @@ -1858,11 +1357,12 @@ icmp6_match(const struct sk_buff *skb, /* Called when user tries to insert an entry of this type. */ static int icmp6_checkentry(const char *tablename, - const struct ip6t_ip6 *ipv6, + const void *entry, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { + const struct ip6t_ip6 *ipv6 = entry; const struct ip6t_icmp *icmpinfo = matchinfo; /* Must specify proto == ICMP, and no unknown invflags */ @@ -1892,164 +1392,42 @@ static struct nf_sockopt_ops ip6t_sockopts = { .get = do_ip6t_get_ctl, }; -static struct ip6t_match tcp_matchstruct = { - .name = "tcp", - .match = &tcp_match, - .checkentry = &tcp_checkentry, -}; - -static struct ip6t_match udp_matchstruct = { - .name = "udp", - .match = &udp_match, - .checkentry = &udp_checkentry, -}; - static struct ip6t_match icmp6_matchstruct = { .name = "icmp6", .match = &icmp6_match, .checkentry = &icmp6_checkentry, }; -#ifdef CONFIG_PROC_FS -static inline int print_name(const char *i, - off_t start_offset, char *buffer, int length, - off_t *pos, unsigned int *count) -{ - if ((*count)++ >= start_offset) { - unsigned int namelen; - - namelen = sprintf(buffer + *pos, "%s\n", - i + sizeof(struct list_head)); - if (*pos + namelen > length) { - /* Stop iterating */ - return 1; - } - *pos += namelen; - } - return 0; -} - -static inline int print_target(const struct ip6t_target *t, - off_t start_offset, char *buffer, int length, - off_t *pos, unsigned int *count) -{ - if (t == &ip6t_standard_target || t == &ip6t_error_target) - return 0; - return print_name((char *)t, start_offset, buffer, length, pos, count); -} - -static int ip6t_get_tables(char *buffer, char **start, off_t offset, int length) -{ - off_t pos = 0; - unsigned int count = 0; - - if (down_interruptible(&ip6t_mutex) != 0) - return 0; - - LIST_FIND(&ip6t_tables, print_name, char *, - offset, buffer, length, &pos, &count); - - up(&ip6t_mutex); - - /* `start' hack - see fs/proc/generic.c line ~105 */ - *start=(char *)((unsigned long)count-offset); - return pos; -} - -static int ip6t_get_targets(char *buffer, char **start, off_t offset, int length) -{ - off_t pos = 0; - unsigned int count = 0; - - if (down_interruptible(&ip6t_mutex) != 0) - return 0; - - LIST_FIND(&ip6t_target, print_target, struct ip6t_target *, - offset, buffer, length, &pos, &count); - - up(&ip6t_mutex); - - *start = (char *)((unsigned long)count - offset); - return pos; -} - -static int ip6t_get_matches(char *buffer, char **start, off_t offset, int length) -{ - off_t pos = 0; - unsigned int count = 0; - - if (down_interruptible(&ip6t_mutex) != 0) - return 0; - - LIST_FIND(&ip6t_match, print_name, char *, - offset, buffer, length, &pos, &count); - - up(&ip6t_mutex); - - *start = (char *)((unsigned long)count - offset); - return pos; -} - -static const struct { char *name; get_info_t *get_info; } ip6t_proc_entry[] = -{ { "ip6_tables_names", ip6t_get_tables }, - { "ip6_tables_targets", ip6t_get_targets }, - { "ip6_tables_matches", ip6t_get_matches }, - { NULL, NULL} }; -#endif /*CONFIG_PROC_FS*/ - static int __init init(void) { int ret; + xt_proto_init(AF_INET6); + /* Noone else will be downing sem now, so we won't sleep */ - down(&ip6t_mutex); - list_append(&ip6t_target, &ip6t_standard_target); - list_append(&ip6t_target, &ip6t_error_target); - list_append(&ip6t_match, &tcp_matchstruct); - list_append(&ip6t_match, &udp_matchstruct); - list_append(&ip6t_match, &icmp6_matchstruct); - up(&ip6t_mutex); + xt_register_target(AF_INET6, &ip6t_standard_target); + xt_register_target(AF_INET6, &ip6t_error_target); + xt_register_match(AF_INET6, &icmp6_matchstruct); /* Register setsockopt */ ret = nf_register_sockopt(&ip6t_sockopts); if (ret < 0) { duprintf("Unable to register sockopts.\n"); + xt_proto_fini(AF_INET6); return ret; } -#ifdef CONFIG_PROC_FS - { - struct proc_dir_entry *proc; - int i; - - for (i = 0; ip6t_proc_entry[i].name; i++) { - proc = proc_net_create(ip6t_proc_entry[i].name, 0, - ip6t_proc_entry[i].get_info); - if (!proc) { - while (--i >= 0) - proc_net_remove(ip6t_proc_entry[i].name); - nf_unregister_sockopt(&ip6t_sockopts); - return -ENOMEM; - } - proc->owner = THIS_MODULE; - } - } -#endif - - printk("ip6_tables: (C) 2000-2002 Netfilter core team\n"); + printk("ip6_tables: (C) 2000-2006 Netfilter Core Team\n"); return 0; } static void __exit fini(void) { nf_unregister_sockopt(&ip6t_sockopts); -#ifdef CONFIG_PROC_FS - { - int i; - for (i = 0; ip6t_proc_entry[i].name; i++) - proc_net_remove(ip6t_proc_entry[i].name); - } -#endif + xt_unregister_match(AF_INET6, &icmp6_matchstruct); + xt_unregister_target(AF_INET6, &ip6t_error_target); + xt_unregister_target(AF_INET6, &ip6t_standard_target); + xt_proto_fini(AF_INET6); } /* @@ -2128,10 +1506,6 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, EXPORT_SYMBOL(ip6t_register_table); EXPORT_SYMBOL(ip6t_unregister_table); EXPORT_SYMBOL(ip6t_do_table); -EXPORT_SYMBOL(ip6t_register_match); -EXPORT_SYMBOL(ip6t_unregister_match); -EXPORT_SYMBOL(ip6t_register_target); -EXPORT_SYMBOL(ip6t_unregister_target); EXPORT_SYMBOL(ip6t_ext_hdr); EXPORT_SYMBOL(ipv6_find_hdr); EXPORT_SYMBOL(ip6_masked_addrcmp); diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c index 8f5549b7272..306200c3505 100644 --- a/net/ipv6/netfilter/ip6t_HL.c +++ b/net/ipv6/netfilter/ip6t_HL.c @@ -62,7 +62,7 @@ static unsigned int ip6t_hl_target(struct sk_buff **pskb, } static int ip6t_hl_checkentry(const char *tablename, - const struct ip6t_entry *e, + const void *entry, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index ae4653bfd65..fc19d8a4ca6 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c @@ -444,7 +444,7 @@ ip6t_log_target(struct sk_buff **pskb, static int ip6t_log_checkentry(const char *tablename, - const struct ip6t_entry *e, + const void *entry, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) diff --git a/net/ipv6/netfilter/ip6t_MARK.c b/net/ipv6/netfilter/ip6t_MARK.c deleted file mode 100644 index eab8fb864ee..00000000000 --- a/net/ipv6/netfilter/ip6t_MARK.c +++ /dev/null @@ -1,81 +0,0 @@ -/* This is a module which is used for setting the NFMARK field of an skb. */ - -/* (C) 1999-2001 Marc Boucher - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include - -#include -#include - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Netfilter Core Team "); - -static unsigned int -target(struct sk_buff **pskb, - const struct net_device *in, - const struct net_device *out, - unsigned int hooknum, - const void *targinfo, - void *userinfo) -{ - const struct ip6t_mark_target_info *markinfo = targinfo; - - if((*pskb)->nfmark != markinfo->mark) - (*pskb)->nfmark = markinfo->mark; - - return IP6T_CONTINUE; -} - -static int -checkentry(const char *tablename, - const struct ip6t_entry *e, - void *targinfo, - unsigned int targinfosize, - unsigned int hook_mask) -{ - if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_mark_target_info))) { - printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n", - targinfosize, - IP6T_ALIGN(sizeof(struct ip6t_mark_target_info))); - return 0; - } - - if (strcmp(tablename, "mangle") != 0) { - printk(KERN_WARNING "MARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename); - return 0; - } - - return 1; -} - -static struct ip6t_target ip6t_mark_reg = { - .name = "MARK", - .target = target, - .checkentry = checkentry, - .me = THIS_MODULE -}; - -static int __init init(void) -{ - printk(KERN_DEBUG "registering ipv6 mark target\n"); - if (ip6t_register_target(&ip6t_mark_reg)) - return -EINVAL; - - return 0; -} - -static void __exit fini(void) -{ - ip6t_unregister_target(&ip6t_mark_reg); -} - -module_init(init); -module_exit(fini); diff --git a/net/ipv6/netfilter/ip6t_NFQUEUE.c b/net/ipv6/netfilter/ip6t_NFQUEUE.c deleted file mode 100644 index c6e3730e740..00000000000 --- a/net/ipv6/netfilter/ip6t_NFQUEUE.c +++ /dev/null @@ -1,70 +0,0 @@ -/* ip6tables module for using new netfilter netlink queue - * - * (C) 2005 by Harald Welte - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include - -#include -#include -#include - -MODULE_AUTHOR("Harald Welte "); -MODULE_DESCRIPTION("ip6tables NFQUEUE target"); -MODULE_LICENSE("GPL"); - -static unsigned int -target(struct sk_buff **pskb, - const struct net_device *in, - const struct net_device *out, - unsigned int hooknum, - const void *targinfo, - void *userinfo) -{ - const struct ipt_NFQ_info *tinfo = targinfo; - - return NF_QUEUE_NR(tinfo->queuenum); -} - -static int -checkentry(const char *tablename, - const struct ip6t_entry *e, - void *targinfo, - unsigned int targinfosize, - unsigned int hook_mask) -{ - if (targinfosize != IP6T_ALIGN(sizeof(struct ipt_NFQ_info))) { - printk(KERN_WARNING "NFQUEUE: targinfosize %u != %Zu\n", - targinfosize, - IP6T_ALIGN(sizeof(struct ipt_NFQ_info))); - return 0; - } - - return 1; -} - -static struct ip6t_target ipt_NFQ_reg = { - .name = "NFQUEUE", - .target = target, - .checkentry = checkentry, - .me = THIS_MODULE, -}; - -static int __init init(void) -{ - return ip6t_register_target(&ipt_NFQ_reg); -} - -static void __exit fini(void) -{ - ip6t_unregister_target(&ipt_NFQ_reg); -} - -module_init(init); -module_exit(fini); diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index b03e87adca9..c745717b4ce 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c @@ -218,12 +218,13 @@ static unsigned int reject6_target(struct sk_buff **pskb, } static int check(const char *tablename, - const struct ip6t_entry *e, + const void *entry, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { const struct ip6t_reject_info *rejinfo = targinfo; + const struct ip6t_entry *e = entry; if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) { DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize); diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c index f5c1a7ff4a1..219a30365df 100644 --- a/net/ipv6/netfilter/ip6t_ah.c +++ b/net/ipv6/netfilter/ip6t_ah.c @@ -98,7 +98,7 @@ match(const struct sk_buff *skb, /* Called when user tries to insert an entry of this type. */ static int checkentry(const char *tablename, - const struct ip6t_ip6 *ip, + const void *entry, void *matchinfo, unsigned int matchinfosize, unsigned int hook_mask) diff --git a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c index 48cf5f9efc9..80fe82669ce 100644 --- a/net/ipv6/netfilter/ip6t_dst.c +++ b/net/ipv6/netfilter/ip6t_dst.c @@ -178,7 +178,7 @@ match(const struct sk_buff *skb, /* Called when user tries to insert an entry of this type. */ static int checkentry(const char *tablename, - const struct ip6t_ip6 *ip, + const void *info, void *matchinfo, unsigned int matchinfosize, unsigned int hook_mask) diff --git a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c index e1828f6d0a4..724285df871 100644 --- a/net/ipv6/netfilter/ip6t_esp.c +++ b/net/ipv6/netfilter/ip6t_esp.c @@ -76,7 +76,7 @@ match(const struct sk_buff *skb, /* Called when user tries to insert an entry of this type. */ static int checkentry(const char *tablename, - const struct ip6t_ip6 *ip, + const void *ip, void *matchinfo, unsigned int matchinfosize, unsigned int hook_mask) diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c index 616c2cbcd54..ddf5f571909 100644 --- a/net/ipv6/netfilter/ip6t_eui64.c +++ b/net/ipv6/netfilter/ip6t_eui64.c @@ -62,7 +62,7 @@ match(const struct sk_buff *skb, static int ip6t_eui64_checkentry(const char *tablename, - const struct ip6t_ip6 *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c index d1549b26866..a9964b946ed 100644 --- a/net/ipv6/netfilter/ip6t_frag.c +++ b/net/ipv6/netfilter/ip6t_frag.c @@ -115,7 +115,7 @@ match(const struct sk_buff *skb, /* Called when user tries to insert an entry of this type. */ static int checkentry(const char *tablename, - const struct ip6t_ip6 *ip, + const void *ip, void *matchinfo, unsigned int matchinfosize, unsigned int hook_mask) diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c index e3bc8e2700e..ed8ded18bbd 100644 --- a/net/ipv6/netfilter/ip6t_hbh.c +++ b/net/ipv6/netfilter/ip6t_hbh.c @@ -178,7 +178,7 @@ match(const struct sk_buff *skb, /* Called when user tries to insert an entry of this type. */ static int checkentry(const char *tablename, - const struct ip6t_ip6 *ip, + const void *entry, void *matchinfo, unsigned int matchinfosize, unsigned int hook_mask) diff --git a/net/ipv6/netfilter/ip6t_hl.c b/net/ipv6/netfilter/ip6t_hl.c index 0beaff5471d..c5d9079f2d9 100644 --- a/net/ipv6/netfilter/ip6t_hl.c +++ b/net/ipv6/netfilter/ip6t_hl.c @@ -48,7 +48,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in, return 0; } -static int checkentry(const char *tablename, const struct ip6t_ip6 *ip, +static int checkentry(const char *tablename, const void *entry, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { diff --git a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c index 32e67f05845..fda1ceaf5a2 100644 --- a/net/ipv6/netfilter/ip6t_ipv6header.c +++ b/net/ipv6/netfilter/ip6t_ipv6header.c @@ -124,7 +124,7 @@ ipv6header_match(const struct sk_buff *skb, static int ipv6header_checkentry(const char *tablename, - const struct ip6t_ip6 *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) diff --git a/net/ipv6/netfilter/ip6t_length.c b/net/ipv6/netfilter/ip6t_length.c deleted file mode 100644 index e0537d3811d..00000000000 --- a/net/ipv6/netfilter/ip6t_length.c +++ /dev/null @@ -1,66 +0,0 @@ -/* Length Match - IPv6 Port */ - -/* (C) 1999-2001 James Morris - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - - -#include -#include -#include -#include - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("James Morris "); -MODULE_DESCRIPTION("IPv6 packet length match"); - -static int -match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const void *matchinfo, - int offset, - unsigned int protoff, - int *hotdrop) -{ - const struct ip6t_length_info *info = matchinfo; - u_int16_t pktlen = ntohs(skb->nh.ipv6h->payload_len) + sizeof(struct ipv6hdr); - - return (pktlen >= info->min && pktlen <= info->max) ^ info->invert; -} - -static int -checkentry(const char *tablename, - const struct ip6t_ip6 *ip, - void *matchinfo, - unsigned int matchsize, - unsigned int hook_mask) -{ - if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_length_info))) - return 0; - - return 1; -} - -static struct ip6t_match length_match = { - .name = "length", - .match = &match, - .checkentry = &checkentry, - .me = THIS_MODULE, -}; - -static int __init init(void) -{ - return ip6t_register_match(&length_match); -} - -static void __exit fini(void) -{ - ip6t_unregister_match(&length_match); -} - -module_init(init); -module_exit(fini); diff --git a/net/ipv6/netfilter/ip6t_limit.c b/net/ipv6/netfilter/ip6t_limit.c deleted file mode 100644 index fb782f610be..00000000000 --- a/net/ipv6/netfilter/ip6t_limit.c +++ /dev/null @@ -1,147 +0,0 @@ -/* Kernel module to control the rate - * - * 2 September 1999: Changed from the target RATE to the match - * `limit', removed logging. Did I mention that - * Alexey is a fucking genius? - * Rusty Russell (rusty@rustcorp.com.au). */ - -/* (C) 1999 Jérôme de Vivie - * (C) 1999 Hervé Eychenne - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include - -#include -#include - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Herve Eychenne "); -MODULE_DESCRIPTION("rate limiting within ip6tables"); - -/* The algorithm used is the Simple Token Bucket Filter (TBF) - * see net/sched/sch_tbf.c in the linux source tree - */ - -static DEFINE_SPINLOCK(limit_lock); - -/* Rusty: This is my (non-mathematically-inclined) understanding of - this algorithm. The `average rate' in jiffies becomes your initial - amount of credit `credit' and the most credit you can ever have - `credit_cap'. The `peak rate' becomes the cost of passing the - test, `cost'. - - `prev' tracks the last packet hit: you gain one credit per jiffy. - If you get credit balance more than this, the extra credit is - discarded. Every time the match passes, you lose `cost' credits; - if you don't have that many, the test fails. - - See Alexey's formal explanation in net/sched/sch_tbf.c. - - To avoid underflow, we multiply by 128 (ie. you get 128 credits per - jiffy). Hence a cost of 2^32-1, means one pass per 32768 seconds - at 1024HZ (or one every 9 hours). A cost of 1 means 12800 passes - per second at 100HZ. */ - -#define CREDITS_PER_JIFFY 128 - -static int -ip6t_limit_match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const void *matchinfo, - int offset, - unsigned int protoff, - int *hotdrop) -{ - struct ip6t_rateinfo *r = ((struct ip6t_rateinfo *)matchinfo)->master; - unsigned long now = jiffies; - - spin_lock_bh(&limit_lock); - r->credit += (now - xchg(&r->prev, now)) * CREDITS_PER_JIFFY; - if (r->credit > r->credit_cap) - r->credit = r->credit_cap; - - if (r->credit >= r->cost) { - /* We're not limited. */ - r->credit -= r->cost; - spin_unlock_bh(&limit_lock); - return 1; - } - - spin_unlock_bh(&limit_lock); - return 0; -} - -/* Precision saver. */ -static u_int32_t -user2credits(u_int32_t user) -{ - /* If multiplying would overflow... */ - if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY)) - /* Divide first. */ - return (user / IP6T_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY; - - return (user * HZ * CREDITS_PER_JIFFY) / IP6T_LIMIT_SCALE; -} - -static int -ip6t_limit_checkentry(const char *tablename, - const struct ip6t_ip6 *ip, - void *matchinfo, - unsigned int matchsize, - unsigned int hook_mask) -{ - struct ip6t_rateinfo *r = matchinfo; - - if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_rateinfo))) - return 0; - - /* Check for overflow. */ - if (r->burst == 0 - || user2credits(r->avg * r->burst) < user2credits(r->avg)) { - printk("Call rusty: overflow in ip6t_limit: %u/%u\n", - r->avg, r->burst); - return 0; - } - - /* User avg in seconds * IP6T_LIMIT_SCALE: convert to jiffies * - 128. */ - r->prev = jiffies; - r->credit = user2credits(r->avg * r->burst); /* Credits full. */ - r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */ - r->cost = user2credits(r->avg); - - /* For SMP, we only want to use one set of counters. */ - r->master = r; - - return 1; -} - -static struct ip6t_match ip6t_limit_reg = { - .name = "limit", - .match = ip6t_limit_match, - .checkentry = ip6t_limit_checkentry, - .me = THIS_MODULE, -}; - -static int __init init(void) -{ - if (ip6t_register_match(&ip6t_limit_reg)) - return -EINVAL; - return 0; -} - -static void __exit fini(void) -{ - ip6t_unregister_match(&ip6t_limit_reg); -} - -module_init(init); -module_exit(fini); diff --git a/net/ipv6/netfilter/ip6t_mac.c b/net/ipv6/netfilter/ip6t_mac.c deleted file mode 100644 index c848152315b..00000000000 --- a/net/ipv6/netfilter/ip6t_mac.c +++ /dev/null @@ -1,81 +0,0 @@ -/* Kernel module to match MAC address parameters. */ - -/* (C) 1999-2001 Paul `Rusty' Russell - * (C) 2002-2004 Netfilter Core Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include - -#include -#include - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("MAC address matching module for IPv6"); -MODULE_AUTHOR("Netfilter Core Teaam "); - -static int -match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const void *matchinfo, - int offset, - unsigned int protoff, - int *hotdrop) -{ - const struct ip6t_mac_info *info = matchinfo; - - /* Is mac pointer valid? */ - return (skb->mac.raw >= skb->head - && (skb->mac.raw + ETH_HLEN) <= skb->data - /* If so, compare... */ - && ((!compare_ether_addr(eth_hdr(skb)->h_source, info->srcaddr)) - ^ info->invert)); -} - -static int -ip6t_mac_checkentry(const char *tablename, - const struct ip6t_ip6 *ip, - void *matchinfo, - unsigned int matchsize, - unsigned int hook_mask) -{ - if (hook_mask - & ~((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_IN) - | (1 << NF_IP6_FORWARD))) { - printk("ip6t_mac: only valid for PRE_ROUTING, LOCAL_IN or" - " FORWARD\n"); - return 0; - } - - if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_mac_info))) - return 0; - - return 1; -} - -static struct ip6t_match mac_match = { - .name = "mac", - .match = &match, - .checkentry = &ip6t_mac_checkentry, - .me = THIS_MODULE, -}; - -static int __init init(void) -{ - return ip6t_register_match(&mac_match); -} - -static void __exit fini(void) -{ - ip6t_unregister_match(&mac_match); -} - -module_init(init); -module_exit(fini); diff --git a/net/ipv6/netfilter/ip6t_mark.c b/net/ipv6/netfilter/ip6t_mark.c deleted file mode 100644 index affc3de364f..00000000000 --- a/net/ipv6/netfilter/ip6t_mark.c +++ /dev/null @@ -1,66 +0,0 @@ -/* Kernel module to match NFMARK values. */ - -/* (C) 1999-2001 Marc Boucher - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - - -#include -#include - -#include -#include - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Netfilter Core Team "); -MODULE_DESCRIPTION("ip6tables mark match"); - -static int -match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const void *matchinfo, - int offset, - unsigned int protoff, - int *hotdrop) -{ - const struct ip6t_mark_info *info = matchinfo; - - return ((skb->nfmark & info->mask) == info->mark) ^ info->invert; -} - -static int -checkentry(const char *tablename, - const struct ip6t_ip6 *ip, - void *matchinfo, - unsigned int matchsize, - unsigned int hook_mask) -{ - if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_mark_info))) - return 0; - - return 1; -} - -static struct ip6t_match mark_match = { - .name = "mark", - .match = &match, - .checkentry = &checkentry, - .me = THIS_MODULE, -}; - -static int __init init(void) -{ - return ip6t_register_match(&mark_match); -} - -static void __exit fini(void) -{ - ip6t_unregister_match(&mark_match); -} - -module_init(init); -module_exit(fini); diff --git a/net/ipv6/netfilter/ip6t_multiport.c b/net/ipv6/netfilter/ip6t_multiport.c index 6e3246153fa..49f7829dfbc 100644 --- a/net/ipv6/netfilter/ip6t_multiport.c +++ b/net/ipv6/netfilter/ip6t_multiport.c @@ -84,11 +84,12 @@ match(const struct sk_buff *skb, /* Called when user tries to insert an entry of this type. */ static int checkentry(const char *tablename, - const struct ip6t_ip6 *ip, + const void *info, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { + const struct ip6t_ip6 *ip = info; const struct ip6t_multiport *multiinfo = matchinfo; if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_multiport))) diff --git a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c index 4de4cdad4b7..5409b375b51 100644 --- a/net/ipv6/netfilter/ip6t_owner.c +++ b/net/ipv6/netfilter/ip6t_owner.c @@ -53,7 +53,7 @@ match(const struct sk_buff *skb, static int checkentry(const char *tablename, - const struct ip6t_ip6 *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c index c1e770e4554..8465b437585 100644 --- a/net/ipv6/netfilter/ip6t_rt.c +++ b/net/ipv6/netfilter/ip6t_rt.c @@ -183,7 +183,7 @@ match(const struct sk_buff *skb, /* Called when user tries to insert an entry of this type. */ static int checkentry(const char *tablename, - const struct ip6t_ip6 *ip, + const void *entry, void *matchinfo, unsigned int matchinfosize, unsigned int hook_mask) diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index 4c0028671c2..ce4a968e1f7 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c @@ -97,6 +97,7 @@ static struct ip6t_table packet_filter = { .valid_hooks = FILTER_VALID_HOOKS, .lock = RW_LOCK_UNLOCKED, .me = THIS_MODULE, + .af = AF_INET6, }; /* The work comes in here from netfilter.c. */ diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index 85c1e6eada1..30a4627e000 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c @@ -127,6 +127,7 @@ static struct ip6t_table packet_mangler = { .valid_hooks = MANGLE_VALID_HOOKS, .lock = RW_LOCK_UNLOCKED, .me = THIS_MODULE, + .af = AF_INET6, }; /* The work comes in here from netfilter.c. */ diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index c2982efd14a..db28ba3855e 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c @@ -106,11 +106,12 @@ static struct } }; -static struct ip6t_table packet_raw = { +static struct xt_table packet_raw = { .name = "raw", .valid_hooks = RAW_VALID_HOOKS, .lock = RW_LOCK_UNLOCKED, - .me = THIS_MODULE + .me = THIS_MODULE, + .af = AF_INET6, }; /* The work comes in here from netfilter.c. */ diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index e57d6fc9957..92ad53d8f8c 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -584,7 +584,7 @@ MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI "); static int __init init(void) { - need_nf_conntrack(); + need_conntrack(); return init_or_cleanup(1); } @@ -595,9 +595,3 @@ static void __exit fini(void) module_init(init); module_exit(fini); - -void need_ip6_conntrack(void) -{ -} - -EXPORT_SYMBOL(need_ip6_conntrack); diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index f3e5ffbd592..84ef9a13108 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -70,8 +70,8 @@ struct nf_ct_frag6_skb_cb struct nf_ct_frag6_queue { - struct nf_ct_frag6_queue *next; - struct list_head lru_list; /* lru list member */ + struct hlist_node list; + struct list_head lru_list; /* lru list member */ __u32 id; /* fragment id */ struct in6_addr saddr; @@ -90,14 +90,13 @@ struct nf_ct_frag6_queue #define FIRST_IN 2 #define LAST_IN 1 __u16 nhoffset; - struct nf_ct_frag6_queue **pprev; }; /* Hash table. */ #define FRAG6Q_HASHSZ 64 -static struct nf_ct_frag6_queue *nf_ct_frag6_hash[FRAG6Q_HASHSZ]; +static struct hlist_head nf_ct_frag6_hash[FRAG6Q_HASHSZ]; static DEFINE_RWLOCK(nf_ct_frag6_lock); static u32 nf_ct_frag6_hash_rnd; static LIST_HEAD(nf_ct_frag6_lru_list); @@ -105,9 +104,7 @@ int nf_ct_frag6_nqueues = 0; static __inline__ void __fq_unlink(struct nf_ct_frag6_queue *fq) { - if (fq->next) - fq->next->pprev = fq->pprev; - *fq->pprev = fq->next; + hlist_del(&fq->list); list_del(&fq->lru_list); nf_ct_frag6_nqueues--; } @@ -158,28 +155,18 @@ static void nf_ct_frag6_secret_rebuild(unsigned long dummy) get_random_bytes(&nf_ct_frag6_hash_rnd, sizeof(u32)); for (i = 0; i < FRAG6Q_HASHSZ; i++) { struct nf_ct_frag6_queue *q; + struct hlist_node *p, *n; - q = nf_ct_frag6_hash[i]; - while (q) { - struct nf_ct_frag6_queue *next = q->next; + hlist_for_each_entry_safe(q, p, n, &nf_ct_frag6_hash[i], list) { unsigned int hval = ip6qhashfn(q->id, &q->saddr, &q->daddr); - if (hval != i) { - /* Unlink. */ - if (q->next) - q->next->pprev = q->pprev; - *q->pprev = q->next; - + hlist_del(&q->list); /* Relink to new hash chain. */ - if ((q->next = nf_ct_frag6_hash[hval]) != NULL) - q->next->pprev = &q->next; - nf_ct_frag6_hash[hval] = q; - q->pprev = &nf_ct_frag6_hash[hval]; + hlist_add_head(&q->list, + &nf_ct_frag6_hash[hval]); } - - q = next; } } write_unlock(&nf_ct_frag6_lock); @@ -314,15 +301,17 @@ out: /* Creation primitives. */ - static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash, struct nf_ct_frag6_queue *fq_in) { struct nf_ct_frag6_queue *fq; +#ifdef CONFIG_SMP + struct hlist_node *n; +#endif write_lock(&nf_ct_frag6_lock); #ifdef CONFIG_SMP - for (fq = nf_ct_frag6_hash[hash]; fq; fq = fq->next) { + hlist_for_each_entry(fq, n, &nf_ct_frag6_hash[hash], list) { if (fq->id == fq_in->id && !ipv6_addr_cmp(&fq_in->saddr, &fq->saddr) && !ipv6_addr_cmp(&fq_in->daddr, &fq->daddr)) { @@ -340,10 +329,7 @@ static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash, atomic_inc(&fq->refcnt); atomic_inc(&fq->refcnt); - if ((fq->next = nf_ct_frag6_hash[hash]) != NULL) - fq->next->pprev = &fq->next; - nf_ct_frag6_hash[hash] = fq; - fq->pprev = &nf_ct_frag6_hash[hash]; + hlist_add_head(&fq->list, &nf_ct_frag6_hash[hash]); INIT_LIST_HEAD(&fq->lru_list); list_add_tail(&fq->lru_list, &nf_ct_frag6_lru_list); nf_ct_frag6_nqueues++; @@ -384,10 +370,11 @@ static __inline__ struct nf_ct_frag6_queue * fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst) { struct nf_ct_frag6_queue *fq; + struct hlist_node *n; unsigned int hash = ip6qhashfn(id, src, dst); read_lock(&nf_ct_frag6_lock); - for (fq = nf_ct_frag6_hash[hash]; fq; fq = fq->next) { + hlist_for_each_entry(fq, n, &nf_ct_frag6_hash[hash], list) { if (fq->id == id && !ipv6_addr_cmp(src, &fq->saddr) && !ipv6_addr_cmp(dst, &fq->daddr)) { diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 7d55f9cbd85..99c0a0fa4a9 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -103,3 +103,261 @@ config NF_CT_NETLINK This option enables support for a netlink-based userspace interface endmenu + +config NETFILTER_XTABLES + tristate "Netfilter Xtables support (required for ip_tables)" + help + This is required if you intend to use any of ip_tables, + ip6_tables or arp_tables. + +# alphabetically ordered list of targets + +config NETFILTER_XT_TARGET_CLASSIFY + tristate '"CLASSIFY" target support' + depends on NETFILTER_XTABLES + help + This option adds a `CLASSIFY' target, which enables the user to set + the priority of a packet. Some qdiscs can use this value for + classification, among these are: + + atm, cbq, dsmark, pfifo_fast, htb, prio + + To compile it as a module, choose M here. If unsure, say N. + +config NETFILTER_XT_TARGET_CONNMARK + tristate '"CONNMARK" target support' + depends on NETFILTER_XTABLES + depends on IP_NF_MANGLE || IP6_NF_MANGLE + depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4) + help + This option adds a `CONNMARK' target, which allows one to manipulate + the connection mark value. Similar to the MARK target, but + affects the connection mark value rather than the packet mark value. + + If you want to compile it as a module, say M here and read + . The module will be called + ipt_CONNMARK.o. If unsure, say `N'. + +config NETFILTER_XT_TARGET_MARK + tristate '"MARK" target support' + depends on NETFILTER_XTABLES + help + This option adds a `MARK' target, which allows you to create rules + in the `mangle' table which alter the netfilter mark (nfmark) field + associated with the packet prior to routing. This can change + the routing method (see `Use netfilter MARK value as routing + key') and can also be used by other subsystems to change their + behavior. + + To compile it as a module, choose M here. If unsure, say N. + +config NETFILTER_XT_TARGET_NFQUEUE + tristate '"NFQUEUE" target Support' + depends on NETFILTER_XTABLES + help + This Target replaced the old obsolete QUEUE target. + + As opposed to QUEUE, it supports 65535 different queues, + not just one. + + To compile it as a module, choose M here. If unsure, say N. + +config NETFILTER_XT_TARGET_NOTRACK + tristate '"NOTRACK" target support' + depends on NETFILTER_XTABLES + depends on IP_NF_RAW || IP6_NF_RAW + depends on IP_NF_CONNTRACK || NF_CONNTRACK + help + The NOTRACK target allows a select rule to specify + which packets *not* to enter the conntrack/NAT + subsystem with all the consequences (no ICMP error tracking, + no protocol helpers for the selected packets). + + If you want to compile it as a module, say M here and read + . If unsure, say `N'. + +config NETFILTER_XT_MATCH_COMMENT + tristate '"comment" match support' + depends on NETFILTER_XTABLES + help + This option adds a `comment' dummy-match, which allows you to put + comments in your iptables ruleset. + + If you want to compile it as a module, say M here and read + . If unsure, say `N'. + +config NETFILTER_XT_MATCH_CONNBYTES + tristate '"connbytes" per-connection counter match support' + depends on NETFILTER_XTABLES + depends on (IP_NF_CONNTRACK && IP_NF_CT_ACCT) || NF_CT_ACCT + help + This option adds a `connbytes' match, which allows you to match the + number of bytes and/or packets for each direction within a connection. + + If you want to compile it as a module, say M here and read + . If unsure, say `N'. + +config NETFILTER_XT_MATCH_CONNMARK + tristate '"connmark" connection mark match support' + depends on NETFILTER_XTABLES + depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || NF_CONNTRACK_MARK + help + This option adds a `connmark' match, which allows you to match the + connection mark value previously set for the session by `CONNMARK'. + + If you want to compile it as a module, say M here and read + . The module will be called + ipt_connmark.o. If unsure, say `N'. + +config NETFILTER_XT_MATCH_CONNTRACK + tristate '"conntrack" connection tracking match support' + depends on NETFILTER_XTABLES + depends on IP_NF_CONNTRACK || NF_CONNTRACK + help + This is a general conntrack match module, a superset of the state match. + + It allows matching on additional conntrack information, which is + useful in complex configurations, such as NAT gateways with multiple + internet links or tunnels. + + To compile it as a module, choose M here. If unsure, say N. + +config NETFILTER_XT_MATCH_DCCP + tristate '"DCCP" protocol match support' + depends on NETFILTER_XTABLES + help + With this option enabled, you will be able to use the iptables + `dccp' match in order to match on DCCP source/destination ports + and DCCP flags. + + If you want to compile it as a module, say M here and read + . If unsure, say `N'. + +config NETFILTER_XT_MATCH_HELPER + tristate '"helper" match support' + depends on NETFILTER_XTABLES + depends on IP_NF_CONNTRACK || NF_CONNTRACK + help + Helper matching allows you to match packets in dynamic connections + tracked by a conntrack-helper, ie. ip_conntrack_ftp + + To compile it as a module, choose M here. If unsure, say Y. + +config NETFILTER_XT_MATCH_LENGTH + tristate '"length" match support' + depends on NETFILTER_XTABLES + help + This option allows you to match the length of a packet against a + specific value or range of values. + + To compile it as a module, choose M here. If unsure, say N. + +config NETFILTER_XT_MATCH_LIMIT + tristate '"limit" match support' + depends on NETFILTER_XTABLES + help + limit matching allows you to control the rate at which a rule can be + matched: mainly useful in combination with the LOG target ("LOG + target support", below) and to avoid some Denial of Service attacks. + + To compile it as a module, choose M here. If unsure, say N. + +config NETFILTER_XT_MATCH_MAC + tristate '"mac" address match support' + depends on NETFILTER_XTABLES + help + MAC matching allows you to match packets based on the source + Ethernet address of the packet. + + To compile it as a module, choose M here. If unsure, say N. + +config NETFILTER_XT_MATCH_MARK + tristate '"mark" match support' + depends on NETFILTER_XTABLES + help + Netfilter mark matching allows you to match packets based on the + `nfmark' value in the packet. This can be set by the MARK target + (see below). + + To compile it as a module, choose M here. If unsure, say N. + +config NETFILTER_XT_MATCH_PHYSDEV + tristate '"physdev" match support' + depends on NETFILTER_XTABLES && BRIDGE_NETFILTER + help + Physdev packet matching matches against the physical bridge ports + the IP packet arrived on or will leave by. + + To compile it as a module, choose M here. If unsure, say N. + +config NETFILTER_XT_MATCH_PKTTYPE + tristate '"pkttype" packet type match support' + depends on NETFILTER_XTABLES + help + Packet type matching allows you to match a packet by + its "class", eg. BROADCAST, MULTICAST, ... + + Typical usage: + iptables -A INPUT -m pkttype --pkt-type broadcast -j LOG + + To compile it as a module, choose M here. If unsure, say N. + +config NETFILTER_XT_MATCH_REALM + tristate '"realm" match support' + depends on NETFILTER_XTABLES + select NET_CLS_ROUTE + help + This option adds a `realm' match, which allows you to use the realm + key from the routing subsystem inside iptables. + + This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option + in tc world. + + If you want to compile it as a module, say M here and read + . If unsure, say `N'. + +config NETFILTER_XT_MATCH_SCTP + tristate '"sctp" protocol match support' + depends on NETFILTER_XTABLES + help + With this option enabled, you will be able to use the + `sctp' match in order to match on SCTP source/destination ports + and SCTP chunk types. + + If you want to compile it as a module, say M here and read + . If unsure, say `N'. + +config NETFILTER_XT_MATCH_STATE + tristate '"state" match support' + depends on NETFILTER_XTABLES + depends on IP_NF_CONNTRACK || NF_CONNTRACK + help + Connection state matching allows you to match packets based on their + relationship to a tracked connection (ie. previous packets). This + is a powerful tool for packet classification. + + To compile it as a module, choose M here. If unsure, say N. + +config NETFILTER_XT_MATCH_STRING + tristate '"string" match support' + depends on NETFILTER_XTABLES + select TEXTSEARCH + select TEXTSEARCH_KMP + select TEXTSEARCH_BM + select TEXTSEARCH_FSM + help + This option adds a `string' match, which allows you to look for + pattern matchings in packets. + + To compile it as a module, choose M here. If unsure, say N. + +config NETFILTER_XT_MATCH_TCPMSS + tristate '"tcpmss" match support' + depends on NETFILTER_XTABLES + help + This option adds a `tcpmss' match, which allows you to examine the + MSS value of TCP SYN packets, which control the maximum packet size + for that connection. + + To compile it as a module, choose M here. If unsure, say N. + diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index cb2183145c3..746172ebc91 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -1,4 +1,5 @@ netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o +nf_conntrack-objs := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o obj-$(CONFIG_NETFILTER) = netfilter.o @@ -6,13 +7,43 @@ obj-$(CONFIG_NETFILTER_NETLINK) += nfnetlink.o obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o -nf_conntrack-objs := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o - +# connection tracking obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o -obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o # SCTP protocol connection tracking obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o # netlink interface for nf_conntrack obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o + +# connection tracking helpers +obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o + +# generic X tables +obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o + +# targets +obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o +obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o +obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o +obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o +obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o + +# matches +obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o +obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o +obj-$(CONFIG_NETFILTER_XT_MATCH_CONNMARK) += xt_connmark.o +obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o +obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o +obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o +obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o +obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o +obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o +obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o +obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o +obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o +obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o +obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o +obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o +obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o +obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 3531d142f69..617599aeeea 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -821,7 +821,7 @@ module_exit(fini); /* Some modules need us, but don't depend directly on any symbol. They should call this. */ -void need_nf_conntrack(void) +void need_conntrack(void) { } @@ -841,7 +841,7 @@ EXPORT_SYMBOL(nf_conntrack_protocol_unregister); EXPORT_SYMBOL(nf_ct_invert_tuplepr); EXPORT_SYMBOL(nf_conntrack_alter_reply); EXPORT_SYMBOL(nf_conntrack_destroyed); -EXPORT_SYMBOL(need_nf_conntrack); +EXPORT_SYMBOL(need_conntrack); EXPORT_SYMBOL(nf_conntrack_helper_register); EXPORT_SYMBOL(nf_conntrack_helper_unregister); EXPORT_SYMBOL(nf_ct_iterate_cleanup); diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c new file mode 100644 index 00000000000..d7817afc6b9 --- /dev/null +++ b/net/netfilter/x_tables.c @@ -0,0 +1,624 @@ +/* + * x_tables core - Backend for {ip,ip6,arp}_tables + * + * Copyright (C) 2006-2006 Harald Welte + * + * Based on existing ip_tables code which is + * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling + * Copyright (C) 2000-2005 Netfilter Core Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Harald Welte "); +MODULE_DESCRIPTION("[ip,ip6,arp]_tables backend module"); + +#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) + +struct xt_af { + struct semaphore mutex; + struct list_head match; + struct list_head target; + struct list_head tables; +}; + +static struct xt_af *xt; + +#ifdef DEBUG_IP_FIREWALL_USER +#define duprintf(format, args...) printk(format , ## args) +#else +#define duprintf(format, args...) +#endif + +enum { + TABLE, + TARGET, + MATCH, +}; + +/* Registration hooks for targets. */ +int +xt_register_target(int af, struct xt_target *target) +{ + int ret; + + ret = down_interruptible(&xt[af].mutex); + if (ret != 0) + return ret; + list_add(&target->list, &xt[af].target); + up(&xt[af].mutex); + return ret; +} +EXPORT_SYMBOL(xt_register_target); + +void +xt_unregister_target(int af, struct xt_target *target) +{ + down(&xt[af].mutex); + LIST_DELETE(&xt[af].target, target); + up(&xt[af].mutex); +} +EXPORT_SYMBOL(xt_unregister_target); + +int +xt_register_match(int af, struct xt_match *match) +{ + int ret; + + ret = down_interruptible(&xt[af].mutex); + if (ret != 0) + return ret; + + list_add(&match->list, &xt[af].match); + up(&xt[af].mutex); + + return ret; +} +EXPORT_SYMBOL(xt_register_match); + +void +xt_unregister_match(int af, struct xt_match *match) +{ + down(&xt[af].mutex); + LIST_DELETE(&xt[af].match, match); + up(&xt[af].mutex); +} +EXPORT_SYMBOL(xt_unregister_match); + + +/* + * These are weird, but module loading must not be done with mutex + * held (since they will register), and we have to have a single + * function to use try_then_request_module(). + */ + +/* Find match, grabs ref. Returns ERR_PTR() on error. */ +struct xt_match *xt_find_match(int af, const char *name, u8 revision) +{ + struct xt_match *m; + int err = 0; + + if (down_interruptible(&xt[af].mutex) != 0) + return ERR_PTR(-EINTR); + + list_for_each_entry(m, &xt[af].match, list) { + if (strcmp(m->name, name) == 0) { + if (m->revision == revision) { + if (try_module_get(m->me)) { + up(&xt[af].mutex); + return m; + } + } else + err = -EPROTOTYPE; /* Found something. */ + } + } + up(&xt[af].mutex); + return ERR_PTR(err); +} +EXPORT_SYMBOL(xt_find_match); + +/* Find target, grabs ref. Returns ERR_PTR() on error. */ +struct xt_target *xt_find_target(int af, const char *name, u8 revision) +{ + struct xt_target *t; + int err = 0; + + if (down_interruptible(&xt[af].mutex) != 0) + return ERR_PTR(-EINTR); + + list_for_each_entry(t, &xt[af].target, list) { + if (strcmp(t->name, name) == 0) { + if (t->revision == revision) { + if (try_module_get(t->me)) { + up(&xt[af].mutex); + return t; + } + } else + err = -EPROTOTYPE; /* Found something. */ + } + } + up(&xt[af].mutex); + return ERR_PTR(err); +} +EXPORT_SYMBOL(xt_find_target); + +static const char *xt_prefix[NPROTO] = { + [AF_INET] = "ipt_%s", + [AF_INET6] = "ip6t_%s", + [NF_ARP] = "arpt_%s", +}; + +struct xt_target *xt_request_find_target(int af, const char *name, u8 revision) +{ + struct xt_target *target; + + target = try_then_request_module(xt_find_target(af, name, revision), + xt_prefix[af], name); + if (IS_ERR(target) || !target) + return NULL; + return target; +} +EXPORT_SYMBOL_GPL(xt_request_find_target); + +static int match_revfn(int af, const char *name, u8 revision, int *bestp) +{ + struct xt_match *m; + int have_rev = 0; + + list_for_each_entry(m, &xt[af].match, list) { + if (strcmp(m->name, name) == 0) { + if (m->revision > *bestp) + *bestp = m->revision; + if (m->revision == revision) + have_rev = 1; + } + } + return have_rev; +} + +static int target_revfn(int af, const char *name, u8 revision, int *bestp) +{ + struct xt_target *t; + int have_rev = 0; + + list_for_each_entry(t, &xt[af].target, list) { + if (strcmp(t->name, name) == 0) { + if (t->revision > *bestp) + *bestp = t->revision; + if (t->revision == revision) + have_rev = 1; + } + } + return have_rev; +} + +/* Returns true or false (if no such extension at all) */ +int xt_find_revision(int af, const char *name, u8 revision, int target, + int *err) +{ + int have_rev, best = -1; + + if (down_interruptible(&xt[af].mutex) != 0) { + *err = -EINTR; + return 1; + } + if (target == 1) + have_rev = target_revfn(af, name, revision, &best); + else + have_rev = match_revfn(af, name, revision, &best); + up(&xt[af].mutex); + + /* Nothing at all? Return 0 to try loading module. */ + if (best == -1) { + *err = -ENOENT; + return 0; + } + + *err = best; + if (!have_rev) + *err = -EPROTONOSUPPORT; + return 1; +} +EXPORT_SYMBOL_GPL(xt_find_revision); + +struct xt_table_info *xt_alloc_table_info(unsigned int size) +{ + struct xt_table_info *newinfo; + int cpu; + + /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ + if ((SMP_ALIGN(size) >> PAGE_SHIFT) + 2 > num_physpages) + return NULL; + + newinfo = kzalloc(sizeof(struct xt_table_info), GFP_KERNEL); + if (!newinfo) + return NULL; + + newinfo->size = size; + + for_each_cpu(cpu) { + if (size <= PAGE_SIZE) + newinfo->entries[cpu] = kmalloc_node(size, + GFP_KERNEL, + cpu_to_node(cpu)); + else + newinfo->entries[cpu] = vmalloc_node(size, + cpu_to_node(cpu)); + + if (newinfo->entries[cpu] == NULL) { + xt_free_table_info(newinfo); + return NULL; + } + } + + return newinfo; +} +EXPORT_SYMBOL(xt_alloc_table_info); + +void xt_free_table_info(struct xt_table_info *info) +{ + int cpu; + + for_each_cpu(cpu) { + if (info->size <= PAGE_SIZE) + kfree(info->entries[cpu]); + else + vfree(info->entries[cpu]); + } + kfree(info); +} +EXPORT_SYMBOL(xt_free_table_info); + +/* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */ +struct xt_table *xt_find_table_lock(int af, const char *name) +{ + struct xt_table *t; + + if (down_interruptible(&xt[af].mutex) != 0) + return ERR_PTR(-EINTR); + + list_for_each_entry(t, &xt[af].tables, list) + if (strcmp(t->name, name) == 0 && try_module_get(t->me)) + return t; + up(&xt[af].mutex); + return NULL; +} +EXPORT_SYMBOL_GPL(xt_find_table_lock); + +void xt_table_unlock(struct xt_table *table) +{ + up(&xt[table->af].mutex); +} +EXPORT_SYMBOL_GPL(xt_table_unlock); + + +struct xt_table_info * +xt_replace_table(struct xt_table *table, + unsigned int num_counters, + struct xt_table_info *newinfo, + int *error) +{ + struct xt_table_info *oldinfo, *private; + + /* Do the substitution. */ + write_lock_bh(&table->lock); + private = table->private; + /* Check inside lock: is the old number correct? */ + if (num_counters != private->number) { + duprintf("num_counters != table->private->number (%u/%u)\n", + num_counters, private->number); + write_unlock_bh(&table->lock); + *error = -EAGAIN; + return NULL; + } + oldinfo = private; + table->private = newinfo; + newinfo->initial_entries = oldinfo->initial_entries; + write_unlock_bh(&table->lock); + + return oldinfo; +} +EXPORT_SYMBOL_GPL(xt_replace_table); + +int xt_register_table(struct xt_table *table, + struct xt_table_info *bootstrap, + struct xt_table_info *newinfo) +{ + int ret; + struct xt_table_info *private; + + ret = down_interruptible(&xt[table->af].mutex); + if (ret != 0) + return ret; + + /* Don't autoload: we'd eat our tail... */ + if (list_named_find(&xt[table->af].tables, table->name)) { + ret = -EEXIST; + goto unlock; + } + + /* Simplifies replace_table code. */ + table->private = bootstrap; + if (!xt_replace_table(table, 0, newinfo, &ret)) + goto unlock; + + private = table->private; + duprintf("table->private->number = %u\n", private->number); + + /* save number of initial entries */ + private->initial_entries = private->number; + + rwlock_init(&table->lock); + list_prepend(&xt[table->af].tables, table); + + ret = 0; + unlock: + up(&xt[table->af].mutex); + return ret; +} +EXPORT_SYMBOL_GPL(xt_register_table); + +void *xt_unregister_table(struct xt_table *table) +{ + struct xt_table_info *private; + + down(&xt[table->af].mutex); + private = table->private; + LIST_DELETE(&xt[table->af].tables, table); + up(&xt[table->af].mutex); + + return private; +} +EXPORT_SYMBOL_GPL(xt_unregister_table); + +#ifdef CONFIG_PROC_FS +static char *xt_proto_prefix[NPROTO] = { + [AF_INET] = "ip", + [AF_INET6] = "ip6", + [NF_ARP] = "arp", +}; + +static struct list_head *xt_get_idx(struct list_head *list, struct seq_file *seq, loff_t pos) +{ + struct list_head *head = list->next; + + if (!head || list_empty(list)) + return NULL; + + while (pos && (head = head->next)) { + if (head == list) + return NULL; + pos--; + } + return pos ? NULL : head; +} + +static struct list_head *type2list(u_int16_t af, u_int16_t type) +{ + struct list_head *list; + + switch (type) { + case TARGET: + list = &xt[af].target; + break; + case MATCH: + list = &xt[af].match; + break; + case TABLE: + list = &xt[af].tables; + break; + default: + list = NULL; + break; + } + + return list; +} + +static void *xt_tgt_seq_start(struct seq_file *seq, loff_t *pos) +{ + struct proc_dir_entry *pde = (struct proc_dir_entry *) seq->private; + u_int16_t af = (unsigned long)pde->data & 0xffff; + u_int16_t type = (unsigned long)pde->data >> 16; + struct list_head *list; + + if (af >= NPROTO) + return NULL; + + list = type2list(af, type); + if (!list) + return NULL; + + if (down_interruptible(&xt[af].mutex) != 0) + return NULL; + + return xt_get_idx(list, seq, *pos); +} + +static void *xt_tgt_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct proc_dir_entry *pde = seq->private; + u_int16_t af = (unsigned long)pde->data & 0xffff; + u_int16_t type = (unsigned long)pde->data >> 16; + struct list_head *list; + + if (af >= NPROTO) + return NULL; + + list = type2list(af, type); + if (!list) + return NULL; + + (*pos)++; + return xt_get_idx(list, seq, *pos); +} + +static void xt_tgt_seq_stop(struct seq_file *seq, void *v) +{ + struct proc_dir_entry *pde = seq->private; + u_int16_t af = (unsigned long)pde->data & 0xffff; + + up(&xt[af].mutex); +} + +static int xt_name_seq_show(struct seq_file *seq, void *v) +{ + char *name = (char *)v + sizeof(struct list_head); + + if (strlen(name)) + return seq_printf(seq, "%s\n", name); + else + return 0; +} + +static struct seq_operations xt_tgt_seq_ops = { + .start = xt_tgt_seq_start, + .next = xt_tgt_seq_next, + .stop = xt_tgt_seq_stop, + .show = xt_name_seq_show, +}; + +static int xt_tgt_open(struct inode *inode, struct file *file) +{ + int ret; + + ret = seq_open(file, &xt_tgt_seq_ops); + if (!ret) { + struct seq_file *seq = file->private_data; + struct proc_dir_entry *pde = PDE(inode); + + seq->private = pde; + } + + return ret; +} + +static struct file_operations xt_file_ops = { + .owner = THIS_MODULE, + .open = xt_tgt_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +#define FORMAT_TABLES "_tables_names" +#define FORMAT_MATCHES "_tables_matches" +#define FORMAT_TARGETS "_tables_targets" + +#endif /* CONFIG_PROC_FS */ + +int xt_proto_init(int af) +{ +#ifdef CONFIG_PROC_FS + char buf[XT_FUNCTION_MAXNAMELEN]; + struct proc_dir_entry *proc; +#endif + + if (af >= NPROTO) + return -EINVAL; + + +#ifdef CONFIG_PROC_FS + strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); + strlcat(buf, FORMAT_TABLES, sizeof(buf)); + proc = proc_net_fops_create(buf, 0440, &xt_file_ops); + if (!proc) + goto out; + proc->data = (void *) ((unsigned long) af | (TABLE << 16)); + + + strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); + strlcat(buf, FORMAT_MATCHES, sizeof(buf)); + proc = proc_net_fops_create(buf, 0440, &xt_file_ops); + if (!proc) + goto out_remove_tables; + proc->data = (void *) ((unsigned long) af | (MATCH << 16)); + + strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); + strlcat(buf, FORMAT_TARGETS, sizeof(buf)); + proc = proc_net_fops_create(buf, 0440, &xt_file_ops); + if (!proc) + goto out_remove_matches; + proc->data = (void *) ((unsigned long) af | (TARGET << 16)); +#endif + + return 0; + +#ifdef CONFIG_PROC_FS +out_remove_matches: + strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); + strlcat(buf, FORMAT_MATCHES, sizeof(buf)); + proc_net_remove(buf); + +out_remove_tables: + strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); + strlcat(buf, FORMAT_TABLES, sizeof(buf)); + proc_net_remove(buf); +out: + return -1; +#endif +} +EXPORT_SYMBOL_GPL(xt_proto_init); + +void xt_proto_fini(int af) +{ +#ifdef CONFIG_PROC_FS + char buf[XT_FUNCTION_MAXNAMELEN]; + + strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); + strlcat(buf, FORMAT_TABLES, sizeof(buf)); + proc_net_remove(buf); + + strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); + strlcat(buf, FORMAT_TARGETS, sizeof(buf)); + proc_net_remove(buf); + + strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); + strlcat(buf, FORMAT_MATCHES, sizeof(buf)); + proc_net_remove(buf); +#endif /*CONFIG_PROC_FS*/ +} +EXPORT_SYMBOL_GPL(xt_proto_fini); + + +static int __init xt_init(void) +{ + int i; + + xt = kmalloc(sizeof(struct xt_af) * NPROTO, GFP_KERNEL); + if (!xt) + return -ENOMEM; + + for (i = 0; i < NPROTO; i++) { + init_MUTEX(&xt[i].mutex); + INIT_LIST_HEAD(&xt[i].target); + INIT_LIST_HEAD(&xt[i].match); + INIT_LIST_HEAD(&xt[i].tables); + } + return 0; +} + +static void __exit xt_fini(void) +{ + kfree(xt); +} + +module_init(xt_init); +module_exit(xt_fini); + diff --git a/net/ipv4/netfilter/ipt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c similarity index 66% rename from net/ipv4/netfilter/ipt_CLASSIFY.c rename to net/netfilter/xt_CLASSIFY.c index dab78d8bd49..78ee266a12e 100644 --- a/net/ipv4/netfilter/ipt_CLASSIFY.c +++ b/net/netfilter/xt_CLASSIFY.c @@ -15,12 +15,13 @@ #include #include -#include -#include +#include +#include MODULE_AUTHOR("Patrick McHardy "); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("iptables qdisc classification target module"); +MODULE_ALIAS("ipt_CLASSIFY"); static unsigned int target(struct sk_buff **pskb, @@ -30,25 +31,25 @@ target(struct sk_buff **pskb, const void *targinfo, void *userinfo) { - const struct ipt_classify_target_info *clinfo = targinfo; + const struct xt_classify_target_info *clinfo = targinfo; - if((*pskb)->priority != clinfo->priority) + if ((*pskb)->priority != clinfo->priority) (*pskb)->priority = clinfo->priority; - return IPT_CONTINUE; + return XT_CONTINUE; } static int checkentry(const char *tablename, - const struct ipt_entry *e, + const void *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { - if (targinfosize != IPT_ALIGN(sizeof(struct ipt_classify_target_info))){ + if (targinfosize != XT_ALIGN(sizeof(struct xt_classify_target_info))){ printk(KERN_ERR "CLASSIFY: invalid size (%u != %Zu).\n", targinfosize, - IPT_ALIGN(sizeof(struct ipt_classify_target_info))); + XT_ALIGN(sizeof(struct xt_classify_target_info))); return 0; } @@ -69,21 +70,39 @@ checkentry(const char *tablename, return 1; } -static struct ipt_target ipt_classify_reg = { +static struct xt_target classify_reg = { + .name = "CLASSIFY", + .target = target, + .checkentry = checkentry, + .me = THIS_MODULE, +}; +static struct xt_target classify6_reg = { .name = "CLASSIFY", .target = target, .checkentry = checkentry, .me = THIS_MODULE, }; + static int __init init(void) { - return ipt_register_target(&ipt_classify_reg); + int ret; + + ret = xt_register_target(AF_INET, &classify_reg); + if (ret) + return ret; + + ret = xt_register_target(AF_INET6, &classify6_reg); + if (ret) + xt_unregister_target(AF_INET, &classify_reg); + + return ret; } static void __exit fini(void) { - ipt_unregister_target(&ipt_classify_reg); + xt_unregister_target(AF_INET, &classify_reg); + xt_unregister_target(AF_INET6, &classify6_reg); } module_init(init); diff --git a/net/ipv4/netfilter/ipt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c similarity index 73% rename from net/ipv4/netfilter/ipt_CONNMARK.c rename to net/netfilter/xt_CONNMARK.c index 8acac5a40a9..22506e376be 100644 --- a/net/ipv4/netfilter/ipt_CONNMARK.c +++ b/net/netfilter/xt_CONNMARK.c @@ -26,9 +26,10 @@ MODULE_AUTHOR("Henrik Nordstrom "); MODULE_DESCRIPTION("IP tables CONNMARK matching module"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("ipt_CONNMARK"); -#include -#include +#include +#include #include static unsigned int @@ -39,7 +40,7 @@ target(struct sk_buff **pskb, const void *targinfo, void *userinfo) { - const struct ipt_connmark_target_info *markinfo = targinfo; + const struct xt_connmark_target_info *markinfo = targinfo; u_int32_t diff; u_int32_t nfmark; u_int32_t newmark; @@ -48,17 +49,17 @@ target(struct sk_buff **pskb, if (ctmark) { switch(markinfo->mode) { - case IPT_CONNMARK_SET: + case XT_CONNMARK_SET: newmark = (*ctmark & ~markinfo->mask) | markinfo->mark; if (newmark != *ctmark) *ctmark = newmark; break; - case IPT_CONNMARK_SAVE: + case XT_CONNMARK_SAVE: newmark = (*ctmark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask); if (*ctmark != newmark) *ctmark = newmark; break; - case IPT_CONNMARK_RESTORE: + case XT_CONNMARK_RESTORE: nfmark = (*pskb)->nfmark; diff = (*ctmark ^ nfmark) & markinfo->mask; if (diff != 0) @@ -67,25 +68,25 @@ target(struct sk_buff **pskb, } } - return IPT_CONTINUE; + return XT_CONTINUE; } static int checkentry(const char *tablename, - const struct ipt_entry *e, + const void *entry, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { - struct ipt_connmark_target_info *matchinfo = targinfo; - if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) { + struct xt_connmark_target_info *matchinfo = targinfo; + if (targinfosize != XT_ALIGN(sizeof(struct xt_connmark_target_info))) { printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n", targinfosize, - IPT_ALIGN(sizeof(struct ipt_connmark_target_info))); + XT_ALIGN(sizeof(struct xt_connmark_target_info))); return 0; } - if (matchinfo->mode == IPT_CONNMARK_RESTORE) { + if (matchinfo->mode == XT_CONNMARK_RESTORE) { if (strcmp(tablename, "mangle") != 0) { printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename); return 0; @@ -100,7 +101,13 @@ checkentry(const char *tablename, return 1; } -static struct ipt_target ipt_connmark_reg = { +static struct xt_target connmark_reg = { + .name = "CONNMARK", + .target = &target, + .checkentry = &checkentry, + .me = THIS_MODULE +}; +static struct xt_target connmark6_reg = { .name = "CONNMARK", .target = &target, .checkentry = &checkentry, @@ -109,13 +116,25 @@ static struct ipt_target ipt_connmark_reg = { static int __init init(void) { - need_ip_conntrack(); - return ipt_register_target(&ipt_connmark_reg); + int ret; + + need_conntrack(); + + ret = xt_register_target(AF_INET, &connmark_reg); + if (ret) + return ret; + + ret = xt_register_target(AF_INET6, &connmark6_reg); + if (ret) + xt_unregister_target(AF_INET, &connmark_reg); + + return ret; } static void __exit fini(void) { - ipt_unregister_target(&ipt_connmark_reg); + xt_unregister_target(AF_INET, &connmark_reg); + xt_unregister_target(AF_INET6, &connmark6_reg); } module_init(init); diff --git a/net/ipv4/netfilter/ipt_MARK.c b/net/netfilter/xt_MARK.c similarity index 61% rename from net/ipv4/netfilter/ipt_MARK.c rename to net/netfilter/xt_MARK.c index 52b4f2c296b..0c11ee9550f 100644 --- a/net/ipv4/netfilter/ipt_MARK.c +++ b/net/netfilter/xt_MARK.c @@ -12,12 +12,14 @@ #include #include -#include -#include +#include +#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Marc Boucher "); -MODULE_DESCRIPTION("iptables MARK modification module"); +MODULE_DESCRIPTION("ip[6]tables MARK modification module"); +MODULE_ALIAS("ipt_MARK"); +MODULE_ALIAS("ip6t_MARK"); static unsigned int target_v0(struct sk_buff **pskb, @@ -27,12 +29,12 @@ target_v0(struct sk_buff **pskb, const void *targinfo, void *userinfo) { - const struct ipt_mark_target_info *markinfo = targinfo; + const struct xt_mark_target_info *markinfo = targinfo; if((*pskb)->nfmark != markinfo->mark) (*pskb)->nfmark = markinfo->mark; - return IPT_CONTINUE; + return XT_CONTINUE; } static unsigned int @@ -43,19 +45,19 @@ target_v1(struct sk_buff **pskb, const void *targinfo, void *userinfo) { - const struct ipt_mark_target_info_v1 *markinfo = targinfo; + const struct xt_mark_target_info_v1 *markinfo = targinfo; int mark = 0; switch (markinfo->mode) { - case IPT_MARK_SET: + case XT_MARK_SET: mark = markinfo->mark; break; - case IPT_MARK_AND: + case XT_MARK_AND: mark = (*pskb)->nfmark & markinfo->mark; break; - case IPT_MARK_OR: + case XT_MARK_OR: mark = (*pskb)->nfmark | markinfo->mark; break; } @@ -63,23 +65,23 @@ target_v1(struct sk_buff **pskb, if((*pskb)->nfmark != mark) (*pskb)->nfmark = mark; - return IPT_CONTINUE; + return XT_CONTINUE; } static int checkentry_v0(const char *tablename, - const struct ipt_entry *e, + const void *entry, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { - struct ipt_mark_target_info *markinfo = targinfo; + struct xt_mark_target_info *markinfo = targinfo; - if (targinfosize != IPT_ALIGN(sizeof(struct ipt_mark_target_info))) { + if (targinfosize != XT_ALIGN(sizeof(struct xt_mark_target_info))) { printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n", targinfosize, - IPT_ALIGN(sizeof(struct ipt_mark_target_info))); + XT_ALIGN(sizeof(struct xt_mark_target_info))); return 0; } @@ -98,17 +100,17 @@ checkentry_v0(const char *tablename, static int checkentry_v1(const char *tablename, - const struct ipt_entry *e, + const void *entry, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { - struct ipt_mark_target_info_v1 *markinfo = targinfo; + struct xt_mark_target_info_v1 *markinfo = targinfo; - if (targinfosize != IPT_ALIGN(sizeof(struct ipt_mark_target_info_v1))){ + if (targinfosize != XT_ALIGN(sizeof(struct xt_mark_target_info_v1))){ printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n", targinfosize, - IPT_ALIGN(sizeof(struct ipt_mark_target_info_v1))); + XT_ALIGN(sizeof(struct xt_mark_target_info_v1))); return 0; } @@ -117,9 +119,9 @@ checkentry_v1(const char *tablename, return 0; } - if (markinfo->mode != IPT_MARK_SET - && markinfo->mode != IPT_MARK_AND - && markinfo->mode != IPT_MARK_OR) { + if (markinfo->mode != XT_MARK_SET + && markinfo->mode != XT_MARK_AND + && markinfo->mode != XT_MARK_OR) { printk(KERN_WARNING "MARK: unknown mode %u\n", markinfo->mode); return 0; @@ -133,7 +135,7 @@ checkentry_v1(const char *tablename, return 1; } -static struct ipt_target ipt_mark_reg_v0 = { +static struct xt_target ipt_mark_reg_v0 = { .name = "MARK", .target = target_v0, .checkentry = checkentry_v0, @@ -141,7 +143,7 @@ static struct ipt_target ipt_mark_reg_v0 = { .revision = 0, }; -static struct ipt_target ipt_mark_reg_v1 = { +static struct xt_target ipt_mark_reg_v1 = { .name = "MARK", .target = target_v1, .checkentry = checkentry_v1, @@ -149,23 +151,40 @@ static struct ipt_target ipt_mark_reg_v1 = { .revision = 1, }; +static struct xt_target ip6t_mark_reg_v0 = { + .name = "MARK", + .target = target_v0, + .checkentry = checkentry_v0, + .me = THIS_MODULE, + .revision = 0, +}; + static int __init init(void) { int err; - err = ipt_register_target(&ipt_mark_reg_v0); - if (!err) { - err = ipt_register_target(&ipt_mark_reg_v1); - if (err) - ipt_unregister_target(&ipt_mark_reg_v0); + err = xt_register_target(AF_INET, &ipt_mark_reg_v0); + if (err) + return err; + + err = xt_register_target(AF_INET, &ipt_mark_reg_v1); + if (err) + xt_unregister_target(AF_INET, &ipt_mark_reg_v0); + + err = xt_register_target(AF_INET6, &ip6t_mark_reg_v0); + if (err) { + xt_unregister_target(AF_INET, &ipt_mark_reg_v0); + xt_unregister_target(AF_INET, &ipt_mark_reg_v1); } + return err; } static void __exit fini(void) { - ipt_unregister_target(&ipt_mark_reg_v0); - ipt_unregister_target(&ipt_mark_reg_v1); + xt_unregister_target(AF_INET, &ipt_mark_reg_v0); + xt_unregister_target(AF_INET, &ipt_mark_reg_v1); + xt_unregister_target(AF_INET6, &ip6t_mark_reg_v0); } module_init(init); diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c new file mode 100644 index 00000000000..8b76b6f8d1e --- /dev/null +++ b/net/netfilter/xt_NFQUEUE.c @@ -0,0 +1,107 @@ +/* iptables module for using new netfilter netlink queue + * + * (C) 2005 by Harald Welte + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include + +#include +#include +#include +#include + +MODULE_AUTHOR("Harald Welte "); +MODULE_DESCRIPTION("[ip,ip6,arp]_tables NFQUEUE target"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("ipt_NFQUEUE"); +MODULE_ALIAS("ip6t_NFQUEUE"); +MODULE_ALIAS("arpt_NFQUEUE"); + +static unsigned int +target(struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + unsigned int hooknum, + const void *targinfo, + void *userinfo) +{ + const struct xt_NFQ_info *tinfo = targinfo; + + return NF_QUEUE_NR(tinfo->queuenum); +} + +static int +checkentry(const char *tablename, + const void *entry, + void *targinfo, + unsigned int targinfosize, + unsigned int hook_mask) +{ + if (targinfosize != XT_ALIGN(sizeof(struct xt_NFQ_info))) { + printk(KERN_WARNING "NFQUEUE: targinfosize %u != %Zu\n", + targinfosize, + XT_ALIGN(sizeof(struct xt_NFQ_info))); + return 0; + } + + return 1; +} + +static struct xt_target ipt_NFQ_reg = { + .name = "NFQUEUE", + .target = target, + .checkentry = checkentry, + .me = THIS_MODULE, +}; + +static struct xt_target ip6t_NFQ_reg = { + .name = "NFQUEUE", + .target = target, + .checkentry = checkentry, + .me = THIS_MODULE, +}; + +static struct xt_target arpt_NFQ_reg = { + .name = "NFQUEUE", + .target = target, + .checkentry = checkentry, + .me = THIS_MODULE, +}; + +static int __init init(void) +{ + int ret; + ret = xt_register_target(AF_INET, &ipt_NFQ_reg); + if (ret) + return ret; + ret = xt_register_target(AF_INET6, &ip6t_NFQ_reg); + if (ret) + goto out_ip; + ret = xt_register_target(NF_ARP, &arpt_NFQ_reg); + if (ret) + goto out_ip6; + + return ret; +out_ip6: + xt_unregister_target(AF_INET6, &ip6t_NFQ_reg); +out_ip: + xt_unregister_target(AF_INET, &ipt_NFQ_reg); + + return ret; +} + +static void __exit fini(void) +{ + xt_unregister_target(NF_ARP, &arpt_NFQ_reg); + xt_unregister_target(AF_INET6, &ip6t_NFQ_reg); + xt_unregister_target(AF_INET, &ipt_NFQ_reg); +} + +module_init(init); +module_exit(fini); diff --git a/net/ipv4/netfilter/ipt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c similarity index 69% rename from net/ipv4/netfilter/ipt_NOTRACK.c rename to net/netfilter/xt_NOTRACK.c index e3c69d072c6..24d477afa93 100644 --- a/net/ipv4/netfilter/ipt_NOTRACK.c +++ b/net/netfilter/xt_NOTRACK.c @@ -4,9 +4,12 @@ #include #include -#include +#include #include +MODULE_LICENSE("GPL"); +MODULE_ALIAS("ipt_NOTRACK"); + static unsigned int target(struct sk_buff **pskb, const struct net_device *in, @@ -17,7 +20,7 @@ target(struct sk_buff **pskb, { /* Previously seen (loopback)? Ignore. */ if ((*pskb)->nfct != NULL) - return IPT_CONTINUE; + return XT_CONTINUE; /* Attach fake conntrack entry. If there is a real ct entry correspondig to this packet, @@ -27,12 +30,12 @@ target(struct sk_buff **pskb, (*pskb)->nfctinfo = IP_CT_NEW; nf_conntrack_get((*pskb)->nfct); - return IPT_CONTINUE; + return XT_CONTINUE; } static int checkentry(const char *tablename, - const struct ipt_entry *e, + const void *entry, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) @@ -51,26 +54,39 @@ checkentry(const char *tablename, return 1; } -static struct ipt_target ipt_notrack_reg = { +static struct xt_target notrack_reg = { .name = "NOTRACK", .target = target, .checkentry = checkentry, - .me = THIS_MODULE + .me = THIS_MODULE, +}; +static struct xt_target notrack6_reg = { + .name = "NOTRACK", + .target = target, + .checkentry = checkentry, + .me = THIS_MODULE, }; static int __init init(void) { - if (ipt_register_target(&ipt_notrack_reg)) - return -EINVAL; + int ret; + + ret = xt_register_target(AF_INET, ¬rack_reg); + if (ret) + return ret; - return 0; + ret = xt_register_target(AF_INET6, ¬rack6_reg); + if (ret) + xt_unregister_target(AF_INET, ¬rack_reg); + + return ret; } static void __exit fini(void) { - ipt_unregister_target(&ipt_notrack_reg); + xt_unregister_target(AF_INET6, ¬rack6_reg); + xt_unregister_target(AF_INET, ¬rack_reg); } module_init(init); module_exit(fini); -MODULE_LICENSE("GPL"); diff --git a/net/ipv4/netfilter/ipt_comment.c b/net/netfilter/xt_comment.c similarity index 55% rename from net/ipv4/netfilter/ipt_comment.c rename to net/netfilter/xt_comment.c index 6b76a1ea524..4ba6fd65c6e 100644 --- a/net/ipv4/netfilter/ipt_comment.c +++ b/net/netfilter/xt_comment.c @@ -6,12 +6,14 @@ #include #include -#include -#include +#include +#include MODULE_AUTHOR("Brad Fisher "); MODULE_DESCRIPTION("iptables comment match module"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("ipt_comment"); +MODULE_ALIAS("ip6t_comment"); static int match(const struct sk_buff *skb, @@ -19,6 +21,7 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protooff, int *hotdrop) { /* We always match */ @@ -27,18 +30,25 @@ match(const struct sk_buff *skb, static int checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { /* Check the size */ - if (matchsize != IPT_ALIGN(sizeof(struct ipt_comment_info))) + if (matchsize != XT_ALIGN(sizeof(struct xt_comment_info))) return 0; return 1; } -static struct ipt_match comment_match = { +static struct xt_match comment_match = { + .name = "comment", + .match = match, + .checkentry = checkentry, + .me = THIS_MODULE +}; + +static struct xt_match comment6_match = { .name = "comment", .match = match, .checkentry = checkentry, @@ -47,12 +57,23 @@ static struct ipt_match comment_match = { static int __init init(void) { - return ipt_register_match(&comment_match); + int ret; + + ret = xt_register_match(AF_INET, &comment_match); + if (ret) + return ret; + + ret = xt_register_match(AF_INET6, &comment6_match); + if (ret) + xt_unregister_match(AF_INET, &comment_match); + + return ret; } static void __exit fini(void) { - ipt_unregister_match(&comment_match); + xt_unregister_match(AF_INET, &comment_match); + xt_unregister_match(AF_INET6, &comment6_match); } module_init(init); diff --git a/net/ipv4/netfilter/ipt_connbytes.c b/net/netfilter/xt_connbytes.c similarity index 66% rename from net/ipv4/netfilter/ipt_connbytes.c rename to net/netfilter/xt_connbytes.c index d68a048b717..150d2a4b0f7 100644 --- a/net/ipv4/netfilter/ipt_connbytes.c +++ b/net/netfilter/xt_connbytes.c @@ -6,13 +6,15 @@ * - add functionality to match number of packets * - add functionality to match average packet size * - add support to match directions seperately + * 2005-10-16 Harald Welte + * - Port to x_tables * */ #include #include #include -#include -#include +#include +#include #include #include @@ -20,6 +22,7 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Harald Welte "); MODULE_DESCRIPTION("iptables match for matching number of pkts/bytes per connection"); +MODULE_ALIAS("ipt_connbytes"); /* 64bit divisor, dividend and result. dynamic precision */ static u_int64_t div64_64(u_int64_t dividend, u_int64_t divisor) @@ -43,9 +46,10 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - const struct ipt_connbytes_info *sinfo = matchinfo; + const struct xt_connbytes_info *sinfo = matchinfo; u_int64_t what = 0; /* initialize to make gcc happy */ const struct ip_conntrack_counter *counters; @@ -53,45 +57,45 @@ match(const struct sk_buff *skb, return 0; /* no match */ switch (sinfo->what) { - case IPT_CONNBYTES_PKTS: + case XT_CONNBYTES_PKTS: switch (sinfo->direction) { - case IPT_CONNBYTES_DIR_ORIGINAL: + case XT_CONNBYTES_DIR_ORIGINAL: what = counters[IP_CT_DIR_ORIGINAL].packets; break; - case IPT_CONNBYTES_DIR_REPLY: + case XT_CONNBYTES_DIR_REPLY: what = counters[IP_CT_DIR_REPLY].packets; break; - case IPT_CONNBYTES_DIR_BOTH: + case XT_CONNBYTES_DIR_BOTH: what = counters[IP_CT_DIR_ORIGINAL].packets; what += counters[IP_CT_DIR_REPLY].packets; break; } break; - case IPT_CONNBYTES_BYTES: + case XT_CONNBYTES_BYTES: switch (sinfo->direction) { - case IPT_CONNBYTES_DIR_ORIGINAL: + case XT_CONNBYTES_DIR_ORIGINAL: what = counters[IP_CT_DIR_ORIGINAL].bytes; break; - case IPT_CONNBYTES_DIR_REPLY: + case XT_CONNBYTES_DIR_REPLY: what = counters[IP_CT_DIR_REPLY].bytes; break; - case IPT_CONNBYTES_DIR_BOTH: + case XT_CONNBYTES_DIR_BOTH: what = counters[IP_CT_DIR_ORIGINAL].bytes; what += counters[IP_CT_DIR_REPLY].bytes; break; } break; - case IPT_CONNBYTES_AVGPKT: + case XT_CONNBYTES_AVGPKT: switch (sinfo->direction) { - case IPT_CONNBYTES_DIR_ORIGINAL: + case XT_CONNBYTES_DIR_ORIGINAL: what = div64_64(counters[IP_CT_DIR_ORIGINAL].bytes, counters[IP_CT_DIR_ORIGINAL].packets); break; - case IPT_CONNBYTES_DIR_REPLY: + case XT_CONNBYTES_DIR_REPLY: what = div64_64(counters[IP_CT_DIR_REPLY].bytes, counters[IP_CT_DIR_REPLY].packets); break; - case IPT_CONNBYTES_DIR_BOTH: + case XT_CONNBYTES_DIR_BOTH: { u_int64_t bytes; u_int64_t pkts; @@ -117,30 +121,36 @@ match(const struct sk_buff *skb, } static int check(const char *tablename, - const struct ipt_ip *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { - const struct ipt_connbytes_info *sinfo = matchinfo; + const struct xt_connbytes_info *sinfo = matchinfo; - if (matchsize != IPT_ALIGN(sizeof(struct ipt_connbytes_info))) + if (matchsize != XT_ALIGN(sizeof(struct xt_connbytes_info))) return 0; - if (sinfo->what != IPT_CONNBYTES_PKTS && - sinfo->what != IPT_CONNBYTES_BYTES && - sinfo->what != IPT_CONNBYTES_AVGPKT) + if (sinfo->what != XT_CONNBYTES_PKTS && + sinfo->what != XT_CONNBYTES_BYTES && + sinfo->what != XT_CONNBYTES_AVGPKT) return 0; - if (sinfo->direction != IPT_CONNBYTES_DIR_ORIGINAL && - sinfo->direction != IPT_CONNBYTES_DIR_REPLY && - sinfo->direction != IPT_CONNBYTES_DIR_BOTH) + if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL && + sinfo->direction != XT_CONNBYTES_DIR_REPLY && + sinfo->direction != XT_CONNBYTES_DIR_BOTH) return 0; return 1; } -static struct ipt_match state_match = { +static struct xt_match connbytes_match = { + .name = "connbytes", + .match = &match, + .checkentry = &check, + .me = THIS_MODULE +}; +static struct xt_match connbytes6_match = { .name = "connbytes", .match = &match, .checkentry = &check, @@ -149,12 +159,21 @@ static struct ipt_match state_match = { static int __init init(void) { - return ipt_register_match(&state_match); + int ret; + ret = xt_register_match(AF_INET, &connbytes_match); + if (ret) + return ret; + + ret = xt_register_match(AF_INET6, &connbytes6_match); + if (ret) + xt_unregister_match(AF_INET, &connbytes_match); + return ret; } static void __exit fini(void) { - ipt_unregister_match(&state_match); + xt_unregister_match(AF_INET, &connbytes_match); + xt_unregister_match(AF_INET6, &connbytes6_match); } module_init(init); diff --git a/net/ipv4/netfilter/ipt_connmark.c b/net/netfilter/xt_connmark.c similarity index 70% rename from net/ipv4/netfilter/ipt_connmark.c rename to net/netfilter/xt_connmark.c index 5306ef293b9..d06e925032d 100644 --- a/net/ipv4/netfilter/ipt_connmark.c +++ b/net/netfilter/xt_connmark.c @@ -25,9 +25,10 @@ MODULE_AUTHOR("Henrik Nordstrom "); MODULE_DESCRIPTION("IP tables connmark match module"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("ipt_connmark"); -#include -#include +#include +#include #include static int @@ -36,9 +37,10 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - const struct ipt_connmark_info *info = matchinfo; + const struct xt_connmark_info *info = matchinfo; u_int32_t ctinfo; const u_int32_t *ctmark = nf_ct_get_mark(skb, &ctinfo); if (!ctmark) @@ -49,14 +51,14 @@ match(const struct sk_buff *skb, static int checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { - struct ipt_connmark_info *cm = - (struct ipt_connmark_info *)matchinfo; - if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info))) + struct xt_connmark_info *cm = + (struct xt_connmark_info *)matchinfo; + if (matchsize != XT_ALIGN(sizeof(struct xt_connmark_info))) return 0; if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) { @@ -67,21 +69,40 @@ checkentry(const char *tablename, return 1; } -static struct ipt_match connmark_match = { +static struct xt_match connmark_match = { + .name = "connmark", + .match = &match, + .checkentry = &checkentry, + .me = THIS_MODULE +}; +static struct xt_match connmark6_match = { .name = "connmark", .match = &match, .checkentry = &checkentry, .me = THIS_MODULE }; + static int __init init(void) { - return ipt_register_match(&connmark_match); + int ret; + + need_conntrack(); + + ret = xt_register_match(AF_INET, &connmark_match); + if (ret) + return ret; + + ret = xt_register_match(AF_INET6, &connmark6_match); + if (ret) + xt_unregister_match(AF_INET, &connmark_match); + return ret; } static void __exit fini(void) { - ipt_unregister_match(&connmark_match); + xt_unregister_match(AF_INET6, &connmark6_match); + xt_unregister_match(AF_INET, &connmark_match); } module_init(init); diff --git a/net/ipv4/netfilter/ipt_conntrack.c b/net/netfilter/xt_conntrack.c similarity index 63% rename from net/ipv4/netfilter/ipt_conntrack.c rename to net/netfilter/xt_conntrack.c index c8d18705469..ffdebc95eb9 100644 --- a/net/ipv4/netfilter/ipt_conntrack.c +++ b/net/netfilter/xt_conntrack.c @@ -18,12 +18,13 @@ #include #endif -#include -#include +#include +#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Marc Boucher "); MODULE_DESCRIPTION("iptables connection tracking match module"); +MODULE_ALIAS("ipt_conntrack"); #if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) @@ -33,9 +34,10 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - const struct ipt_conntrack_info *sinfo = matchinfo; + const struct xt_conntrack_info *sinfo = matchinfo; struct ip_conntrack *ct; enum ip_conntrack_info ctinfo; unsigned int statebit; @@ -45,58 +47,58 @@ match(const struct sk_buff *skb, #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg)) if (ct == &ip_conntrack_untracked) - statebit = IPT_CONNTRACK_STATE_UNTRACKED; + statebit = XT_CONNTRACK_STATE_UNTRACKED; else if (ct) - statebit = IPT_CONNTRACK_STATE_BIT(ctinfo); + statebit = XT_CONNTRACK_STATE_BIT(ctinfo); else - statebit = IPT_CONNTRACK_STATE_INVALID; + statebit = XT_CONNTRACK_STATE_INVALID; - if(sinfo->flags & IPT_CONNTRACK_STATE) { + if(sinfo->flags & XT_CONNTRACK_STATE) { if (ct) { if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip != ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip) - statebit |= IPT_CONNTRACK_STATE_SNAT; + statebit |= XT_CONNTRACK_STATE_SNAT; if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip != ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip) - statebit |= IPT_CONNTRACK_STATE_DNAT; + statebit |= XT_CONNTRACK_STATE_DNAT; } - if (FWINV((statebit & sinfo->statemask) == 0, IPT_CONNTRACK_STATE)) + if (FWINV((statebit & sinfo->statemask) == 0, XT_CONNTRACK_STATE)) return 0; } - if(sinfo->flags & IPT_CONNTRACK_PROTO) { - if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, IPT_CONNTRACK_PROTO)) + if(sinfo->flags & XT_CONNTRACK_PROTO) { + if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, XT_CONNTRACK_PROTO)) return 0; } - if(sinfo->flags & IPT_CONNTRACK_ORIGSRC) { - if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, IPT_CONNTRACK_ORIGSRC)) + if(sinfo->flags & XT_CONNTRACK_ORIGSRC) { + if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, XT_CONNTRACK_ORIGSRC)) return 0; } - if(sinfo->flags & IPT_CONNTRACK_ORIGDST) { - if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, IPT_CONNTRACK_ORIGDST)) + if(sinfo->flags & XT_CONNTRACK_ORIGDST) { + if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, XT_CONNTRACK_ORIGDST)) return 0; } - if(sinfo->flags & IPT_CONNTRACK_REPLSRC) { - if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, IPT_CONNTRACK_REPLSRC)) + if(sinfo->flags & XT_CONNTRACK_REPLSRC) { + if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, XT_CONNTRACK_REPLSRC)) return 0; } - if(sinfo->flags & IPT_CONNTRACK_REPLDST) { - if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, IPT_CONNTRACK_REPLDST)) + if(sinfo->flags & XT_CONNTRACK_REPLDST) { + if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, XT_CONNTRACK_REPLDST)) return 0; } - if(sinfo->flags & IPT_CONNTRACK_STATUS) { - if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, IPT_CONNTRACK_STATUS)) + if(sinfo->flags & XT_CONNTRACK_STATUS) { + if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, XT_CONNTRACK_STATUS)) return 0; } - if(sinfo->flags & IPT_CONNTRACK_EXPIRES) { + if(sinfo->flags & XT_CONNTRACK_EXPIRES) { unsigned long expires; if(!ct) @@ -104,7 +106,7 @@ match(const struct sk_buff *skb, expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0; - if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), IPT_CONNTRACK_EXPIRES)) + if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), XT_CONNTRACK_EXPIRES)) return 0; } @@ -118,9 +120,10 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - const struct ipt_conntrack_info *sinfo = matchinfo; + const struct xt_conntrack_info *sinfo = matchinfo; struct nf_conn *ct; enum ip_conntrack_info ctinfo; unsigned int statebit; @@ -130,58 +133,58 @@ match(const struct sk_buff *skb, #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg)) if (ct == &nf_conntrack_untracked) - statebit = IPT_CONNTRACK_STATE_UNTRACKED; + statebit = XT_CONNTRACK_STATE_UNTRACKED; else if (ct) - statebit = IPT_CONNTRACK_STATE_BIT(ctinfo); + statebit = XT_CONNTRACK_STATE_BIT(ctinfo); else - statebit = IPT_CONNTRACK_STATE_INVALID; + statebit = XT_CONNTRACK_STATE_INVALID; - if(sinfo->flags & IPT_CONNTRACK_STATE) { + if(sinfo->flags & XT_CONNTRACK_STATE) { if (ct) { if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip != ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip) - statebit |= IPT_CONNTRACK_STATE_SNAT; + statebit |= XT_CONNTRACK_STATE_SNAT; if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip != ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip) - statebit |= IPT_CONNTRACK_STATE_DNAT; + statebit |= XT_CONNTRACK_STATE_DNAT; } - if (FWINV((statebit & sinfo->statemask) == 0, IPT_CONNTRACK_STATE)) + if (FWINV((statebit & sinfo->statemask) == 0, XT_CONNTRACK_STATE)) return 0; } - if(sinfo->flags & IPT_CONNTRACK_PROTO) { - if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, IPT_CONNTRACK_PROTO)) + if(sinfo->flags & XT_CONNTRACK_PROTO) { + if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, XT_CONNTRACK_PROTO)) return 0; } - if(sinfo->flags & IPT_CONNTRACK_ORIGSRC) { - if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, IPT_CONNTRACK_ORIGSRC)) + if(sinfo->flags & XT_CONNTRACK_ORIGSRC) { + if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, XT_CONNTRACK_ORIGSRC)) return 0; } - if(sinfo->flags & IPT_CONNTRACK_ORIGDST) { - if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, IPT_CONNTRACK_ORIGDST)) + if(sinfo->flags & XT_CONNTRACK_ORIGDST) { + if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, XT_CONNTRACK_ORIGDST)) return 0; } - if(sinfo->flags & IPT_CONNTRACK_REPLSRC) { - if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, IPT_CONNTRACK_REPLSRC)) + if(sinfo->flags & XT_CONNTRACK_REPLSRC) { + if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, XT_CONNTRACK_REPLSRC)) return 0; } - if(sinfo->flags & IPT_CONNTRACK_REPLDST) { - if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, IPT_CONNTRACK_REPLDST)) + if(sinfo->flags & XT_CONNTRACK_REPLDST) { + if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, XT_CONNTRACK_REPLDST)) return 0; } - if(sinfo->flags & IPT_CONNTRACK_STATUS) { - if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, IPT_CONNTRACK_STATUS)) + if(sinfo->flags & XT_CONNTRACK_STATUS) { + if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, XT_CONNTRACK_STATUS)) return 0; } - if(sinfo->flags & IPT_CONNTRACK_EXPIRES) { + if(sinfo->flags & XT_CONNTRACK_EXPIRES) { unsigned long expires; if(!ct) @@ -189,7 +192,7 @@ match(const struct sk_buff *skb, expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0; - if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), IPT_CONNTRACK_EXPIRES)) + if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), XT_CONNTRACK_EXPIRES)) return 0; } @@ -199,18 +202,18 @@ match(const struct sk_buff *skb, #endif /* CONFIG_NF_IP_CONNTRACK */ static int check(const char *tablename, - const struct ipt_ip *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { - if (matchsize != IPT_ALIGN(sizeof(struct ipt_conntrack_info))) + if (matchsize != XT_ALIGN(sizeof(struct xt_conntrack_info))) return 0; return 1; } -static struct ipt_match conntrack_match = { +static struct xt_match conntrack_match = { .name = "conntrack", .match = &match, .checkentry = &check, @@ -219,13 +222,16 @@ static struct ipt_match conntrack_match = { static int __init init(void) { - need_ip_conntrack(); - return ipt_register_match(&conntrack_match); + int ret; + need_conntrack(); + ret = xt_register_match(AF_INET, &conntrack_match); + + return ret; } static void __exit fini(void) { - ipt_unregister_match(&conntrack_match); + xt_unregister_match(AF_INET, &conntrack_match); } module_init(init); diff --git a/net/ipv4/netfilter/ipt_dccp.c b/net/netfilter/xt_dccp.c similarity index 58% rename from net/ipv4/netfilter/ipt_dccp.c rename to net/netfilter/xt_dccp.c index ad3278bba6c..779f42fc952 100644 --- a/net/ipv4/netfilter/ipt_dccp.c +++ b/net/netfilter/xt_dccp.c @@ -14,8 +14,16 @@ #include #include +#include +#include + #include -#include +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Harald Welte "); +MODULE_DESCRIPTION("Match for DCCP protocol packets"); +MODULE_ALIAS("ipt_dccp"); #define DCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \ || (!!((invflag) & (option)) ^ (cond))) @@ -26,6 +34,7 @@ static DEFINE_SPINLOCK(dccp_buflock); static inline int dccp_find_option(u_int8_t option, const struct sk_buff *skb, + unsigned int protoff, const struct dccp_hdr *dh, int *hotdrop) { @@ -44,9 +53,7 @@ dccp_find_option(u_int8_t option, return 0; spin_lock_bh(&dccp_buflock); - op = skb_header_pointer(skb, - skb->nh.iph->ihl*4 + optoff, - optlen, dccp_optbuf); + op = skb_header_pointer(skb, protoff + optoff, optlen, dccp_optbuf); if (op == NULL) { /* If we don't have the whole header, drop packet. */ spin_unlock_bh(&dccp_buflock); @@ -78,10 +85,10 @@ match_types(const struct dccp_hdr *dh, u_int16_t typemask) } static inline int -match_option(u_int8_t option, const struct sk_buff *skb, +match_option(u_int8_t option, const struct sk_buff *skb, unsigned int protoff, const struct dccp_hdr *dh, int *hotdrop) { - return dccp_find_option(option, skb, dh, hotdrop); + return dccp_find_option(option, skb, protoff, dh, hotdrop); } static int @@ -90,16 +97,17 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - const struct ipt_dccp_info *info = - (const struct ipt_dccp_info *)matchinfo; + const struct xt_dccp_info *info = + (const struct xt_dccp_info *)matchinfo; struct dccp_hdr _dh, *dh; if (offset) return 0; - dh = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_dh), &_dh); + dh = skb_header_pointer(skb, protoff, sizeof(_dh), &_dh); if (dh == NULL) { *hotdrop = 1; return 0; @@ -107,42 +115,73 @@ match(const struct sk_buff *skb, return DCCHECK(((ntohs(dh->dccph_sport) >= info->spts[0]) && (ntohs(dh->dccph_sport) <= info->spts[1])), - IPT_DCCP_SRC_PORTS, info->flags, info->invflags) + XT_DCCP_SRC_PORTS, info->flags, info->invflags) && DCCHECK(((ntohs(dh->dccph_dport) >= info->dpts[0]) && (ntohs(dh->dccph_dport) <= info->dpts[1])), - IPT_DCCP_DEST_PORTS, info->flags, info->invflags) + XT_DCCP_DEST_PORTS, info->flags, info->invflags) && DCCHECK(match_types(dh, info->typemask), - IPT_DCCP_TYPE, info->flags, info->invflags) - && DCCHECK(match_option(info->option, skb, dh, hotdrop), - IPT_DCCP_OPTION, info->flags, info->invflags); + XT_DCCP_TYPE, info->flags, info->invflags) + && DCCHECK(match_option(info->option, skb, protoff, dh, + hotdrop), + XT_DCCP_OPTION, info->flags, info->invflags); } static int checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *inf, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { - const struct ipt_dccp_info *info; + const struct ipt_ip *ip = inf; + const struct xt_dccp_info *info; - info = (const struct ipt_dccp_info *)matchinfo; + info = (const struct xt_dccp_info *)matchinfo; return ip->proto == IPPROTO_DCCP - && !(ip->invflags & IPT_INV_PROTO) - && matchsize == IPT_ALIGN(sizeof(struct ipt_dccp_info)) - && !(info->flags & ~IPT_DCCP_VALID_FLAGS) - && !(info->invflags & ~IPT_DCCP_VALID_FLAGS) + && !(ip->invflags & XT_INV_PROTO) + && matchsize == XT_ALIGN(sizeof(struct xt_dccp_info)) + && !(info->flags & ~XT_DCCP_VALID_FLAGS) + && !(info->invflags & ~XT_DCCP_VALID_FLAGS) && !(info->invflags & ~info->flags); } -static struct ipt_match dccp_match = +static int +checkentry6(const char *tablename, + const void *inf, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + const struct ip6t_ip6 *ip = inf; + const struct xt_dccp_info *info; + + info = (const struct xt_dccp_info *)matchinfo; + + return ip->proto == IPPROTO_DCCP + && !(ip->invflags & XT_INV_PROTO) + && matchsize == XT_ALIGN(sizeof(struct xt_dccp_info)) + && !(info->flags & ~XT_DCCP_VALID_FLAGS) + && !(info->invflags & ~XT_DCCP_VALID_FLAGS) + && !(info->invflags & ~info->flags); +} + + +static struct xt_match dccp_match = { .name = "dccp", .match = &match, .checkentry = &checkentry, .me = THIS_MODULE, }; +static struct xt_match dccp6_match = +{ + .name = "dccp", + .match = &match, + .checkentry = &checkentry6, + .me = THIS_MODULE, +}; + static int __init init(void) { @@ -154,23 +193,29 @@ static int __init init(void) dccp_optbuf = kmalloc(256 * 4, GFP_KERNEL); if (!dccp_optbuf) return -ENOMEM; - ret = ipt_register_match(&dccp_match); + ret = xt_register_match(AF_INET, &dccp_match); if (ret) - kfree(dccp_optbuf); + goto out_kfree; + ret = xt_register_match(AF_INET6, &dccp6_match); + if (ret) + goto out_unreg; + + return ret; + +out_unreg: + xt_unregister_match(AF_INET, &dccp_match); +out_kfree: + kfree(dccp_optbuf); return ret; } static void __exit fini(void) { - ipt_unregister_match(&dccp_match); + xt_unregister_match(AF_INET6, &dccp6_match); + xt_unregister_match(AF_INET, &dccp_match); kfree(dccp_optbuf); } module_init(init); module_exit(fini); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Harald Welte "); -MODULE_DESCRIPTION("Match for DCCP protocol packets"); - diff --git a/net/ipv4/netfilter/ipt_helper.c b/net/netfilter/xt_helper.c similarity index 72% rename from net/ipv4/netfilter/ipt_helper.c rename to net/netfilter/xt_helper.c index aef649e393a..38b6715e1db 100644 --- a/net/ipv4/netfilter/ipt_helper.c +++ b/net/netfilter/xt_helper.c @@ -13,7 +13,6 @@ #include #include #include -#include #if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) #include #include @@ -23,12 +22,14 @@ #include #include #endif -#include -#include +#include +#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Martin Josefsson "); MODULE_DESCRIPTION("iptables helper match module"); +MODULE_ALIAS("ipt_helper"); +MODULE_ALIAS("ip6t_helper"); #if 0 #define DEBUGP printk @@ -43,27 +44,28 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - const struct ipt_helper_info *info = matchinfo; + const struct xt_helper_info *info = matchinfo; struct ip_conntrack *ct; enum ip_conntrack_info ctinfo; int ret = info->invert; ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo); if (!ct) { - DEBUGP("ipt_helper: Eek! invalid conntrack?\n"); + DEBUGP("xt_helper: Eek! invalid conntrack?\n"); return ret; } if (!ct->master) { - DEBUGP("ipt_helper: conntrack %p has no master\n", ct); + DEBUGP("xt_helper: conntrack %p has no master\n", ct); return ret; } read_lock_bh(&ip_conntrack_lock); if (!ct->master->helper) { - DEBUGP("ipt_helper: master ct %p has no helper\n", + DEBUGP("xt_helper: master ct %p has no helper\n", exp->expectant); goto out_unlock; } @@ -89,27 +91,28 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - const struct ipt_helper_info *info = matchinfo; + const struct xt_helper_info *info = matchinfo; struct nf_conn *ct; enum ip_conntrack_info ctinfo; int ret = info->invert; ct = nf_ct_get((struct sk_buff *)skb, &ctinfo); if (!ct) { - DEBUGP("ipt_helper: Eek! invalid conntrack?\n"); + DEBUGP("xt_helper: Eek! invalid conntrack?\n"); return ret; } if (!ct->master) { - DEBUGP("ipt_helper: conntrack %p has no master\n", ct); + DEBUGP("xt_helper: conntrack %p has no master\n", ct); return ret; } read_lock_bh(&nf_conntrack_lock); if (!ct->master->helper) { - DEBUGP("ipt_helper: master ct %p has no helper\n", + DEBUGP("xt_helper: master ct %p has no helper\n", exp->expectant); goto out_unlock; } @@ -129,23 +132,29 @@ out_unlock: #endif static int check(const char *tablename, - const struct ipt_ip *ip, + const void *inf, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { - struct ipt_helper_info *info = matchinfo; + struct xt_helper_info *info = matchinfo; info->name[29] = '\0'; /* verify size */ - if (matchsize != IPT_ALIGN(sizeof(struct ipt_helper_info))) + if (matchsize != XT_ALIGN(sizeof(struct xt_helper_info))) return 0; return 1; } -static struct ipt_match helper_match = { +static struct xt_match helper_match = { + .name = "helper", + .match = &match, + .checkentry = &check, + .me = THIS_MODULE, +}; +static struct xt_match helper6_match = { .name = "helper", .match = &match, .checkentry = &check, @@ -154,13 +163,24 @@ static struct ipt_match helper_match = { static int __init init(void) { - need_ip_conntrack(); - return ipt_register_match(&helper_match); + int ret; + need_conntrack(); + + ret = xt_register_match(AF_INET, &helper_match); + if (ret < 0) + return ret; + + ret = xt_register_match(AF_INET6, &helper6_match); + if (ret < 0) + xt_unregister_match(AF_INET, &helper_match); + + return ret; } static void __exit fini(void) { - ipt_unregister_match(&helper_match); + xt_unregister_match(AF_INET, &helper_match); + xt_unregister_match(AF_INET6, &helper6_match); } module_init(init); diff --git a/net/netfilter/xt_length.c b/net/netfilter/xt_length.c new file mode 100644 index 00000000000..ab6c710cf88 --- /dev/null +++ b/net/netfilter/xt_length.c @@ -0,0 +1,98 @@ +/* Kernel module to match packet length. */ +/* (C) 1999-2001 James Morris + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +#include +#include + +MODULE_AUTHOR("James Morris "); +MODULE_DESCRIPTION("IP tables packet length matching module"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("ipt_length"); +MODULE_ALIAS("ip6t_length"); + +static int +match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const void *matchinfo, + int offset, + unsigned int protoff, + int *hotdrop) +{ + const struct xt_length_info *info = matchinfo; + u_int16_t pktlen = ntohs(skb->nh.iph->tot_len); + + return (pktlen >= info->min && pktlen <= info->max) ^ info->invert; +} + +static int +match6(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const void *matchinfo, + int offset, + unsigned int protoff, + int *hotdrop) +{ + const struct xt_length_info *info = matchinfo; + u_int16_t pktlen = ntohs(skb->nh.ipv6h->payload_len) + sizeof(struct ipv6hdr); + + return (pktlen >= info->min && pktlen <= info->max) ^ info->invert; +} + +static int +checkentry(const char *tablename, + const void *ip, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + if (matchsize != XT_ALIGN(sizeof(struct xt_length_info))) + return 0; + + return 1; +} + +static struct xt_match length_match = { + .name = "length", + .match = &match, + .checkentry = &checkentry, + .me = THIS_MODULE, +}; +static struct xt_match length6_match = { + .name = "length", + .match = &match6, + .checkentry = &checkentry, + .me = THIS_MODULE, +}; + +static int __init init(void) +{ + int ret; + ret = xt_register_match(AF_INET, &length_match); + if (ret) + return ret; + ret = xt_register_match(AF_INET6, &length6_match); + if (ret) + xt_unregister_match(AF_INET, &length_match); + + return ret; +} + +static void __exit fini(void) +{ + xt_unregister_match(AF_INET, &length_match); + xt_unregister_match(AF_INET6, &length6_match); +} + +module_init(init); +module_exit(fini); diff --git a/net/ipv4/netfilter/ipt_limit.c b/net/netfilter/xt_limit.c similarity index 78% rename from net/ipv4/netfilter/ipt_limit.c rename to net/netfilter/xt_limit.c index 0c24dcc703a..15e40506bc3 100644 --- a/net/ipv4/netfilter/ipt_limit.c +++ b/net/netfilter/xt_limit.c @@ -18,12 +18,14 @@ #include #include -#include -#include +#include +#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Herve Eychenne "); MODULE_DESCRIPTION("iptables rate limit match"); +MODULE_ALIAS("ipt_limit"); +MODULE_ALIAS("ip6t_limit"); /* The algorithm used is the Simple Token Bucket Filter (TBF) * see net/sched/sch_tbf.c in the linux source tree @@ -68,9 +70,10 @@ ipt_limit_match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - struct ipt_rateinfo *r = ((struct ipt_rateinfo *)matchinfo)->master; + struct xt_rateinfo *r = ((struct xt_rateinfo *)matchinfo)->master; unsigned long now = jiffies; spin_lock_bh(&limit_lock); @@ -96,32 +99,32 @@ user2credits(u_int32_t user) /* If multiplying would overflow... */ if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY)) /* Divide first. */ - return (user / IPT_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY; + return (user / XT_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY; - return (user * HZ * CREDITS_PER_JIFFY) / IPT_LIMIT_SCALE; + return (user * HZ * CREDITS_PER_JIFFY) / XT_LIMIT_SCALE; } static int ipt_limit_checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *inf, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { - struct ipt_rateinfo *r = matchinfo; + struct xt_rateinfo *r = matchinfo; - if (matchsize != IPT_ALIGN(sizeof(struct ipt_rateinfo))) + if (matchsize != XT_ALIGN(sizeof(struct xt_rateinfo))) return 0; /* Check for overflow. */ if (r->burst == 0 || user2credits(r->avg * r->burst) < user2credits(r->avg)) { - printk("Overflow in ipt_limit, try lower: %u/%u\n", + printk("Overflow in xt_limit, try lower: %u/%u\n", r->avg, r->burst); return 0; } - /* User avg in seconds * IPT_LIMIT_SCALE: convert to jiffies * + /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies * 128. */ r->prev = jiffies; r->credit = user2credits(r->avg * r->burst); /* Credits full. */ @@ -134,7 +137,13 @@ ipt_limit_checkentry(const char *tablename, return 1; } -static struct ipt_match ipt_limit_reg = { +static struct xt_match ipt_limit_reg = { + .name = "limit", + .match = ipt_limit_match, + .checkentry = ipt_limit_checkentry, + .me = THIS_MODULE, +}; +static struct xt_match limit6_reg = { .name = "limit", .match = ipt_limit_match, .checkentry = ipt_limit_checkentry, @@ -143,14 +152,23 @@ static struct ipt_match ipt_limit_reg = { static int __init init(void) { - if (ipt_register_match(&ipt_limit_reg)) - return -EINVAL; - return 0; + int ret; + + ret = xt_register_match(AF_INET, &ipt_limit_reg); + if (ret) + return ret; + + ret = xt_register_match(AF_INET6, &limit6_reg); + if (ret) + xt_unregister_match(AF_INET, &ipt_limit_reg); + + return ret; } static void __exit fini(void) { - ipt_unregister_match(&ipt_limit_reg); + xt_unregister_match(AF_INET, &ipt_limit_reg); + xt_unregister_match(AF_INET6, &limit6_reg); } module_init(init); diff --git a/net/ipv4/netfilter/ipt_mac.c b/net/netfilter/xt_mac.c similarity index 65% rename from net/ipv4/netfilter/ipt_mac.c rename to net/netfilter/xt_mac.c index 1b9bb4559f8..0461dcb5fc7 100644 --- a/net/ipv4/netfilter/ipt_mac.c +++ b/net/netfilter/xt_mac.c @@ -13,12 +13,15 @@ #include #include -#include -#include +#include +#include +#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Netfilter Core Team "); MODULE_DESCRIPTION("iptables mac matching module"); +MODULE_ALIAS("ipt_mac"); +MODULE_ALIAS("ip6t_mac"); static int match(const struct sk_buff *skb, @@ -26,9 +29,10 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - const struct ipt_mac_info *info = matchinfo; + const struct xt_mac_info *info = matchinfo; /* Is mac pointer valid? */ return (skb->mac.raw >= skb->head @@ -40,7 +44,7 @@ match(const struct sk_buff *skb, static int ipt_mac_checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *inf, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) @@ -49,17 +53,23 @@ ipt_mac_checkentry(const char *tablename, if (hook_mask & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD))) { - printk("ipt_mac: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n"); + printk("xt_mac: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n"); return 0; } - if (matchsize != IPT_ALIGN(sizeof(struct ipt_mac_info))) + if (matchsize != XT_ALIGN(sizeof(struct xt_mac_info))) return 0; return 1; } -static struct ipt_match mac_match = { +static struct xt_match mac_match = { + .name = "mac", + .match = &match, + .checkentry = &ipt_mac_checkentry, + .me = THIS_MODULE, +}; +static struct xt_match mac6_match = { .name = "mac", .match = &match, .checkentry = &ipt_mac_checkentry, @@ -68,12 +78,22 @@ static struct ipt_match mac_match = { static int __init init(void) { - return ipt_register_match(&mac_match); + int ret; + ret = xt_register_match(AF_INET, &mac_match); + if (ret) + return ret; + + ret = xt_register_match(AF_INET6, &mac6_match); + if (ret) + xt_unregister_match(AF_INET, &mac_match); + + return ret; } static void __exit fini(void) { - ipt_unregister_match(&mac_match); + xt_unregister_match(AF_INET, &mac_match); + xt_unregister_match(AF_INET6, &mac6_match); } module_init(init); diff --git a/net/ipv4/netfilter/ipt_mark.c b/net/netfilter/xt_mark.c similarity index 60% rename from net/ipv4/netfilter/ipt_mark.c rename to net/netfilter/xt_mark.c index 00bef6cdd3f..2a0ac62b72c 100644 --- a/net/ipv4/netfilter/ipt_mark.c +++ b/net/netfilter/xt_mark.c @@ -10,12 +10,14 @@ #include #include -#include -#include +#include +#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Marc Boucher "); MODULE_DESCRIPTION("iptables mark matching module"); +MODULE_ALIAS("ipt_mark"); +MODULE_ALIAS("ip6t_mark"); static int match(const struct sk_buff *skb, @@ -23,23 +25,24 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - const struct ipt_mark_info *info = matchinfo; + const struct xt_mark_info *info = matchinfo; return ((skb->nfmark & info->mask) == info->mark) ^ info->invert; } static int checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *entry, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { - struct ipt_mark_info *minfo = (struct ipt_mark_info *) matchinfo; + struct xt_mark_info *minfo = (struct xt_mark_info *) matchinfo; - if (matchsize != IPT_ALIGN(sizeof(struct ipt_mark_info))) + if (matchsize != XT_ALIGN(sizeof(struct xt_mark_info))) return 0; if (minfo->mark > 0xffffffff || minfo->mask > 0xffffffff) { @@ -50,7 +53,14 @@ checkentry(const char *tablename, return 1; } -static struct ipt_match mark_match = { +static struct xt_match mark_match = { + .name = "mark", + .match = &match, + .checkentry = &checkentry, + .me = THIS_MODULE, +}; + +static struct xt_match mark6_match = { .name = "mark", .match = &match, .checkentry = &checkentry, @@ -59,12 +69,22 @@ static struct ipt_match mark_match = { static int __init init(void) { - return ipt_register_match(&mark_match); + int ret; + ret = xt_register_match(AF_INET, &mark_match); + if (ret) + return ret; + + ret = xt_register_match(AF_INET6, &mark6_match); + if (ret) + xt_unregister_match(AF_INET, &mark_match); + + return ret; } static void __exit fini(void) { - ipt_unregister_match(&mark_match); + xt_unregister_match(AF_INET, &mark_match); + xt_unregister_match(AF_INET6, &mark6_match); } module_init(init); diff --git a/net/ipv6/netfilter/ip6t_physdev.c b/net/netfilter/xt_physdev.c similarity index 57% rename from net/ipv6/netfilter/ip6t_physdev.c rename to net/netfilter/xt_physdev.c index 71515c86ece..19bb57c14df 100644 --- a/net/ipv6/netfilter/ip6t_physdev.c +++ b/net/netfilter/xt_physdev.c @@ -10,8 +10,8 @@ #include #include -#include -#include +#include +#include #include #define MATCH 1 #define NOMATCH 0 @@ -19,6 +19,8 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Bart De Schuymer "); MODULE_DESCRIPTION("iptables bridge physical device match module"); +MODULE_ALIAS("ipt_physdev"); +MODULE_ALIAS("ip6t_physdev"); static int match(const struct sk_buff *skb, @@ -31,7 +33,7 @@ match(const struct sk_buff *skb, { int i; static const char nulldevname[IFNAMSIZ]; - const struct ip6t_physdev_info *info = matchinfo; + const struct xt_physdev_info *info = matchinfo; unsigned int ret; const char *indev, *outdev; struct nf_bridge_info *nf_bridge; @@ -41,37 +43,37 @@ match(const struct sk_buff *skb, * the destination device will be a bridge. */ if (!(nf_bridge = skb->nf_bridge)) { /* Return MATCH if the invert flags of the used options are on */ - if ((info->bitmask & IP6T_PHYSDEV_OP_BRIDGED) && - !(info->invert & IP6T_PHYSDEV_OP_BRIDGED)) + if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) && + !(info->invert & XT_PHYSDEV_OP_BRIDGED)) return NOMATCH; - if ((info->bitmask & IP6T_PHYSDEV_OP_ISIN) && - !(info->invert & IP6T_PHYSDEV_OP_ISIN)) + if ((info->bitmask & XT_PHYSDEV_OP_ISIN) && + !(info->invert & XT_PHYSDEV_OP_ISIN)) return NOMATCH; - if ((info->bitmask & IP6T_PHYSDEV_OP_ISOUT) && - !(info->invert & IP6T_PHYSDEV_OP_ISOUT)) + if ((info->bitmask & XT_PHYSDEV_OP_ISOUT) && + !(info->invert & XT_PHYSDEV_OP_ISOUT)) return NOMATCH; - if ((info->bitmask & IP6T_PHYSDEV_OP_IN) && - !(info->invert & IP6T_PHYSDEV_OP_IN)) + if ((info->bitmask & XT_PHYSDEV_OP_IN) && + !(info->invert & XT_PHYSDEV_OP_IN)) return NOMATCH; - if ((info->bitmask & IP6T_PHYSDEV_OP_OUT) && - !(info->invert & IP6T_PHYSDEV_OP_OUT)) + if ((info->bitmask & XT_PHYSDEV_OP_OUT) && + !(info->invert & XT_PHYSDEV_OP_OUT)) return NOMATCH; return MATCH; } /* This only makes sense in the FORWARD and POSTROUTING chains */ - if ((info->bitmask & IP6T_PHYSDEV_OP_BRIDGED) && + if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) && (!!(nf_bridge->mask & BRNF_BRIDGED) ^ - !(info->invert & IP6T_PHYSDEV_OP_BRIDGED))) + !(info->invert & XT_PHYSDEV_OP_BRIDGED))) return NOMATCH; - if ((info->bitmask & IP6T_PHYSDEV_OP_ISIN && - (!nf_bridge->physindev ^ !!(info->invert & IP6T_PHYSDEV_OP_ISIN))) || - (info->bitmask & IP6T_PHYSDEV_OP_ISOUT && - (!nf_bridge->physoutdev ^ !!(info->invert & IP6T_PHYSDEV_OP_ISOUT)))) + if ((info->bitmask & XT_PHYSDEV_OP_ISIN && + (!nf_bridge->physindev ^ !!(info->invert & XT_PHYSDEV_OP_ISIN))) || + (info->bitmask & XT_PHYSDEV_OP_ISOUT && + (!nf_bridge->physoutdev ^ !!(info->invert & XT_PHYSDEV_OP_ISOUT)))) return NOMATCH; - if (!(info->bitmask & IP6T_PHYSDEV_OP_IN)) + if (!(info->bitmask & XT_PHYSDEV_OP_IN)) goto match_outdev; indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname; for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) { @@ -80,11 +82,11 @@ match(const struct sk_buff *skb, & ((const unsigned int *)info->in_mask)[i]; } - if ((ret == 0) ^ !(info->invert & IP6T_PHYSDEV_OP_IN)) + if ((ret == 0) ^ !(info->invert & XT_PHYSDEV_OP_IN)) return NOMATCH; match_outdev: - if (!(info->bitmask & IP6T_PHYSDEV_OP_OUT)) + if (!(info->bitmask & XT_PHYSDEV_OP_OUT)) return MATCH; outdev = nf_bridge->physoutdev ? nf_bridge->physoutdev->name : nulldevname; @@ -94,27 +96,34 @@ match_outdev: & ((const unsigned int *)info->out_mask)[i]; } - return (ret != 0) ^ !(info->invert & IP6T_PHYSDEV_OP_OUT); + return (ret != 0) ^ !(info->invert & XT_PHYSDEV_OP_OUT); } static int checkentry(const char *tablename, - const struct ip6t_ip6 *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { - const struct ip6t_physdev_info *info = matchinfo; + const struct xt_physdev_info *info = matchinfo; - if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_physdev_info))) + if (matchsize != XT_ALIGN(sizeof(struct xt_physdev_info))) return 0; - if (!(info->bitmask & IP6T_PHYSDEV_OP_MASK) || - info->bitmask & ~IP6T_PHYSDEV_OP_MASK) + if (!(info->bitmask & XT_PHYSDEV_OP_MASK) || + info->bitmask & ~XT_PHYSDEV_OP_MASK) return 0; return 1; } -static struct ip6t_match physdev_match = { +static struct xt_match physdev_match = { + .name = "physdev", + .match = &match, + .checkentry = &checkentry, + .me = THIS_MODULE, +}; + +static struct xt_match physdev6_match = { .name = "physdev", .match = &match, .checkentry = &checkentry, @@ -123,12 +132,23 @@ static struct ip6t_match physdev_match = { static int __init init(void) { - return ip6t_register_match(&physdev_match); + int ret; + + ret = xt_register_match(AF_INET, &physdev_match); + if (ret < 0) + return ret; + + ret = xt_register_match(AF_INET6, &physdev6_match); + if (ret < 0) + xt_unregister_match(AF_INET, &physdev_match); + + return ret; } static void __exit fini(void) { - ip6t_unregister_match(&physdev_match); + xt_unregister_match(AF_INET, &physdev_match); + xt_unregister_match(AF_INET6, &physdev6_match); } module_init(init); diff --git a/net/ipv4/netfilter/ipt_pkttype.c b/net/netfilter/xt_pkttype.c similarity index 55% rename from net/ipv4/netfilter/ipt_pkttype.c rename to net/netfilter/xt_pkttype.c index 8ddb1dc5e5a..ab1b2630f97 100644 --- a/net/ipv4/netfilter/ipt_pkttype.c +++ b/net/netfilter/xt_pkttype.c @@ -10,60 +10,72 @@ #include #include -#include -#include +#include +#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Michal Ludvig "); MODULE_DESCRIPTION("IP tables match to match on linklayer packet type"); +MODULE_ALIAS("ipt_pkttype"); +MODULE_ALIAS("ip6t_pkttype"); static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - const struct ipt_pkttype_info *info = matchinfo; + const struct xt_pkttype_info *info = matchinfo; - return (skb->pkt_type == info->pkttype) ^ info->invert; + return (skb->pkt_type == info->pkttype) ^ info->invert; } static int checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { -/* - if (hook_mask - & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) - | (1 << NF_IP_FORWARD))) { - printk("ipt_pkttype: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n"); - return 0; - } -*/ - if (matchsize != IPT_ALIGN(sizeof(struct ipt_pkttype_info))) + if (matchsize != XT_ALIGN(sizeof(struct xt_pkttype_info))) return 0; return 1; } -static struct ipt_match pkttype_match = { +static struct xt_match pkttype_match = { .name = "pkttype", .match = &match, .checkentry = &checkentry, .me = THIS_MODULE, }; +static struct xt_match pkttype6_match = { + .name = "pkttype", + .match = &match, + .checkentry = &checkentry, + .me = THIS_MODULE, +}; + static int __init init(void) { - return ipt_register_match(&pkttype_match); + int ret; + ret = xt_register_match(AF_INET, &pkttype_match); + if (ret) + return ret; + + ret = xt_register_match(AF_INET6, &pkttype6_match); + if (ret) + xt_unregister_match(AF_INET, &pkttype_match); + + return ret; } static void __exit fini(void) { - ipt_unregister_match(&pkttype_match); + xt_unregister_match(AF_INET, &pkttype_match); + xt_unregister_match(AF_INET6, &pkttype6_match); } module_init(init); diff --git a/net/ipv4/netfilter/ipt_realm.c b/net/netfilter/xt_realm.c similarity index 70% rename from net/ipv4/netfilter/ipt_realm.c rename to net/netfilter/xt_realm.c index 54a6897ebaa..2b7e1781d34 100644 --- a/net/ipv4/netfilter/ipt_realm.c +++ b/net/netfilter/xt_realm.c @@ -14,12 +14,14 @@ #include #include -#include -#include +#include +#include +#include MODULE_AUTHOR("Sampsa Ranta "); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("iptables realm match"); +MODULE_DESCRIPTION("X_tables realm match"); +MODULE_ALIAS("ipt_realm"); static int match(const struct sk_buff *skb, @@ -27,16 +29,17 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - const struct ipt_realm_info *info = matchinfo; + const struct xt_realm_info *info = matchinfo; struct dst_entry *dst = skb->dst; return (info->id == (dst->tclassid & info->mask)) ^ info->invert; } static int check(const char *tablename, - const struct ipt_ip *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) @@ -44,18 +47,18 @@ static int check(const char *tablename, if (hook_mask & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_LOCAL_IN))) { - printk("ipt_realm: only valid for POST_ROUTING, LOCAL_OUT, " + printk("xt_realm: only valid for POST_ROUTING, LOCAL_OUT, " "LOCAL_IN or FORWARD.\n"); return 0; } - if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info))) { - printk("ipt_realm: invalid matchsize.\n"); + if (matchsize != XT_ALIGN(sizeof(struct xt_realm_info))) { + printk("xt_realm: invalid matchsize.\n"); return 0; } return 1; } -static struct ipt_match realm_match = { +static struct xt_match realm_match = { .name = "realm", .match = match, .checkentry = check, @@ -64,12 +67,12 @@ static struct ipt_match realm_match = { static int __init init(void) { - return ipt_register_match(&realm_match); + return xt_register_match(AF_INET, &realm_match); } static void __exit fini(void) { - ipt_unregister_match(&realm_match); + xt_unregister_match(AF_INET, &realm_match); } module_init(init); diff --git a/net/ipv4/netfilter/ipt_sctp.c b/net/netfilter/xt_sctp.c similarity index 62% rename from net/ipv4/netfilter/ipt_sctp.c rename to net/netfilter/xt_sctp.c index fe2b327bcaa..10fbfc5ba75 100644 --- a/net/ipv4/netfilter/ipt_sctp.c +++ b/net/netfilter/xt_sctp.c @@ -1,10 +1,18 @@ #include #include #include +#include #include +#include +#include #include -#include +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Kiran Kumar Immidi"); +MODULE_DESCRIPTION("Match for SCTP protocol packets"); +MODULE_ALIAS("ipt_sctp"); #ifdef DEBUG_SCTP #define duprintf(format, args...) printk(format , ## args) @@ -16,7 +24,7 @@ || (!!((invflag) & (option)) ^ (cond))) static int -match_flags(const struct ipt_sctp_flag_info *flag_info, +match_flags(const struct xt_sctp_flag_info *flag_info, const int flag_count, u_int8_t chunktype, u_int8_t chunkflags) @@ -32,15 +40,15 @@ match_flags(const struct ipt_sctp_flag_info *flag_info, return 1; } -static int +static inline int match_packet(const struct sk_buff *skb, + unsigned int offset, const u_int32_t *chunkmap, int chunk_match_type, - const struct ipt_sctp_flag_info *flag_info, + const struct xt_sctp_flag_info *flag_info, const int flag_count, int *hotdrop) { - int offset; u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)]; sctp_chunkhdr_t _sch, *sch; @@ -52,7 +60,6 @@ match_packet(const struct sk_buff *skb, SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap); } - offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t); do { sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch); if (sch == NULL) { @@ -118,19 +125,20 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - const struct ipt_sctp_info *info; + const struct xt_sctp_info *info; sctp_sctphdr_t _sh, *sh; - info = (const struct ipt_sctp_info *)matchinfo; + info = (const struct xt_sctp_info *)matchinfo; if (offset) { duprintf("Dropping non-first fragment.. FIXME\n"); return 0; } - sh = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_sh), &_sh); + sh = skb_header_pointer(skb, protoff, sizeof(_sh), &_sh); if (sh == NULL) { duprintf("Dropping evil TCP offset=0 tinygram.\n"); *hotdrop = 1; @@ -140,64 +148,103 @@ match(const struct sk_buff *skb, return SCCHECK(((ntohs(sh->source) >= info->spts[0]) && (ntohs(sh->source) <= info->spts[1])), - IPT_SCTP_SRC_PORTS, info->flags, info->invflags) + XT_SCTP_SRC_PORTS, info->flags, info->invflags) && SCCHECK(((ntohs(sh->dest) >= info->dpts[0]) && (ntohs(sh->dest) <= info->dpts[1])), - IPT_SCTP_DEST_PORTS, info->flags, info->invflags) - && SCCHECK(match_packet(skb, info->chunkmap, info->chunk_match_type, + XT_SCTP_DEST_PORTS, info->flags, info->invflags) + && SCCHECK(match_packet(skb, protoff, + info->chunkmap, info->chunk_match_type, info->flag_info, info->flag_count, hotdrop), - IPT_SCTP_CHUNK_TYPES, info->flags, info->invflags); + XT_SCTP_CHUNK_TYPES, info->flags, info->invflags); } static int checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *inf, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + const struct xt_sctp_info *info; + const struct ipt_ip *ip = inf; + + info = (const struct xt_sctp_info *)matchinfo; + + return ip->proto == IPPROTO_SCTP + && !(ip->invflags & XT_INV_PROTO) + && matchsize == XT_ALIGN(sizeof(struct xt_sctp_info)) + && !(info->flags & ~XT_SCTP_VALID_FLAGS) + && !(info->invflags & ~XT_SCTP_VALID_FLAGS) + && !(info->invflags & ~info->flags) + && ((!(info->flags & XT_SCTP_CHUNK_TYPES)) || + (info->chunk_match_type & + (SCTP_CHUNK_MATCH_ALL + | SCTP_CHUNK_MATCH_ANY + | SCTP_CHUNK_MATCH_ONLY))); +} + +static int +checkentry6(const char *tablename, + const void *inf, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { - const struct ipt_sctp_info *info; + const struct xt_sctp_info *info; + const struct ip6t_ip6 *ip = inf; - info = (const struct ipt_sctp_info *)matchinfo; + info = (const struct xt_sctp_info *)matchinfo; return ip->proto == IPPROTO_SCTP - && !(ip->invflags & IPT_INV_PROTO) - && matchsize == IPT_ALIGN(sizeof(struct ipt_sctp_info)) - && !(info->flags & ~IPT_SCTP_VALID_FLAGS) - && !(info->invflags & ~IPT_SCTP_VALID_FLAGS) + && !(ip->invflags & XT_INV_PROTO) + && matchsize == XT_ALIGN(sizeof(struct xt_sctp_info)) + && !(info->flags & ~XT_SCTP_VALID_FLAGS) + && !(info->invflags & ~XT_SCTP_VALID_FLAGS) && !(info->invflags & ~info->flags) - && ((!(info->flags & IPT_SCTP_CHUNK_TYPES)) || + && ((!(info->flags & XT_SCTP_CHUNK_TYPES)) || (info->chunk_match_type & (SCTP_CHUNK_MATCH_ALL | SCTP_CHUNK_MATCH_ANY | SCTP_CHUNK_MATCH_ONLY))); } -static struct ipt_match sctp_match = + +static struct xt_match sctp_match = { - .list = { NULL, NULL}, .name = "sctp", .match = &match, .checkentry = &checkentry, - .destroy = NULL, + .me = THIS_MODULE +}; +static struct xt_match sctp6_match = +{ + .name = "sctp", + .match = &match, + .checkentry = &checkentry6, .me = THIS_MODULE }; + static int __init init(void) { - return ipt_register_match(&sctp_match); + int ret; + ret = xt_register_match(AF_INET, &sctp_match); + if (ret) + return ret; + + ret = xt_register_match(AF_INET6, &sctp6_match); + if (ret) + xt_unregister_match(AF_INET, &sctp_match); + + return ret; } static void __exit fini(void) { - ipt_unregister_match(&sctp_match); + xt_unregister_match(AF_INET6, &sctp6_match); + xt_unregister_match(AF_INET, &sctp_match); } module_init(init); module_exit(fini); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Kiran Kumar Immidi"); -MODULE_DESCRIPTION("Match for SCTP protocol packets"); - diff --git a/net/ipv4/netfilter/ipt_state.c b/net/netfilter/xt_state.c similarity index 53% rename from net/ipv4/netfilter/ipt_state.c rename to net/netfilter/xt_state.c index 4d7f16b70ce..39ce808d40e 100644 --- a/net/ipv4/netfilter/ipt_state.c +++ b/net/netfilter/xt_state.c @@ -1,7 +1,7 @@ /* Kernel module to match connection tracking information. */ /* (C) 1999-2001 Paul `Rusty' Russell - * (C) 2002-2004 Netfilter Core Team + * (C) 2002-2005 Netfilter Core Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -11,12 +11,14 @@ #include #include #include -#include -#include +#include +#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Rusty Russell "); -MODULE_DESCRIPTION("iptables connection tracking state match module"); +MODULE_DESCRIPTION("ip[6]_tables connection tracking state match module"); +MODULE_ALIAS("ipt_state"); +MODULE_ALIAS("ip6t_state"); static int match(const struct sk_buff *skb, @@ -24,35 +26,43 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - const struct ipt_state_info *sinfo = matchinfo; + const struct xt_state_info *sinfo = matchinfo; enum ip_conntrack_info ctinfo; unsigned int statebit; if (nf_ct_is_untracked(skb)) - statebit = IPT_STATE_UNTRACKED; + statebit = XT_STATE_UNTRACKED; else if (!nf_ct_get_ctinfo(skb, &ctinfo)) - statebit = IPT_STATE_INVALID; + statebit = XT_STATE_INVALID; else - statebit = IPT_STATE_BIT(ctinfo); + statebit = XT_STATE_BIT(ctinfo); return (sinfo->statemask & statebit); } static int check(const char *tablename, - const struct ipt_ip *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { - if (matchsize != IPT_ALIGN(sizeof(struct ipt_state_info))) + if (matchsize != XT_ALIGN(sizeof(struct xt_state_info))) return 0; return 1; } -static struct ipt_match state_match = { +static struct xt_match state_match = { + .name = "state", + .match = &match, + .checkentry = &check, + .me = THIS_MODULE, +}; + +static struct xt_match state6_match = { .name = "state", .match = &match, .checkentry = &check, @@ -61,13 +71,25 @@ static struct ipt_match state_match = { static int __init init(void) { - need_ip_conntrack(); - return ipt_register_match(&state_match); + int ret; + + need_conntrack(); + + ret = xt_register_match(AF_INET, &state_match); + if (ret < 0) + return ret; + + ret = xt_register_match(AF_INET6, &state6_match); + if (ret < 0) + xt_unregister_match(AF_INET,&state_match); + + return ret; } static void __exit fini(void) { - ipt_unregister_match(&state_match); + xt_unregister_match(AF_INET, &state_match); + xt_unregister_match(AF_INET6, &state6_match); } module_init(init); diff --git a/net/ipv4/netfilter/ipt_string.c b/net/netfilter/xt_string.c similarity index 66% rename from net/ipv4/netfilter/ipt_string.c rename to net/netfilter/xt_string.c index b5def204d79..7c7d5c8807d 100644 --- a/net/ipv4/netfilter/ipt_string.c +++ b/net/netfilter/xt_string.c @@ -11,23 +11,26 @@ #include #include #include -#include -#include +#include +#include #include MODULE_AUTHOR("Pablo Neira Ayuso "); MODULE_DESCRIPTION("IP tables string match module"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("ipt_string"); +MODULE_ALIAS("ip6t_string"); static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { struct ts_state state; - struct ipt_string_info *conf = (struct ipt_string_info *) matchinfo; + struct xt_string_info *conf = (struct xt_string_info *) matchinfo; memset(&state, 0, sizeof(struct ts_state)); @@ -36,18 +39,18 @@ static int match(const struct sk_buff *skb, != UINT_MAX) && !conf->invert; } -#define STRING_TEXT_PRIV(m) ((struct ipt_string_info *) m) +#define STRING_TEXT_PRIV(m) ((struct xt_string_info *) m) static int checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { - struct ipt_string_info *conf = matchinfo; + struct xt_string_info *conf = matchinfo; struct ts_config *ts_conf; - if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info))) + if (matchsize != XT_ALIGN(sizeof(struct xt_string_info))) return 0; /* Damn, can't handle this case properly with iptables... */ @@ -69,7 +72,14 @@ static void destroy(void *matchinfo, unsigned int matchsize) textsearch_destroy(STRING_TEXT_PRIV(matchinfo)->config); } -static struct ipt_match string_match = { +static struct xt_match string_match = { + .name = "string", + .match = match, + .checkentry = checkentry, + .destroy = destroy, + .me = THIS_MODULE +}; +static struct xt_match string6_match = { .name = "string", .match = match, .checkentry = checkentry, @@ -79,12 +89,22 @@ static struct ipt_match string_match = { static int __init init(void) { - return ipt_register_match(&string_match); + int ret; + + ret = xt_register_match(AF_INET, &string_match); + if (ret) + return ret; + ret = xt_register_match(AF_INET6, &string6_match); + if (ret) + xt_unregister_match(AF_INET, &string_match); + + return ret; } static void __exit fini(void) { - ipt_unregister_match(&string_match); + xt_unregister_match(AF_INET, &string_match); + xt_unregister_match(AF_INET6, &string6_match); } module_init(init); diff --git a/net/ipv4/netfilter/ipt_tcpmss.c b/net/netfilter/xt_tcpmss.c similarity index 59% rename from net/ipv4/netfilter/ipt_tcpmss.c rename to net/netfilter/xt_tcpmss.c index 4dc9b16ab4a..acf7f533e9f 100644 --- a/net/ipv4/netfilter/ipt_tcpmss.c +++ b/net/netfilter/xt_tcpmss.c @@ -1,6 +1,7 @@ /* Kernel module to match TCP MSS values. */ /* Copyright (C) 2000 Marc Boucher + * Portions (C) 2005 by Harald Welte * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -11,19 +12,24 @@ #include #include -#include +#include +#include + #include +#include #define TH_SYN 0x02 MODULE_LICENSE("GPL"); MODULE_AUTHOR("Marc Boucher "); MODULE_DESCRIPTION("iptables TCP MSS match module"); +MODULE_ALIAS("ipt_tcpmss"); /* Returns 1 if the mss option is set and matched by the range, 0 otherwise */ static inline int mssoption_match(u_int16_t min, u_int16_t max, const struct sk_buff *skb, + unsigned int protoff, int invert, int *hotdrop) { @@ -33,8 +39,7 @@ mssoption_match(u_int16_t min, u_int16_t max, unsigned int i, optlen; /* If we don't have the whole header, drop packet. */ - th = skb_header_pointer(skb, skb->nh.iph->ihl * 4, - sizeof(_tcph), &_tcph); + th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); if (th == NULL) goto dropit; @@ -47,8 +52,7 @@ mssoption_match(u_int16_t min, u_int16_t max, goto out; /* Truncated options. */ - op = skb_header_pointer(skb, skb->nh.iph->ihl * 4 + sizeof(*th), - optlen, _opt); + op = skb_header_pointer(skb, protoff + sizeof(*th), optlen, _opt); if (op == NULL) goto dropit; @@ -79,22 +83,24 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, + unsigned int protoff, int *hotdrop) { - const struct ipt_tcpmss_match_info *info = matchinfo; + const struct xt_tcpmss_match_info *info = matchinfo; - return mssoption_match(info->mss_min, info->mss_max, skb, + return mssoption_match(info->mss_min, info->mss_max, skb, protoff, info->invert, hotdrop); } static int checkentry(const char *tablename, - const struct ipt_ip *ip, + const void *ipinfo, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { - if (matchsize != IPT_ALIGN(sizeof(struct ipt_tcpmss_match_info))) + const struct ipt_ip *ip = ipinfo; + if (matchsize != XT_ALIGN(sizeof(struct xt_tcpmss_match_info))) return 0; /* Must specify -p tcp */ @@ -106,21 +112,60 @@ checkentry(const char *tablename, return 1; } -static struct ipt_match tcpmss_match = { +static int +checkentry6(const char *tablename, + const void *ipinfo, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + const struct ip6t_ip6 *ip = ipinfo; + + if (matchsize != XT_ALIGN(sizeof(struct xt_tcpmss_match_info))) + return 0; + + /* Must specify -p tcp */ + if (ip->proto != IPPROTO_TCP || (ip->invflags & XT_INV_PROTO)) { + printk("tcpmss: Only works on TCP packets\n"); + return 0; + } + + return 1; +} + +static struct xt_match tcpmss_match = { .name = "tcpmss", .match = &match, .checkentry = &checkentry, .me = THIS_MODULE, }; +static struct xt_match tcpmss6_match = { + .name = "tcpmss", + .match = &match, + .checkentry = &checkentry6, + .me = THIS_MODULE, +}; + + static int __init init(void) { - return ipt_register_match(&tcpmss_match); + int ret; + ret = xt_register_match(AF_INET, &tcpmss_match); + if (ret) + return ret; + + ret = xt_register_match(AF_INET6, &tcpmss6_match); + if (ret) + xt_unregister_match(AF_INET, &tcpmss_match); + + return ret; } static void __exit fini(void) { - ipt_unregister_match(&tcpmss_match); + xt_unregister_match(AF_INET6, &tcpmss6_match); + xt_unregister_match(AF_INET, &tcpmss_match); } module_init(init); diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c new file mode 100644 index 00000000000..33f86fd6f3e --- /dev/null +++ b/net/netfilter/xt_tcpudp.c @@ -0,0 +1,333 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_DESCRIPTION("x_tables match for TCP and UDP, supports IPv4 and IPv6"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("xt_tcp"); +MODULE_ALIAS("xt_udp"); +MODULE_ALIAS("ipt_udp"); +MODULE_ALIAS("ipt_tcp"); +MODULE_ALIAS("ip6t_udp"); +MODULE_ALIAS("ip6t_tcp"); + +#ifdef DEBUG_IP_FIREWALL_USER +#define duprintf(format, args...) printk(format , ## args) +#else +#define duprintf(format, args...) +#endif + + +/* Returns 1 if the port is matched by the range, 0 otherwise */ +static inline int +port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert) +{ + int ret; + + ret = (port >= min && port <= max) ^ invert; + return ret; +} + +static int +tcp_find_option(u_int8_t option, + const struct sk_buff *skb, + unsigned int protoff, + unsigned int optlen, + int invert, + int *hotdrop) +{ + /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */ + u_int8_t _opt[60 - sizeof(struct tcphdr)], *op; + unsigned int i; + + duprintf("tcp_match: finding option\n"); + + if (!optlen) + return invert; + + /* If we don't have the whole header, drop packet. */ + op = skb_header_pointer(skb, protoff + sizeof(struct tcphdr), + optlen, _opt); + if (op == NULL) { + *hotdrop = 1; + return 0; + } + + for (i = 0; i < optlen; ) { + if (op[i] == option) return !invert; + if (op[i] < 2) i++; + else i += op[i+1]?:1; + } + + return invert; +} + +static int +tcp_match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const void *matchinfo, + int offset, + unsigned int protoff, + int *hotdrop) +{ + struct tcphdr _tcph, *th; + const struct xt_tcp *tcpinfo = matchinfo; + + if (offset) { + /* To quote Alan: + + Don't allow a fragment of TCP 8 bytes in. Nobody normal + causes this. Its a cracker trying to break in by doing a + flag overwrite to pass the direction checks. + */ + if (offset == 1) { + duprintf("Dropping evil TCP offset=1 frag.\n"); + *hotdrop = 1; + } + /* Must not be a fragment. */ + return 0; + } + +#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg)) + + th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); + if (th == NULL) { + /* We've been asked to examine this packet, and we + can't. Hence, no choice but to drop. */ + duprintf("Dropping evil TCP offset=0 tinygram.\n"); + *hotdrop = 1; + return 0; + } + + if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1], + ntohs(th->source), + !!(tcpinfo->invflags & XT_TCP_INV_SRCPT))) + return 0; + if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1], + ntohs(th->dest), + !!(tcpinfo->invflags & XT_TCP_INV_DSTPT))) + return 0; + if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask) + == tcpinfo->flg_cmp, + XT_TCP_INV_FLAGS)) + return 0; + if (tcpinfo->option) { + if (th->doff * 4 < sizeof(_tcph)) { + *hotdrop = 1; + return 0; + } + if (!tcp_find_option(tcpinfo->option, skb, protoff, + th->doff*4 - sizeof(_tcph), + tcpinfo->invflags & XT_TCP_INV_OPTION, + hotdrop)) + return 0; + } + return 1; +} + +/* Called when user tries to insert an entry of this type. */ +static int +tcp_checkentry(const char *tablename, + const void *info, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + const struct ipt_ip *ip = info; + const struct xt_tcp *tcpinfo = matchinfo; + + /* Must specify proto == TCP, and no unknown invflags */ + return ip->proto == IPPROTO_TCP + && !(ip->invflags & XT_INV_PROTO) + && matchsize == XT_ALIGN(sizeof(struct xt_tcp)) + && !(tcpinfo->invflags & ~XT_TCP_INV_MASK); +} + +/* Called when user tries to insert an entry of this type. */ +static int +tcp6_checkentry(const char *tablename, + const void *entry, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + const struct ip6t_ip6 *ipv6 = entry; + const struct xt_tcp *tcpinfo = matchinfo; + + /* Must specify proto == TCP, and no unknown invflags */ + return ipv6->proto == IPPROTO_TCP + && !(ipv6->invflags & XT_INV_PROTO) + && matchsize == XT_ALIGN(sizeof(struct xt_tcp)) + && !(tcpinfo->invflags & ~XT_TCP_INV_MASK); +} + + +static int +udp_match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const void *matchinfo, + int offset, + unsigned int protoff, + int *hotdrop) +{ + struct udphdr _udph, *uh; + const struct xt_udp *udpinfo = matchinfo; + + /* Must not be a fragment. */ + if (offset) + return 0; + + uh = skb_header_pointer(skb, protoff, sizeof(_udph), &_udph); + if (uh == NULL) { + /* We've been asked to examine this packet, and we + can't. Hence, no choice but to drop. */ + duprintf("Dropping evil UDP tinygram.\n"); + *hotdrop = 1; + return 0; + } + + return port_match(udpinfo->spts[0], udpinfo->spts[1], + ntohs(uh->source), + !!(udpinfo->invflags & XT_UDP_INV_SRCPT)) + && port_match(udpinfo->dpts[0], udpinfo->dpts[1], + ntohs(uh->dest), + !!(udpinfo->invflags & XT_UDP_INV_DSTPT)); +} + +/* Called when user tries to insert an entry of this type. */ +static int +udp_checkentry(const char *tablename, + const void *info, + void *matchinfo, + unsigned int matchinfosize, + unsigned int hook_mask) +{ + const struct ipt_ip *ip = info; + const struct xt_udp *udpinfo = matchinfo; + + /* Must specify proto == UDP, and no unknown invflags */ + if (ip->proto != IPPROTO_UDP || (ip->invflags & XT_INV_PROTO)) { + duprintf("ipt_udp: Protocol %u != %u\n", ip->proto, + IPPROTO_UDP); + return 0; + } + if (matchinfosize != XT_ALIGN(sizeof(struct xt_udp))) { + duprintf("ipt_udp: matchsize %u != %u\n", + matchinfosize, XT_ALIGN(sizeof(struct xt_udp))); + return 0; + } + if (udpinfo->invflags & ~XT_UDP_INV_MASK) { + duprintf("ipt_udp: unknown flags %X\n", + udpinfo->invflags); + return 0; + } + + return 1; +} + +/* Called when user tries to insert an entry of this type. */ +static int +udp6_checkentry(const char *tablename, + const void *entry, + void *matchinfo, + unsigned int matchinfosize, + unsigned int hook_mask) +{ + const struct ip6t_ip6 *ipv6 = entry; + const struct xt_udp *udpinfo = matchinfo; + + /* Must specify proto == UDP, and no unknown invflags */ + if (ipv6->proto != IPPROTO_UDP || (ipv6->invflags & XT_INV_PROTO)) { + duprintf("ip6t_udp: Protocol %u != %u\n", ipv6->proto, + IPPROTO_UDP); + return 0; + } + if (matchinfosize != XT_ALIGN(sizeof(struct xt_udp))) { + duprintf("ip6t_udp: matchsize %u != %u\n", + matchinfosize, XT_ALIGN(sizeof(struct xt_udp))); + return 0; + } + if (udpinfo->invflags & ~XT_UDP_INV_MASK) { + duprintf("ip6t_udp: unknown flags %X\n", + udpinfo->invflags); + return 0; + } + + return 1; +} + +static struct xt_match tcp_matchstruct = { + .name = "tcp", + .match = &tcp_match, + .checkentry = &tcp_checkentry, + .me = THIS_MODULE, +}; +static struct xt_match tcp6_matchstruct = { + .name = "tcp", + .match = &tcp_match, + .checkentry = &tcp6_checkentry, + .me = THIS_MODULE, +}; + +static struct xt_match udp_matchstruct = { + .name = "udp", + .match = &udp_match, + .checkentry = &udp_checkentry, + .me = THIS_MODULE, +}; +static struct xt_match udp6_matchstruct = { + .name = "udp", + .match = &udp_match, + .checkentry = &udp6_checkentry, + .me = THIS_MODULE, +}; + +static int __init init(void) +{ + int ret; + ret = xt_register_match(AF_INET, &tcp_matchstruct); + if (ret) + return ret; + + ret = xt_register_match(AF_INET6, &tcp6_matchstruct); + if (ret) + goto out_unreg_tcp; + + ret = xt_register_match(AF_INET, &udp_matchstruct); + if (ret) + goto out_unreg_tcp6; + + ret = xt_register_match(AF_INET6, &udp6_matchstruct); + if (ret) + goto out_unreg_udp; + + return ret; + +out_unreg_udp: + xt_unregister_match(AF_INET, &tcp_matchstruct); +out_unreg_tcp6: + xt_unregister_match(AF_INET6, &tcp6_matchstruct); +out_unreg_tcp: + xt_unregister_match(AF_INET, &tcp_matchstruct); + return ret; +} + +static void __exit fini(void) +{ + xt_unregister_match(AF_INET6, &udp6_matchstruct); + xt_unregister_match(AF_INET, &udp_matchstruct); + xt_unregister_match(AF_INET6, &tcp6_matchstruct); + xt_unregister_match(AF_INET, &tcp_matchstruct); +} + +module_init(init); +module_exit(fini); diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index b5001939b74..39a22a3ffe7 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c @@ -62,7 +62,7 @@ ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook) struct ipt_target *target; int ret = 0; - target = ipt_find_target(t->u.user.name, t->u.user.revision); + target = xt_find_target(AF_INET, t->u.user.name, t->u.user.revision); if (!target) return -ENOENT; -- GitLab From 988bd50300ef2e2d5cb8563e2ac99453dd9acd86 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Thu, 12 Jan 2006 14:32:20 -0800 Subject: [PATCH 049/465] IPoIB: Fix memory leak of multicast group structures The current handling of multicast groups in IPoIB ends up never freeing send-only multicast groups. It turns out the logic was much more complicated than it needed to be; we can fix this bug and completely kill ipoib_mcast_dev_down() at the same time. Signed-off-by: Eli Cohen Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib_ib.c | 13 +--- .../infiniband/ulp/ipoib/ipoib_multicast.c | 61 +++---------------- 2 files changed, 9 insertions(+), 65 deletions(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 23885801b6d..f7e84897079 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -453,17 +453,8 @@ int ipoib_ib_dev_down(struct net_device *dev) } ipoib_mcast_stop_thread(dev, 1); - - /* - * Flush the multicast groups first so we stop any multicast joins. The - * completion thread may have already died and we may deadlock waiting - * for the completion thread to finish some multicast joins. - */ ipoib_mcast_dev_flush(dev); - /* Delete broadcast and local addresses since they will be recreated */ - ipoib_mcast_dev_down(dev); - ipoib_flush_paths(dev); return 0; @@ -624,9 +615,7 @@ void ipoib_ib_dev_cleanup(struct net_device *dev) ipoib_dbg(priv, "cleaning up ib_dev\n"); ipoib_mcast_stop_thread(dev, 1); - - /* Delete the broadcast address and the local address */ - ipoib_mcast_dev_down(dev); + ipoib_mcast_dev_flush(dev); ipoib_transport_dev_cleanup(dev); } diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index bf1c08cca8c..7403bac1977 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -742,50 +742,23 @@ void ipoib_mcast_dev_flush(struct net_device *dev) { struct ipoib_dev_priv *priv = netdev_priv(dev); LIST_HEAD(remove_list); - struct ipoib_mcast *mcast, *tmcast, *nmcast; + struct ipoib_mcast *mcast, *tmcast; unsigned long flags; ipoib_dbg_mcast(priv, "flushing multicast list\n"); spin_lock_irqsave(&priv->lock, flags); - list_for_each_entry_safe(mcast, tmcast, &priv->multicast_list, list) { - nmcast = ipoib_mcast_alloc(dev, 0); - if (nmcast) { - nmcast->flags = - mcast->flags & (1 << IPOIB_MCAST_FLAG_SENDONLY); - - nmcast->mcmember.mgid = mcast->mcmember.mgid; - - /* Add the new group in before the to-be-destroyed group */ - list_add_tail(&nmcast->list, &mcast->list); - list_del_init(&mcast->list); - rb_replace_node(&mcast->rb_node, &nmcast->rb_node, - &priv->multicast_tree); - - list_add_tail(&mcast->list, &remove_list); - } else { - ipoib_warn(priv, "could not reallocate multicast group " - IPOIB_GID_FMT "\n", - IPOIB_GID_ARG(mcast->mcmember.mgid)); - } + list_for_each_entry_safe(mcast, tmcast, &priv->multicast_list, list) { + list_del(&mcast->list); + rb_erase(&mcast->rb_node, &priv->multicast_tree); + list_add_tail(&mcast->list, &remove_list); } if (priv->broadcast) { - nmcast = ipoib_mcast_alloc(dev, 0); - if (nmcast) { - nmcast->mcmember.mgid = priv->broadcast->mcmember.mgid; - - rb_replace_node(&priv->broadcast->rb_node, - &nmcast->rb_node, - &priv->multicast_tree); - - list_add_tail(&priv->broadcast->list, &remove_list); - priv->broadcast = nmcast; - } else - ipoib_warn(priv, "could not reallocate broadcast group " - IPOIB_GID_FMT "\n", - IPOIB_GID_ARG(priv->broadcast->mcmember.mgid)); + rb_erase(&priv->broadcast->rb_node, &priv->multicast_tree); + list_add_tail(&priv->broadcast->list, &remove_list); + priv->broadcast = NULL; } spin_unlock_irqrestore(&priv->lock, flags); @@ -796,24 +769,6 @@ void ipoib_mcast_dev_flush(struct net_device *dev) } } -void ipoib_mcast_dev_down(struct net_device *dev) -{ - struct ipoib_dev_priv *priv = netdev_priv(dev); - unsigned long flags; - - /* Delete broadcast since it will be recreated */ - if (priv->broadcast) { - ipoib_dbg_mcast(priv, "deleting broadcast group\n"); - - spin_lock_irqsave(&priv->lock, flags); - rb_erase(&priv->broadcast->rb_node, &priv->multicast_tree); - spin_unlock_irqrestore(&priv->lock, flags); - ipoib_mcast_leave(dev, priv->broadcast); - ipoib_mcast_free(priv->broadcast); - priv->broadcast = NULL; - } -} - void ipoib_mcast_restart_task(void *dev_ptr) { struct net_device *dev = dev_ptr; -- GitLab From 59f174faffd5dfee709fa0ead320cc6daf827e93 Mon Sep 17 00:00:00 2001 From: Ishai Rabinovitz Date: Thu, 12 Jan 2006 15:24:51 -0800 Subject: [PATCH 050/465] IB/mthca: Fix memory leak of multicast group structures Convert "/ (1 << lg)" to ">> lg" for a slight code size reduction. add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-24 (-24) function old new delta mthca_map_cmd 613 589 -24 Signed-off-by: Ishai Rabinovitz Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index 22ac72bc20c..f69e4896eff 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c @@ -606,7 +606,7 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm, err = -EINVAL; goto out; } - for (i = 0; i < mthca_icm_size(&iter) / (1 << lg); ++i) { + for (i = 0; i < mthca_icm_size(&iter) >> lg; ++i) { if (virt != -1) { pages[nent * 2] = cpu_to_be64(virt); virt += 1 << lg; -- GitLab From 17e2e819517d75f2f3407e59c5f7f6f0ef305d14 Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Thu, 12 Jan 2006 15:35:15 -0800 Subject: [PATCH 051/465] IB/mthca: Fix memory leaks in error handling Fix memory leaks in mthca_create_qp() and mthca_create_srq() error handling. Signed-off-by: Jack Morgenstein Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_provider.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index db35690c91d..484a7e6b7f8 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c @@ -445,8 +445,10 @@ static struct ib_srq *mthca_create_srq(struct ib_pd *pd, if (pd->uobject) { context = to_mucontext(pd->uobject->context); - if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) - return ERR_PTR(-EFAULT); + if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) { + err = -EFAULT; + goto err_free; + } err = mthca_map_user_db(to_mdev(pd->device), &context->uar, context->db_tab, ucmd.db_index, @@ -522,8 +524,10 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd, if (pd->uobject) { context = to_mucontext(pd->uobject->context); - if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) + if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) { + kfree(qp); return ERR_PTR(-EFAULT); + } err = mthca_map_user_db(to_mdev(pd->device), &context->uar, context->db_tab, -- GitLab From c063a06835d3ccfa6c039d3a3869fcf22249c862 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 12 Jan 2006 15:43:58 -0800 Subject: [PATCH 052/465] IB/mthca: Cosmetic: use the ALIGN macro Use the ALIGN macro to simplify some rounding code. Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_cmd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index f69e4896eff..be1791be627 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c @@ -727,8 +727,8 @@ int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status) * system pages needed. */ dev->fw.arbel.fw_pages = - (dev->fw.arbel.fw_pages + (1 << (PAGE_SHIFT - 12)) - 1) >> - (PAGE_SHIFT - 12); + ALIGN(dev->fw.arbel.fw_pages, PAGE_SIZE >> 12) >> + (PAGE_SHIFT - 12); mthca_dbg(dev, "Clear int @ %llx, EQ arm @ %llx, EQ set CI @ %llx\n", (unsigned long long) dev->fw.arbel.clr_int_base, @@ -1445,6 +1445,7 @@ int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages, * pages needed. */ *aux_pages = (*aux_pages + (1 << (PAGE_SHIFT - 12)) - 1) >> (PAGE_SHIFT - 12); + *aux_pages = ALIGN(*aux_pages, PAGE_SIZE >> 12) >> (PAGE_SHIFT - 12); return 0; } -- GitLab From 9eacee2ac624bfa9740d49355dbe6ee88d0cba0a Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 12 Jan 2006 15:55:41 -0800 Subject: [PATCH 053/465] IB/mthca: Initialize grh_present before using it build_mlx_header() was using sqp->ud_header.grh_present before it was initialized by mthca_read_ah(). Furthermore, header->grh_present is set by ib_ud_header_init, so there's no need to set it again in mthca_read_ah(). Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_av.c | 10 ++++++---- drivers/infiniband/hw/mthca/mthca_dev.h | 1 + drivers/infiniband/hw/mthca/mthca_qp.c | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c index 22fdc446f25..a14eed08a0f 100644 --- a/drivers/infiniband/hw/mthca/mthca_av.c +++ b/drivers/infiniband/hw/mthca/mthca_av.c @@ -163,6 +163,11 @@ int mthca_destroy_ah(struct mthca_dev *dev, struct mthca_ah *ah) return 0; } +int mthca_ah_grh_present(struct mthca_ah *ah) +{ + return !!(ah->av->g_slid & 0x80); +} + int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, struct ib_ud_header *header) { @@ -172,8 +177,7 @@ int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, header->lrh.service_level = be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 28; header->lrh.destination_lid = ah->av->dlid; header->lrh.source_lid = cpu_to_be16(ah->av->g_slid & 0x7f); - if (ah->av->g_slid & 0x80) { - header->grh_present = 1; + if (mthca_ah_grh_present(ah)) { header->grh.traffic_class = (be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 20) & 0xff; header->grh.flow_label = @@ -184,8 +188,6 @@ int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, &header->grh.source_gid); memcpy(header->grh.destination_gid.raw, ah->av->dgid, 16); - } else { - header->grh_present = 0; } return 0; diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h index 795b379260b..a104ab041ea 100644 --- a/drivers/infiniband/hw/mthca/mthca_dev.h +++ b/drivers/infiniband/hw/mthca/mthca_dev.h @@ -520,6 +520,7 @@ int mthca_create_ah(struct mthca_dev *dev, int mthca_destroy_ah(struct mthca_dev *dev, struct mthca_ah *ah); int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, struct ib_ud_header *header); +int mthca_ah_grh_present(struct mthca_ah *ah); int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid); int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid); diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 564b6d51c39..fba608ed7df 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -1434,7 +1434,7 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp, u16 pkey; ib_ud_header_init(256, /* assume a MAD */ - sqp->ud_header.grh_present, + mthca_ah_grh_present(to_mah(wr->wr.ud.ah)), &sqp->ud_header); err = mthca_read_ah(dev, to_mah(wr->wr.ud.ah), &sqp->ud_header); -- GitLab From 9e1c72a4e465ceb2c4c6e2dfc0584a59bec5c2c9 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Thu, 12 Jan 2006 14:25:50 -0700 Subject: [PATCH 054/465] [PATCH] Remove bzImage target Since the documentation no longer tells people to 'make bzImage', and with the previous patch nothing more than 'make' is required to get the right bootable images (just like on i386 now), this removes the bzImage -> zImage target redirect on ARCH=powerpc Signed-off-by: Tom Rini Signed-off-by: Paul Mackerras --- arch/powerpc/Makefile | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index d3654a264ef..07b8e15b48f 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -147,9 +147,6 @@ all: $(KBUILD_IMAGE) CPPFLAGS_vmlinux.lds := -Upowerpc -# All the instructions talk about "make bzImage". -bzImage: zImage - BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm uImage .PHONY: $(BOOT_TARGETS) -- GitLab From 43ccf202214067f12af5d7a6e144e18bb35553a9 Mon Sep 17 00:00:00 2001 From: Dave C Boutcher Date: Thu, 12 Jan 2006 16:05:35 -0600 Subject: [PATCH 055/465] [PATCH] powerpc: Add some more pSeries hypervisor call constants Adds a few more hypervisor call constants. Signed-off-by: Dave Boutcher Signed-off-by: Paul Mackerras --- include/asm-powerpc/hvcall.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/asm-powerpc/hvcall.h b/include/asm-powerpc/hvcall.h index da7af5a720e..38ca9ad6110 100644 --- a/include/asm-powerpc/hvcall.h +++ b/include/asm-powerpc/hvcall.h @@ -6,7 +6,10 @@ #define H_Success 0 #define H_Busy 1 /* Hardware busy -- retry later */ +#define H_Closed 2 /* Resource closed */ #define H_Constrained 4 /* Resource request constrained to max allowed */ +#define H_InProgress 14 /* Kind of like busy */ +#define H_Continue 18 /* Returned from H_Join on success */ #define H_LongBusyStartRange 9900 /* Start of long busy range */ #define H_LongBusyOrder1msec 9900 /* Long busy, hint that 1msec is a good time to retry */ #define H_LongBusyOrder10msec 9901 /* Long busy, hint that 10msec is a good time to retry */ @@ -114,6 +117,8 @@ #define H_REGISTER_VTERM 0x154 #define H_FREE_VTERM 0x158 #define H_POLL_PENDING 0x1D8 +#define H_JOIN 0x298 +#define H_ENABLE_CRQ 0x2B0 #ifndef __ASSEMBLY__ -- GitLab From 898b5395e915210f41223caa30312994d64cba1d Mon Sep 17 00:00:00 2001 From: Dave C Boutcher Date: Thu, 12 Jan 2006 16:07:17 -0600 Subject: [PATCH 056/465] [PATCH] powerpc: Add/remove/update properties in /proc/device-tree Add support to the proc_device_tree file for removing and updating properties. Remove just removes the proc file, update changes the data pointer within the proc file. The remainder of the device-tree changes occur elsewhere. Signed-off-by: Dave Boutcher Signed-off-by: Paul Mackerras --- fs/proc/proc_devtree.c | 24 ++++++++++++++++++++++++ include/linux/proc_fs.h | 5 +++++ 2 files changed, 29 insertions(+) diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c index fb117b74809..9bdd077d6f5 100644 --- a/fs/proc/proc_devtree.c +++ b/fs/proc/proc_devtree.c @@ -81,6 +81,30 @@ void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop __proc_device_tree_add_prop(pde, prop); } +void proc_device_tree_remove_prop(struct proc_dir_entry *pde, + struct property *prop) +{ + remove_proc_entry(prop->name, pde); +} + +void proc_device_tree_update_prop(struct proc_dir_entry *pde, + struct property *newprop, + struct property *oldprop) +{ + struct proc_dir_entry *ent; + + for (ent = pde->subdir; ent != NULL; ent = ent->next) + if (ent->data == oldprop) + break; + if (ent == NULL) { + printk(KERN_WARNING "device-tree: property \"%s\" " + " does not exist\n", oldprop->name); + } else { + ent->data = newprop; + ent->size = newprop->length; + } +} + /* * Process a node, adding entries for its children and its properties. */ diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 74488e49166..aa6322d4519 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -146,6 +146,11 @@ struct property; extern void proc_device_tree_init(void); extern void proc_device_tree_add_node(struct device_node *, struct proc_dir_entry *); extern void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop); +extern void proc_device_tree_remove_prop(struct proc_dir_entry *pde, + struct property *prop); +extern void proc_device_tree_update_prop(struct proc_dir_entry *pde, + struct property *newprop, + struct property *oldprop); #endif /* CONFIG_PROC_DEVICETREE */ extern struct proc_dir_entry *proc_symlink(const char *, -- GitLab From 088186ded490ced80758200cf8f906ed741df306 Mon Sep 17 00:00:00 2001 From: Dave C Boutcher Date: Thu, 12 Jan 2006 16:08:27 -0600 Subject: [PATCH 057/465] [PATCH] powerpc: Add/remove/update properties in firmware device tree Add support for updating and removing device tree properties. Since we hand out pointers to properties with gay abandon, we can't just free the property storage. Instead we move deleted, or the old copy of an updated property, to a "dead properties" list. Also note, its not feasable to kref device tree properties. we call get_property() all over the kernel in a wild variety of contexts. One consequence of this change is that we now take a read_lock(&devtree_lock) when doing get_property(). Signed-off-by: Dave Boutcher Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom.c | 90 +++++++++++++++++++++++++++++++++++++- include/asm-powerpc/prom.h | 5 +++ 2 files changed, 93 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 02e2115323e..70057b63de2 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -1627,6 +1627,11 @@ static void of_node_release(struct kref *kref) kfree(prop->value); kfree(prop); prop = next; + + if (!prop) { + prop = node->deadprops; + node->deadprops = NULL; + } } kfree(node->intrs); kfree(node->full_name); @@ -1783,13 +1788,16 @@ unsigned char *get_property(struct device_node *np, const char *name, { struct property *pp; + read_lock(&devtree_lock); for (pp = np->properties; pp != 0; pp = pp->next) if (strcmp(pp->name, name) == 0) { if (lenp != 0) *lenp = pp->length; - return pp->value; + break; } - return NULL; + read_unlock(&devtree_lock); + + return pp ? pp->value : NULL; } EXPORT_SYMBOL(get_property); @@ -1823,4 +1831,82 @@ int prom_add_property(struct device_node* np, struct property* prop) return 0; } +/* + * Remove a property from a node. Note that we don't actually + * remove it, since we have given out who-knows-how-many pointers + * to the data using get-property. Instead we just move the property + * to the "dead properties" list, so it won't be found any more. + */ +int prom_remove_property(struct device_node *np, struct property *prop) +{ + struct property **next; + int found = 0; + + write_lock(&devtree_lock); + next = &np->properties; + while (*next) { + if (*next == prop) { + /* found the node */ + *next = prop->next; + prop->next = np->deadprops; + np->deadprops = prop; + found = 1; + break; + } + next = &(*next)->next; + } + write_unlock(&devtree_lock); + + if (!found) + return -ENODEV; + +#ifdef CONFIG_PROC_DEVICETREE + /* try to remove the proc node as well */ + if (np->pde) + proc_device_tree_remove_prop(np->pde, prop); +#endif /* CONFIG_PROC_DEVICETREE */ + + return 0; +} + +/* + * Update a property in a node. Note that we don't actually + * remove it, since we have given out who-knows-how-many pointers + * to the data using get-property. Instead we just move the property + * to the "dead properties" list, and add the new property to the + * property list + */ +int prom_update_property(struct device_node *np, + struct property *newprop, + struct property *oldprop) +{ + struct property **next; + int found = 0; + + write_lock(&devtree_lock); + next = &np->properties; + while (*next) { + if (*next == oldprop) { + /* found the node */ + newprop->next = oldprop->next; + *next = newprop; + oldprop->next = np->deadprops; + np->deadprops = oldprop; + found = 1; + break; + } + next = &(*next)->next; + } + write_unlock(&devtree_lock); + + if (!found) + return -ENODEV; +#ifdef CONFIG_PROC_DEVICETREE + /* try to add to proc as well if it was initialized */ + if (np->pde) + proc_device_tree_update_prop(np->pde, newprop, oldprop); +#endif /* CONFIG_PROC_DEVICETREE */ + + return 0; +} diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 329e9bf6226..25d8d5974d1 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -87,6 +87,7 @@ struct device_node { char *full_name; struct property *properties; + struct property *deadprops; /* removed properties */ struct device_node *parent; struct device_node *child; struct device_node *sibling; @@ -164,6 +165,10 @@ extern int prom_n_size_cells(struct device_node* np); extern int prom_n_intr_cells(struct device_node* np); extern void prom_get_irq_senses(unsigned char *senses, int off, int max); extern int prom_add_property(struct device_node* np, struct property* prop); +extern int prom_remove_property(struct device_node *np, struct property *prop); +extern int prom_update_property(struct device_node *np, + struct property *newprop, + struct property *oldprop); #ifdef CONFIG_PPC32 /* -- GitLab From ecaa8b0ff326920c8a89d748382e1c1d8812676c Mon Sep 17 00:00:00 2001 From: Dave C Boutcher Date: Thu, 12 Jan 2006 16:09:29 -0600 Subject: [PATCH 058/465] [PATCH] powerpc: Add of_find_property function Add an of_find_property function that returns a struct property given a property name. Then change the get_property function to use that routine internally. Signed-off-by: Dave Boutcher Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom.c | 19 +++++++++++++------ include/asm-powerpc/prom.h | 3 +++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 70057b63de2..d50c8df0183 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -1779,12 +1779,8 @@ static int __init prom_reconfig_setup(void) __initcall(prom_reconfig_setup); #endif -/* - * Find a property with a given name for a given node - * and return the value. - */ -unsigned char *get_property(struct device_node *np, const char *name, - int *lenp) +struct property *of_find_property(struct device_node *np, const char *name, + int *lenp) { struct property *pp; @@ -1797,6 +1793,17 @@ unsigned char *get_property(struct device_node *np, const char *name, } read_unlock(&devtree_lock); + return pp; +} + +/* + * Find a property with a given name for a given node + * and return the value. + */ +unsigned char *get_property(struct device_node *np, const char *name, + int *lenp) +{ + struct property *pp = of_find_property(np,name,lenp); return pp ? pp->value : NULL; } EXPORT_SYMBOL(get_property); diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 25d8d5974d1..5b2bd4eefb0 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -136,6 +136,9 @@ extern struct device_node *of_find_all_nodes(struct device_node *prev); extern struct device_node *of_get_parent(const struct device_node *node); extern struct device_node *of_get_next_child(const struct device_node *node, struct device_node *prev); +extern struct property *of_find_property(struct device_node *np, + const char *name, + int *lenp); extern struct device_node *of_node_get(struct device_node *node); extern void of_node_put(struct device_node *node); -- GitLab From 610d91511f99f0a8325ad78fb7259c454b23e65a Mon Sep 17 00:00:00 2001 From: Dave C Boutcher Date: Thu, 12 Jan 2006 16:10:22 -0600 Subject: [PATCH 059/465] [PATCH] powerpc: Add support for changing properties from userspace Add support to reconfigure the device tree through the existing proc filesystem interface. Add "add_property", "remove_property", and "update_property" commands to the existing interface. Signed-off-by: Dave Boutcher Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/reconfig.c | 100 ++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index d8864164dbe..86cfa6ecdcf 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c @@ -350,6 +350,100 @@ static int do_remove_node(char *buf) return rv; } +static char *parse_node(char *buf, size_t bufsize, struct device_node **npp) +{ + char *handle_str; + phandle handle; + *npp = NULL; + + handle_str = buf; + + buf = strchr(buf, ' '); + if (!buf) + return NULL; + *buf = '\0'; + buf++; + + handle = simple_strtoul(handle_str, NULL, 10); + + *npp = of_find_node_by_phandle(handle); + return buf; +} + +static int do_add_property(char *buf, size_t bufsize) +{ + struct property *prop = NULL; + struct device_node *np; + unsigned char *value; + char *name, *end; + int length; + end = buf + bufsize; + buf = parse_node(buf, bufsize, &np); + + if (!np) + return -ENODEV; + + if (parse_next_property(buf, end, &name, &length, &value) == NULL) + return -EINVAL; + + prop = new_property(name, length, value, NULL); + if (!prop) + return -ENOMEM; + + prom_add_property(np, prop); + + return 0; +} + +static int do_remove_property(char *buf, size_t bufsize) +{ + struct device_node *np; + char *tmp; + struct property *prop; + buf = parse_node(buf, bufsize, &np); + + if (!np) + return -ENODEV; + + tmp = strchr(buf,' '); + if (tmp) + *tmp = '\0'; + + if (strlen(buf) == 0) + return -EINVAL; + + prop = of_find_property(np, buf, NULL); + + return prom_remove_property(np, prop); +} + +static int do_update_property(char *buf, size_t bufsize) +{ + struct device_node *np; + unsigned char *value; + char *name, *end; + int length; + struct property *newprop, *oldprop; + buf = parse_node(buf, bufsize, &np); + end = buf + bufsize; + + if (!np) + return -ENODEV; + + if (parse_next_property(buf, end, &name, &length, &value) == NULL) + return -EINVAL; + + newprop = new_property(name, length, value, NULL); + if (!newprop) + return -ENOMEM; + + oldprop = of_find_property(np, name,NULL); + if (!oldprop) + return -ENODEV; + + return prom_update_property(np, newprop, oldprop); +} + /** * ofdt_write - perform operations on the Open Firmware device tree * @@ -392,6 +486,12 @@ static ssize_t ofdt_write(struct file *file, const char __user *buf, size_t coun rv = do_add_node(tmp, count - (tmp - kbuf)); else if (!strcmp(kbuf, "remove_node")) rv = do_remove_node(tmp); + else if (!strcmp(kbuf, "add_property")) + rv = do_add_property(tmp, count - (tmp - kbuf)); + else if (!strcmp(kbuf, "remove_property")) + rv = do_remove_property(tmp, count - (tmp - kbuf)); + else if (!strcmp(kbuf, "update_property")) + rv = do_update_property(tmp, count - (tmp - kbuf)); else rv = -EINVAL; out: -- GitLab From 135f0b17a7a146fa65ccd75704eecf77ee19d587 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Thu, 12 Jan 2006 16:55:58 -0700 Subject: [PATCH 060/465] [PATCH] powerpc/boot: Better use of defaultimage- The following reworks how defaultimage- is used. We default to zImage here and then override it on platforms that need something more (uImage in the future) or less (vmlinux on iSeries). Signed-off-by: Tom Rini Signed-off-by: Paul Mackerras --- arch/powerpc/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 07b8e15b48f..44dd82b791d 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -139,9 +139,9 @@ drivers-$(CONFIG_CPM2) += arch/ppc/8260_io/ drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/ -defaultimage-$(CONFIG_PPC32) := zImage +# Default to zImage, override when needed +defaultimage-y := zImage defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux -defaultimage-$(CONFIG_PPC_PSERIES) := zImage KBUILD_IMAGE := $(defaultimage-y) all: $(KBUILD_IMAGE) -- GitLab From 7e78e5e502d4f220d24c6f738f2fdb078ad33607 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Thu, 12 Jan 2006 21:04:23 -0600 Subject: [PATCH 061/465] [PATCH] powerpc: Updated platforms that use gianfar to match driver The gianfar driver changed how it required MDIO bus and phy id's to be passed to it. Also, it no longer passes the physical address of the MDIO bus. Instead we have a proper platform device. Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras --- arch/ppc/platforms/83xx/mpc834x_sys.c | 10 ++++------ arch/ppc/platforms/85xx/mpc8540_ads.c | 14 ++++++-------- arch/ppc/platforms/85xx/mpc8560_ads.c | 11 ++++------- arch/ppc/platforms/85xx/mpc85xx_cds_common.c | 16 ++++++++-------- arch/ppc/platforms/85xx/sbc8560.c | 10 ++++------ arch/ppc/platforms/85xx/stx_gp3.c | 10 ++++------ arch/ppc/platforms/85xx/tqm85xx.c | 16 ++++++---------- arch/ppc/syslib/mpc83xx_devices.c | 10 ++++++++-- arch/ppc/syslib/mpc85xx_devices.c | 10 ++++++++-- 9 files changed, 52 insertions(+), 55 deletions(-) diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c index 04bdc39bf47..012e1e652c0 100644 --- a/arch/ppc/platforms/83xx/mpc834x_sys.c +++ b/arch/ppc/platforms/83xx/mpc834x_sys.c @@ -51,9 +51,6 @@ #include -static const char *GFAR_PHY_0 = "phy0:0"; -static const char *GFAR_PHY_1 = "phy0:1"; - #ifndef CONFIG_PCI unsigned long isa_io_base = 0; unsigned long isa_mem_base = 0; @@ -129,20 +126,21 @@ mpc834x_sys_setup_arch(void) mdata->irq[1] = MPC83xx_IRQ_EXT2; mdata->irq[2] = -1; mdata->irq[31] = -1; - mdata->paddr += binfo->bi_immr_base; /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC1); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->bus_id = GFAR_PHY_0; + pdata->bus_id = 0; + pdata->phy_id = 0; memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); } pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC2); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->bus_id = GFAR_PHY_1; + pdata->bus_id = 0; + pdata->phy_id = 1; memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); } diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c index c5cde97c6ef..2eceb1e6f4e 100644 --- a/arch/ppc/platforms/85xx/mpc8540_ads.c +++ b/arch/ppc/platforms/85xx/mpc8540_ads.c @@ -52,10 +52,6 @@ #include -static const char *GFAR_PHY_0 = "phy0:0"; -static const char *GFAR_PHY_1 = "phy0:1"; -static const char *GFAR_PHY_3 = "phy0:3"; - /* ************************************************************************ * * Setup the architecture @@ -102,27 +98,29 @@ mpc8540ads_setup_arch(void) mdata->irq[2] = -1; mdata->irq[3] = MPC85xx_IRQ_EXT5; mdata->irq[31] = -1; - mdata->paddr += binfo->bi_immr_base; /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->bus_id = GFAR_PHY_0; + pdata->bus_id = 0; + pdata->phy_id = 0; memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); } pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->bus_id = GFAR_PHY_1; + pdata->bus_id = 0; + pdata->phy_id = 1; memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); } pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_FEC); if (pdata) { pdata->board_flags = 0; - pdata->bus_id = GFAR_PHY_3; + pdata->bus_id = 0; + pdata->phy_id = 3; memcpy(pdata->mac_addr, binfo->bi_enet2addr, 6); } diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c index 8e39a551709..442c7ff195d 100644 --- a/arch/ppc/platforms/85xx/mpc8560_ads.c +++ b/arch/ppc/platforms/85xx/mpc8560_ads.c @@ -56,10 +56,6 @@ #include -static const char *GFAR_PHY_0 = "phy0:0"; -static const char *GFAR_PHY_1 = "phy0:1"; -static const char *GFAR_PHY_3 = "phy0:3"; - /* ************************************************************************ * * Setup the architecture @@ -99,20 +95,21 @@ mpc8560ads_setup_arch(void) mdata->irq[2] = -1; mdata->irq[3] = MPC85xx_IRQ_EXT5; mdata->irq[31] = -1; - mdata->paddr += binfo->bi_immr_base; /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->bus_id = GFAR_PHY_0; + pdata->bus_id = 0; + pdata->phy_id = 0; memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); } pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->bus_id = GFAR_PHY_1; + pdata->bus_id = 0; + pdata->phy_id = 1; memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); } diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c index 2959e3c4083..b332ebae6bd 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c @@ -395,9 +395,6 @@ mpc85xx_cds_pcibios_fixup(void) TODC_ALLOC(); -static const char *GFAR_PHY_0 = "phy0:0"; -static const char *GFAR_PHY_1 = "phy0:1"; - /* ************************************************************************ * * Setup the architecture @@ -461,34 +458,37 @@ mpc85xx_cds_setup_arch(void) mdata->irq[2] = -1; mdata->irq[3] = -1; mdata->irq[31] = -1; - mdata->paddr += binfo->bi_immr_base; /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->bus_id = GFAR_PHY_0; + pdata->bus_id = 0; + pdata->phy_id = 0; memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); } pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->bus_id = GFAR_PHY_1; + pdata->bus_id = 0; + pdata->phy_id = 1; memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); } pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_eTSEC1); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->bus_id = GFAR_PHY_0; + pdata->bus_id = 0; + pdata->phy_id = 0; memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); } pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_eTSEC2); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->bus_id = GFAR_PHY_1; + pdata->bus_id = 0; + pdata->phy_id = 1; memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); } diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c index 45a5b81b4ed..e777ba824aa 100644 --- a/arch/ppc/platforms/85xx/sbc8560.c +++ b/arch/ppc/platforms/85xx/sbc8560.c @@ -91,9 +91,6 @@ sbc8560_early_serial_map(void) } #endif -static const char *GFAR_PHY_25 = "phy0:25"; -static const char *GFAR_PHY_26 = "phy0:26"; - /* ************************************************************************ * * Setup the architecture @@ -136,20 +133,21 @@ sbc8560_setup_arch(void) mdata->irq[25] = MPC85xx_IRQ_EXT6; mdata->irq[26] = MPC85xx_IRQ_EXT7; mdata->irq[31] = -1; - mdata->paddr += binfo->bi_immr_base; /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->bus_id = GFAR_PHY_25; + pdata->bus_id = 0; + pdata->phy_id = 25; memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); } pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->bus_id = GFAR_PHY_26; + pdata->bus_id = 0; + pdata->phy_id = 26; memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); } diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c index 15ce9d07063..061bb7cf2d9 100644 --- a/arch/ppc/platforms/85xx/stx_gp3.c +++ b/arch/ppc/platforms/85xx/stx_gp3.c @@ -93,9 +93,6 @@ static u8 gp3_openpic_initsenses[] __initdata = { 0x0, /* External 11: */ }; -static const char *GFAR_PHY_2 = "phy0:2"; -static const char *GFAR_PHY_4 = "phy0:4"; - /* * Setup the architecture */ @@ -130,20 +127,21 @@ gp3_setup_arch(void) mdata->irq[2] = MPC85xx_IRQ_EXT5; mdata->irq[4] = MPC85xx_IRQ_EXT5; mdata->irq[31] = -1; - mdata->paddr += binfo->bi_immr_base; /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); if (pdata) { /* pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */ - pdata->bus_id = GFAR_PHY_2; + pdata->bus_id = 0; + pdata->phy_id = 2; memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); } pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); if (pdata) { /* pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */ - pdata->bus_id = GFAR_PHY_4; + pdata->bus_id = 0; + pdata->phy_id = 4; memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); } diff --git a/arch/ppc/platforms/85xx/tqm85xx.c b/arch/ppc/platforms/85xx/tqm85xx.c index c6dfd8f0f9d..b436f4d0a3f 100644 --- a/arch/ppc/platforms/85xx/tqm85xx.c +++ b/arch/ppc/platforms/85xx/tqm85xx.c @@ -91,12 +91,6 @@ static u_char tqm85xx_openpic_initsenses[] __initdata = { 0x0, /* External 11: */ }; -static const char *GFAR_PHY_0 = "phy0:2"; -static const char *GFAR_PHY_1 = "phy0:1"; -#ifdef CONFIG_MPC8540 -static const char *GFAR_PHY_3 = "phy0:3"; -#endif - /* ************************************************************************ * * Setup the architecture @@ -149,20 +143,21 @@ tqm85xx_setup_arch(void) mdata->irq[2] = -1; mdata->irq[3] = MPC85xx_IRQ_EXT8; mdata->irq[31] = -1; - mdata->paddr += binfo->bi_immr_base; /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->bus_id = GFAR_PHY_0; + pdata->bus_id = 0; + pdata->phy_id = 2; memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); } pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->bus_id = GFAR_PHY_1; + pdata->bus_id = 0; + pdata->phy_id = 1; memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); } @@ -170,7 +165,8 @@ tqm85xx_setup_arch(void) pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_FEC); if (pdata) { pdata->board_flags = 0; - pdata->bus_id = GFAR_PHY_3; + pdata->bus_id = 0; + pdata->phy_id = 3; memcpy(pdata->mac_addr, binfo->bi_enet2addr, 6); } #endif diff --git a/arch/ppc/syslib/mpc83xx_devices.c b/arch/ppc/syslib/mpc83xx_devices.c index 847df440998..f9b95de70e2 100644 --- a/arch/ppc/syslib/mpc83xx_devices.c +++ b/arch/ppc/syslib/mpc83xx_devices.c @@ -28,7 +28,6 @@ */ struct gianfar_mdio_data mpc83xx_mdio_pdata = { - .paddr = 0x24520, }; static struct gianfar_platform_data mpc83xx_tsec1_pdata = { @@ -226,7 +225,14 @@ struct platform_device ppc_sys_platform_devices[] = { .name = "fsl-gianfar_mdio", .id = 0, .dev.platform_data = &mpc83xx_mdio_pdata, - .num_resources = 0, + .num_resources = 1, + .resource = (struct resource[]) { + { + .start = 0x24520, + .end = 0x2453f, + .flags = IORESOURCE_MEM, + }, + }, }, }; diff --git a/arch/ppc/syslib/mpc85xx_devices.c b/arch/ppc/syslib/mpc85xx_devices.c index 69949d25565..00e9b6ff2f6 100644 --- a/arch/ppc/syslib/mpc85xx_devices.c +++ b/arch/ppc/syslib/mpc85xx_devices.c @@ -26,7 +26,6 @@ * what CCSRBAR is, will get fixed up by mach_mpc85xx_fixup */ struct gianfar_mdio_data mpc85xx_mdio_pdata = { - .paddr = MPC85xx_MIIM_OFFSET, }; static struct gianfar_platform_data mpc85xx_tsec1_pdata = { @@ -720,7 +719,14 @@ struct platform_device ppc_sys_platform_devices[] = { .name = "fsl-gianfar_mdio", .id = 0, .dev.platform_data = &mpc85xx_mdio_pdata, - .num_resources = 0, + .num_resources = 1, + .resource = (struct resource[]) { + { + .start = 0x24520, + .end = 0x2453f, + .flags = IORESOURCE_MEM, + }, + }, }, }; -- GitLab From e58c3495e6007af59382540bb21ee941e470d88d Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 13 Jan 2006 14:56:25 +1100 Subject: [PATCH 062/465] [PATCH] powerpc: Cleanup LOADADDR etc. asm macros This patch consolidates the variety of macros used for loading 32 or 64-bit constants in assembler (LOADADDR, LOADBASE, SET_REG_TO_*). The idea is to make the set of macros consistent across 32 and 64 bit and to make it more obvious which is the appropriate one to use in a given situation. The new macros and their semantics are described in the comments in ppc_asm.h. In the process, we change several places that were unnecessarily using immediate loads on ppc64 to use the GOT/TOC. Likewise we cleanup a couple of places where we were clumsily subtracting PAGE_OFFSET with asm instructions to use assemble-time arithmetic or the toreal() macro instead. Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/cpu_setup_power4.S | 4 +- arch/powerpc/kernel/entry_32.S | 2 +- arch/powerpc/kernel/entry_64.S | 12 ++-- arch/powerpc/kernel/fpu.S | 10 +-- arch/powerpc/kernel/head_64.S | 87 +++++++++++++------------- arch/powerpc/kernel/idle_power4.S | 8 +-- arch/powerpc/kernel/misc_32.S | 4 +- arch/powerpc/kernel/misc_64.S | 10 +-- include/asm-powerpc/ppc_asm.h | 76 +++++++++++----------- 9 files changed, 108 insertions(+), 105 deletions(-) diff --git a/arch/powerpc/kernel/cpu_setup_power4.S b/arch/powerpc/kernel/cpu_setup_power4.S index cca942fe611..b61d86e7ceb 100644 --- a/arch/powerpc/kernel/cpu_setup_power4.S +++ b/arch/powerpc/kernel/cpu_setup_power4.S @@ -130,7 +130,7 @@ _GLOBAL(__save_cpu_setup) mfcr r7 /* Get storage ptr */ - LOADADDR(r5,cpu_state_storage) + LOAD_REG_IMMEDIATE(r5,cpu_state_storage) /* We only deal with 970 for now */ mfspr r0,SPRN_PVR @@ -164,7 +164,7 @@ _GLOBAL(__restore_cpu_setup) /* Get storage ptr (FIXME when using anton reloc as we * are running with translation disabled here */ - LOADADDR(r5,cpu_state_storage) + LOAD_REG_IMMEDIATE(r5,cpu_state_storage) /* We only deal with 970 for now */ mfspr r0,SPRN_PVR diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 036b71d2adf..d8da2a35c0a 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -988,7 +988,7 @@ _GLOBAL(enter_rtas) stwu r1,-INT_FRAME_SIZE(r1) mflr r0 stw r0,INT_FRAME_SIZE+4(r1) - LOADADDR(r4, rtas) + LOAD_REG_ADDR(r4, rtas) lis r6,1f@ha /* physical return address for rtas */ addi r6,r6,1f@l tophys(r6,r6) diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index aacebb33e98..4ba81e1b6bf 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -689,9 +689,8 @@ _GLOBAL(enter_rtas) std r6,PACASAVEDMSR(r13) /* Setup our real return addr */ - SET_REG_TO_LABEL(r4,.rtas_return_loc) - SET_REG_TO_CONST(r9,PAGE_OFFSET) - sub r4,r4,r9 + LOAD_REG_ADDR(r4,.rtas_return_loc) + clrldi r4,r4,2 /* convert to realmode address */ mtlr r4 li r0,0 @@ -706,7 +705,7 @@ _GLOBAL(enter_rtas) sync /* disable interrupts so SRR0/1 */ mtmsrd r0 /* don't get trashed */ - SET_REG_TO_LABEL(r4,rtas) + LOAD_REG_ADDR(r4, rtas) ld r5,RTASENTRY(r4) /* get the rtas->entry value */ ld r4,RTASBASE(r4) /* get the rtas->base value */ @@ -718,8 +717,7 @@ _GLOBAL(enter_rtas) _STATIC(rtas_return_loc) /* relocation is off at this point */ mfspr r4,SPRN_SPRG3 /* Get PACA */ - SET_REG_TO_CONST(r5, PAGE_OFFSET) - sub r4,r4,r5 /* RELOC the PACA base pointer */ + clrldi r4,r4,2 /* convert to realmode address */ mfmsr r6 li r0,MSR_RI @@ -728,7 +726,7 @@ _STATIC(rtas_return_loc) mtmsrd r6 ld r1,PACAR1(r4) /* Restore our SP */ - LOADADDR(r3,.rtas_restore_regs) + LOAD_REG_IMMEDIATE(r3,.rtas_restore_regs) ld r4,PACASAVEDMSR(r4) /* Restore our MSR */ mtspr SPRN_SRR0,r3 diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S index b780b42c95f..e4362dfa37f 100644 --- a/arch/powerpc/kernel/fpu.S +++ b/arch/powerpc/kernel/fpu.S @@ -39,9 +39,9 @@ _GLOBAL(load_up_fpu) * to another. Instead we call giveup_fpu in switch_to. */ #ifndef CONFIG_SMP - LOADBASE(r3, last_task_used_math) + LOAD_REG_ADDRBASE(r3, last_task_used_math) toreal(r3) - PPC_LL r4,OFF(last_task_used_math)(r3) + PPC_LL r4,ADDROFF(last_task_used_math)(r3) PPC_LCMPI 0,r4,0 beq 1f toreal(r4) @@ -77,7 +77,7 @@ _GLOBAL(load_up_fpu) #ifndef CONFIG_SMP subi r4,r5,THREAD fromreal(r4) - PPC_STL r4,OFF(last_task_used_math)(r3) + PPC_STL r4,ADDROFF(last_task_used_math)(r3) #endif /* CONFIG_SMP */ /* restore registers and return */ /* we haven't used ctr or xer or lr */ @@ -113,8 +113,8 @@ _GLOBAL(giveup_fpu) 1: #ifndef CONFIG_SMP li r5,0 - LOADBASE(r4,last_task_used_math) - PPC_STL r5,OFF(last_task_used_math)(r4) + LOAD_REG_ADDRBASE(r4,last_task_used_math) + PPC_STL r5,ADDROFF(last_task_used_math)(r4) #endif /* CONFIG_SMP */ blr diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 1c066d12537..b3718f3eb7b 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -154,12 +154,12 @@ _GLOBAL(__secondary_hold) bne 100b #ifdef CONFIG_HMT - LOADADDR(r4, .hmt_init) + SET_REG_IMMEDIATE(r4, .hmt_init) mtctr r4 bctr #else #ifdef CONFIG_SMP - LOADADDR(r4, .pSeries_secondary_smp_init) + LOAD_REG_IMMEDIATE(r4, .pSeries_secondary_smp_init) mtctr r4 mr r3,r24 bctr @@ -205,9 +205,10 @@ exception_marker: #define EX_LR 72 /* - * We're short on space and time in the exception prolog, so we can't use - * the normal LOADADDR macro. Normally we just need the low halfword of the - * address, but for Kdump we need the whole low word. + * We're short on space and time in the exception prolog, so we can't + * use the normal SET_REG_IMMEDIATE macro. Normally we just need the + * low halfword of the address, but for Kdump we need the whole low + * word. */ #ifdef CONFIG_CRASH_DUMP #define LOAD_HANDLER(reg, label) \ @@ -713,7 +714,7 @@ system_reset_iSeries: lbz r23,PACAPROCSTART(r13) /* Test if this processor * should start */ sync - LOADADDR(r3,current_set) + LOAD_REG_IMMEDIATE(r3,current_set) sldi r28,r24,3 /* get current_set[cpu#] */ ldx r3,r3,r28 addi r1,r3,THREAD_SIZE @@ -746,8 +747,8 @@ iSeries_secondary_smp_loop: decrementer_iSeries_masked: li r11,1 stb r11,PACALPPACA+LPPACADECRINT(r13) - LOADBASE(r12,tb_ticks_per_jiffy) - lwz r12,OFF(tb_ticks_per_jiffy)(r12) + LOAD_REG_ADDRBASE(r12,tb_ticks_per_jiffy) + lwz r12,ADDROFF(tb_ticks_per_jiffy)(r12) mtspr SPRN_DEC,r12 /* fall through */ @@ -1412,7 +1413,7 @@ _GLOBAL(pSeries_secondary_smp_init) * physical cpu id in r24, we need to search the pacas to find * which logical id maps to our physical one. */ - LOADADDR(r13, paca) /* Get base vaddr of paca array */ + LOAD_REG_IMMEDIATE(r13, paca) /* Get base vaddr of paca array */ li r5,0 /* logical cpu id */ 1: lhz r6,PACAHWCPUID(r13) /* Load HW procid from paca */ cmpw r6,r24 /* Compare to our id */ @@ -1446,8 +1447,8 @@ _GLOBAL(pSeries_secondary_smp_init) #ifdef CONFIG_PPC_ISERIES _STATIC(__start_initialization_iSeries) /* Clear out the BSS */ - LOADADDR(r11,__bss_stop) - LOADADDR(r8,__bss_start) + LOAD_REG_IMMEDIATE(r11,__bss_stop) + LOAD_REG_IMMEDIATE(r8,__bss_start) sub r11,r11,r8 /* bss size */ addi r11,r11,7 /* round up to an even double word */ rldicl. r11,r11,61,3 /* shift right by 3 */ @@ -1458,17 +1459,17 @@ _STATIC(__start_initialization_iSeries) 3: stdu r0,8(r8) bdnz 3b 4: - LOADADDR(r1,init_thread_union) + LOAD_REG_IMMEDIATE(r1,init_thread_union) addi r1,r1,THREAD_SIZE li r0,0 stdu r0,-STACK_FRAME_OVERHEAD(r1) - LOADADDR(r3,cpu_specs) - LOADADDR(r4,cur_cpu_spec) + LOAD_REG_IMMEDIATE(r3,cpu_specs) + LOAD_REG_IMMEDIATE(r4,cur_cpu_spec) li r5,0 bl .identify_cpu - LOADADDR(r2,__toc_start) + LOAD_REG_IMMEDIATE(r2,__toc_start) addi r2,r2,0x4000 addi r2,r2,0x4000 @@ -1528,7 +1529,7 @@ _GLOBAL(__start_initialization_multiplatform) li r24,0 /* Switch off MMU if not already */ - LOADADDR(r4, .__after_prom_start - KERNELBASE) + LOAD_REG_IMMEDIATE(r4, .__after_prom_start - KERNELBASE) add r4,r4,r30 bl .__mmu_off b .__after_prom_start @@ -1548,7 +1549,7 @@ _STATIC(__boot_from_prom) /* put a relocation offset into r3 */ bl .reloc_offset - LOADADDR(r2,__toc_start) + LOAD_REG_IMMEDIATE(r2,__toc_start) addi r2,r2,0x4000 addi r2,r2,0x4000 @@ -1588,9 +1589,9 @@ _STATIC(__after_prom_start) */ bl .reloc_offset mr r26,r3 - SET_REG_TO_CONST(r27,KERNELBASE) + LOAD_REG_IMMEDIATE(r27, KERNELBASE) - LOADADDR(r3, PHYSICAL_START) /* target addr */ + LOAD_REG_IMMEDIATE(r3, PHYSICAL_START) /* target addr */ // XXX FIXME: Use phys returned by OF (r30) add r4,r27,r26 /* source addr */ @@ -1598,7 +1599,7 @@ _STATIC(__after_prom_start) /* i.e. where we are running */ /* the source addr */ - LOADADDR(r5,copy_to_here) /* # bytes of memory to copy */ + LOAD_REG_IMMEDIATE(r5,copy_to_here) /* # bytes of memory to copy */ sub r5,r5,r27 li r6,0x100 /* Start offset, the first 0x100 */ @@ -1608,11 +1609,11 @@ _STATIC(__after_prom_start) /* this includes the code being */ /* executed here. */ - LOADADDR(r0, 4f) /* Jump to the copy of this code */ + LOAD_REG_IMMEDIATE(r0, 4f) /* Jump to the copy of this code */ mtctr r0 /* that we just made/relocated */ bctr -4: LOADADDR(r5,klimit) +4: LOAD_REG_IMMEDIATE(r5,klimit) add r5,r5,r26 ld r5,0(r5) /* get the value of klimit */ sub r5,r5,r27 @@ -1694,7 +1695,7 @@ _GLOBAL(pmac_secondary_start) mtmsrd r3 /* RI on */ /* Set up a paca value for this processor. */ - LOADADDR(r4, paca) /* Get base vaddr of paca array */ + LOAD_REG_IMMEDIATE(r4, paca) /* Get base vaddr of paca array */ mulli r13,r24,PACA_SIZE /* Calculate vaddr of right paca */ add r13,r13,r4 /* for this processor. */ mtspr SPRN_SPRG3,r13 /* Save vaddr of paca in SPRG3 */ @@ -1731,7 +1732,7 @@ _GLOBAL(__secondary_start) bl .early_setup_secondary /* Initialize the kernel stack. Just a repeat for iSeries. */ - LOADADDR(r3,current_set) + LOAD_REG_ADDR(r3, current_set) sldi r28,r24,3 /* get current_set[cpu#] */ ldx r1,r3,r28 addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD @@ -1742,8 +1743,8 @@ _GLOBAL(__secondary_start) mtlr r7 /* enable MMU and jump to start_secondary */ - LOADADDR(r3,.start_secondary_prolog) - SET_REG_TO_CONST(r4, MSR_KERNEL) + LOAD_REG_ADDR(r3, .start_secondary_prolog) + LOAD_REG_IMMEDIATE(r4, MSR_KERNEL) #ifdef DO_SOFT_DISABLE ori r4,r4,MSR_EE #endif @@ -1792,8 +1793,8 @@ _STATIC(start_here_multiplatform) * be detached from the kernel completely. Besides, we need * to clear it now for kexec-style entry. */ - LOADADDR(r11,__bss_stop) - LOADADDR(r8,__bss_start) + LOAD_REG_IMMEDIATE(r11,__bss_stop) + LOAD_REG_IMMEDIATE(r8,__bss_start) sub r11,r11,r8 /* bss size */ addi r11,r11,7 /* round up to an even double word */ rldicl. r11,r11,61,3 /* shift right by 3 */ @@ -1831,7 +1832,7 @@ _STATIC(start_here_multiplatform) /* up the htab. This is done because we have relocated the */ /* kernel but are still running in real mode. */ - LOADADDR(r3,init_thread_union) + LOAD_REG_IMMEDIATE(r3,init_thread_union) add r3,r3,r26 /* set up a stack pointer (physical address) */ @@ -1840,14 +1841,14 @@ _STATIC(start_here_multiplatform) stdu r0,-STACK_FRAME_OVERHEAD(r1) /* set up the TOC (physical address) */ - LOADADDR(r2,__toc_start) + LOAD_REG_IMMEDIATE(r2,__toc_start) addi r2,r2,0x4000 addi r2,r2,0x4000 add r2,r2,r26 - LOADADDR(r3,cpu_specs) + LOAD_REG_IMMEDIATE(r3, cpu_specs) add r3,r3,r26 - LOADADDR(r4,cur_cpu_spec) + LOAD_REG_IMMEDIATE(r4,cur_cpu_spec) add r4,r4,r26 mr r5,r26 bl .identify_cpu @@ -1863,11 +1864,11 @@ _STATIC(start_here_multiplatform) * nowhere it can be initialized differently before we reach this * code */ - LOADADDR(r27, boot_cpuid) + LOAD_REG_IMMEDIATE(r27, boot_cpuid) add r27,r27,r26 lwz r27,0(r27) - LOADADDR(r24, paca) /* Get base vaddr of paca array */ + LOAD_REG_IMMEDIATE(r24, paca) /* Get base vaddr of paca array */ mulli r13,r27,PACA_SIZE /* Calculate vaddr of right paca */ add r13,r13,r24 /* for this processor. */ add r13,r13,r26 /* convert to physical addr */ @@ -1880,8 +1881,8 @@ _STATIC(start_here_multiplatform) mr r3,r31 bl .early_setup - LOADADDR(r3,.start_here_common) - SET_REG_TO_CONST(r4, MSR_KERNEL) + LOAD_REG_IMMEDIATE(r3, .start_here_common) + LOAD_REG_IMMEDIATE(r4, MSR_KERNEL) mtspr SPRN_SRR0,r3 mtspr SPRN_SRR1,r4 rfid @@ -1895,7 +1896,7 @@ _STATIC(start_here_common) /* The following code sets up the SP and TOC now that we are */ /* running with translation enabled. */ - LOADADDR(r3,init_thread_union) + LOAD_REG_IMMEDIATE(r3,init_thread_union) /* set up the stack */ addi r1,r3,THREAD_SIZE @@ -1908,16 +1909,16 @@ _STATIC(start_here_common) li r3,0 bl .do_cpu_ftr_fixups - LOADADDR(r26, boot_cpuid) + LOAD_REG_IMMEDIATE(r26, boot_cpuid) lwz r26,0(r26) - LOADADDR(r24, paca) /* Get base vaddr of paca array */ + LOAD_REG_IMMEDIATE(r24, paca) /* Get base vaddr of paca array */ mulli r13,r26,PACA_SIZE /* Calculate vaddr of right paca */ add r13,r13,r24 /* for this processor. */ mtspr SPRN_SPRG3,r13 /* ptr to current */ - LOADADDR(r4,init_task) + LOAD_REG_IMMEDIATE(r4, init_task) std r4,PACACURRENT(r13) /* Load the TOC */ @@ -1940,7 +1941,7 @@ _STATIC(start_here_common) _GLOBAL(hmt_init) #ifdef CONFIG_HMT - LOADADDR(r5, hmt_thread_data) + LOAD_REG_IMMEDIATE(r5, hmt_thread_data) mfspr r7,SPRN_PVR srwi r7,r7,16 cmpwi r7,0x34 /* Pulsar */ @@ -1961,7 +1962,7 @@ _GLOBAL(hmt_init) b 101f __hmt_secondary_hold: - LOADADDR(r5, hmt_thread_data) + LOAD_REG_IMMEDIATE(r5, hmt_thread_data) clrldi r5,r5,4 li r7,0 mfspr r6,SPRN_PIR @@ -1989,7 +1990,7 @@ __hmt_secondary_hold: #ifdef CONFIG_HMT _GLOBAL(hmt_start_secondary) - LOADADDR(r4,__hmt_secondary_hold) + LOAD_REG_IMMEDIATE(r4,__hmt_secondary_hold) clrldi r4,r4,4 mtspr SPRN_NIADORM, r4 mfspr r4, SPRN_MSRDORM diff --git a/arch/powerpc/kernel/idle_power4.S b/arch/powerpc/kernel/idle_power4.S index 1494e2f177f..c16b4afab58 100644 --- a/arch/powerpc/kernel/idle_power4.S +++ b/arch/powerpc/kernel/idle_power4.S @@ -38,14 +38,14 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP) /* We must dynamically check for the NAP feature as it * can be cleared by CPU init after the fixups are done */ - LOADBASE(r3,cur_cpu_spec) - ld r4,OFF(cur_cpu_spec)(r3) + LOAD_REG_ADDRBASE(r3,cur_cpu_spec) + ld r4,ADDROFF(cur_cpu_spec)(r3) ld r4,CPU_SPEC_FEATURES(r4) andi. r0,r4,CPU_FTR_CAN_NAP beqlr /* Now check if user or arch enabled NAP mode */ - LOADBASE(r3,powersave_nap) - lwz r4,OFF(powersave_nap)(r3) + LOAD_REG_ADDRBASE(r3,powersave_nap) + lwz r4,ADDROFF(powersave_nap)(r3) cmpwi 0,r4,0 beqlr diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 01d0d97a16e..be982023409 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S @@ -68,7 +68,7 @@ _GLOBAL(reloc_offset) mflr r0 bl 1f 1: mflr r3 - LOADADDR(r4,1b) + LOAD_REG_IMMEDIATE(r4,1b) subf r3,r4,r3 mtlr r0 blr @@ -80,7 +80,7 @@ _GLOBAL(add_reloc_offset) mflr r0 bl 1f 1: mflr r5 - LOADADDR(r4,1b) + LOAD_REG_IMMEDIATE(r4,1b) subf r5,r4,r5 add r3,r3,r5 mtlr r0 diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index ae48a002f81..2778cce058e 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S @@ -39,7 +39,7 @@ _GLOBAL(reloc_offset) mflr r0 bl 1f 1: mflr r3 - LOADADDR(r4,1b) + LOAD_REG_IMMEDIATE(r4,1b) subf r3,r4,r3 mtlr r0 blr @@ -51,7 +51,7 @@ _GLOBAL(add_reloc_offset) mflr r0 bl 1f 1: mflr r5 - LOADADDR(r4,1b) + LOAD_REG_IMMEDIATE(r4,1b) subf r5,r4,r5 add r3,r3,r5 mtlr r0 @@ -498,15 +498,15 @@ _GLOBAL(identify_cpu) */ _GLOBAL(do_cpu_ftr_fixups) /* Get CPU 0 features */ - LOADADDR(r6,cur_cpu_spec) + LOAD_REG_IMMEDIATE(r6,cur_cpu_spec) sub r6,r6,r3 ld r4,0(r6) sub r4,r4,r3 ld r4,CPU_SPEC_FEATURES(r4) /* Get the fixup table */ - LOADADDR(r6,__start___ftr_fixup) + LOAD_REG_IMMEDIATE(r6,__start___ftr_fixup) sub r6,r6,r3 - LOADADDR(r7,__stop___ftr_fixup) + LOAD_REG_IMMEDIATE(r7,__stop___ftr_fixup) sub r7,r7,r3 /* Do the fixup */ 1: cmpld r6,r7 diff --git a/include/asm-powerpc/ppc_asm.h b/include/asm-powerpc/ppc_asm.h index 0dc798d46ea..ab8688d3902 100644 --- a/include/asm-powerpc/ppc_asm.h +++ b/include/asm-powerpc/ppc_asm.h @@ -156,52 +156,56 @@ n: #endif /* - * LOADADDR( rn, name ) - * loads the address of 'name' into 'rn' + * LOAD_REG_IMMEDIATE(rn, expr) + * Loads the value of the constant expression 'expr' into register 'rn' + * using immediate instructions only. Use this when it's important not + * to reference other data (i.e. on ppc64 when the TOC pointer is not + * valid). * - * LOADBASE( rn, name ) - * loads the address (possibly without the low 16 bits) of 'name' into 'rn' - * suitable for base+disp addressing + * LOAD_REG_ADDR(rn, name) + * Loads the address of label 'name' into register 'rn'. Use this when + * you don't particularly need immediate instructions only, but you need + * the whole address in one register (e.g. it's a structure address and + * you want to access various offsets within it). On ppc32 this is + * identical to LOAD_REG_IMMEDIATE. + * + * LOAD_REG_ADDRBASE(rn, name) + * ADDROFF(name) + * LOAD_REG_ADDRBASE loads part of the address of label 'name' into + * register 'rn'. ADDROFF(name) returns the remainder of the address as + * a constant expression. ADDROFF(name) is a signed expression < 16 bits + * in size, so is suitable for use directly as an offset in load and store + * instructions. Use this when loading/storing a single word or less as: + * LOAD_REG_ADDRBASE(rX, name) + * ld rY,ADDROFF(name)(rX) */ #ifdef __powerpc64__ -#define LOADADDR(rn,name) \ - lis rn,name##@highest; \ - ori rn,rn,name##@higher; \ - rldicr rn,rn,32,31; \ - oris rn,rn,name##@h; \ - ori rn,rn,name##@l - -#define LOADBASE(rn,name) \ - ld rn,name@got(r2) - -#define OFF(name) 0 - -#define SET_REG_TO_CONST(reg, value) \ - lis reg,(((value)>>48)&0xFFFF); \ - ori reg,reg,(((value)>>32)&0xFFFF); \ - rldicr reg,reg,32,31; \ - oris reg,reg,(((value)>>16)&0xFFFF); \ - ori reg,reg,((value)&0xFFFF); - -#define SET_REG_TO_LABEL(reg, label) \ - lis reg,(label)@highest; \ - ori reg,reg,(label)@higher; \ - rldicr reg,reg,32,31; \ - oris reg,reg,(label)@h; \ - ori reg,reg,(label)@l; +#define LOAD_REG_IMMEDIATE(reg,expr) \ + lis (reg),(expr)@highest; \ + ori (reg),(reg),(expr)@higher; \ + rldicr (reg),(reg),32,31; \ + oris (reg),(reg),(expr)@h; \ + ori (reg),(reg),(expr)@l; + +#define LOAD_REG_ADDR(reg,name) \ + ld (reg),name@got(r2) + +#define LOAD_REG_ADDRBASE(reg,name) LOAD_REG_ADDR(reg,name) +#define ADDROFF(name) 0 /* offsets for stack frame layout */ #define LRSAVE 16 #else /* 32-bit */ -#define LOADADDR(rn,name) \ - lis rn,name@ha; \ - addi rn,rn,name@l -#define LOADBASE(rn,name) \ - lis rn,name@ha +#define LOAD_REG_IMMEDIATE(reg,expr) \ + lis (reg),(expr)@ha; \ + addi (reg),(reg),(expr)@l; + +#define LOAD_REG_ADDR(reg,name) LOAD_REG_IMMEDIATE(reg, name) -#define OFF(name) name@l +#define LOAD_REG_ADDRBASE(reg, name) lis (reg),name@ha +#define ADDROFF(name) name@l /* offsets for stack frame layout */ #define LRSAVE 4 -- GitLab From 3356bb9f7ba378a6e2709f9df95f4ea52111f4df Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 13 Jan 2006 10:26:42 +1100 Subject: [PATCH 063/465] [PATCH] powerpc: Remove lppaca structure from the PACA At present the lppaca - the structure shared with the iSeries hypervisor and phyp - is contained within the PACA, our own low-level per-cpu structure. This doesn't have to be so, the patch below removes it, making a separate array of lppaca structures. This saves approximately 500*NR_CPUS bytes of image size and kernel memory, because we don't need aligning gap between the Linux and hypervisor portions of every PACA. On the other hand it means an extra level of dereference in many accesses to the lppaca. The patch also gets rid of several places where we assign the paca address to a local variable for no particular reason. Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/asm-offsets.c | 2 +- arch/powerpc/kernel/entry_64.S | 3 ++- arch/powerpc/kernel/head_64.S | 25 +++++++++++------- arch/powerpc/kernel/irq.c | 12 +++------ arch/powerpc/kernel/lparcfg.c | 13 ++++------ arch/powerpc/kernel/paca.c | 36 +++++++++++++++++--------- arch/powerpc/kernel/time.c | 2 +- arch/powerpc/lib/locks.c | 8 ++---- arch/powerpc/platforms/iseries/irq.c | 6 ++--- arch/powerpc/platforms/iseries/misc.S | 3 ++- arch/powerpc/platforms/iseries/setup.c | 8 +++--- arch/powerpc/platforms/iseries/smp.c | 2 +- arch/powerpc/platforms/pseries/lpar.c | 4 +-- arch/powerpc/platforms/pseries/setup.c | 20 +++++++------- include/asm-powerpc/lppaca.h | 6 ++++- include/asm-powerpc/paca.h | 14 +--------- include/asm-powerpc/spinlock.h | 2 +- include/asm-powerpc/time.h | 5 ++-- 18 files changed, 84 insertions(+), 87 deletions(-) diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 56399c5c931..840aad43a98 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -135,7 +135,7 @@ int main(void) DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc)); DEFINE(PACA_EXSLB, offsetof(struct paca_struct, exslb)); DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp)); - DEFINE(PACALPPACA, offsetof(struct paca_struct, lppaca)); + DEFINE(PACALPPACAPTR, offsetof(struct paca_struct, lppaca_ptr)); DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0)); diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 4ba81e1b6bf..54203631886 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -511,7 +511,8 @@ restore: cmpdi 0,r5,0 beq 4f /* Check for pending interrupts (iSeries) */ - ld r3,PACALPPACA+LPPACAANYINT(r13) + ld r3,PACALPPACAPTR(r13) + ld r3,LPPACAANYINT(r3) cmpdi r3,0 beq+ 4f /* skip do_IRQ if no interrupts */ diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index b3718f3eb7b..30826846634 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -255,8 +255,9 @@ exception_marker: #define EXCEPTION_PROLOG_ISERIES_2 \ mfmsr r10; \ - ld r11,PACALPPACA+LPPACASRR0(r13); \ - ld r12,PACALPPACA+LPPACASRR1(r13); \ + ld r12,PACALPPACAPTR(r13); \ + ld r11,LPPACASRR0(r12); \ + ld r12,LPPACASRR1(r12); \ ori r10,r10,MSR_RI; \ mtmsrd r10,1 @@ -635,7 +636,8 @@ data_access_slb_iSeries: std r12,PACA_EXSLB+EX_R12(r13) mfspr r10,SPRN_SPRG1 std r10,PACA_EXSLB+EX_R13(r13) - ld r12,PACALPPACA+LPPACASRR1(r13); + ld r12,PACALPPACAPTR(r13) + ld r12,LPPACASRR1(r12) b .slb_miss_realmode STD_EXCEPTION_ISERIES(0x400, instruction_access, PACA_EXGEN) @@ -645,7 +647,8 @@ instruction_access_slb_iSeries: mtspr SPRN_SPRG1,r13 /* save r13 */ mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ std r3,PACA_EXSLB+EX_R3(r13) - ld r3,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ + ld r3,PACALPPACAPTR(r13) + ld r3,LPPACASRR0(r3) /* get SRR0 value */ std r9,PACA_EXSLB+EX_R9(r13) mfcr r9 #ifdef __DISABLED__ @@ -657,7 +660,8 @@ instruction_access_slb_iSeries: std r12,PACA_EXSLB+EX_R12(r13) mfspr r10,SPRN_SPRG1 std r10,PACA_EXSLB+EX_R13(r13) - ld r12,PACALPPACA+LPPACASRR1(r13); + ld r12,PACALPPACAPTR(r13) + ld r12,LPPACASRR1(r12) b .slb_miss_realmode #ifdef __DISABLED__ @@ -746,7 +750,8 @@ iSeries_secondary_smp_loop: .globl decrementer_iSeries_masked decrementer_iSeries_masked: li r11,1 - stb r11,PACALPPACA+LPPACADECRINT(r13) + ld r12,PACALPPACAPTR(r13) + stb r11,LPPACADECRINT(r12) LOAD_REG_ADDRBASE(r12,tb_ticks_per_jiffy) lwz r12,ADDROFF(tb_ticks_per_jiffy)(r12) mtspr SPRN_DEC,r12 @@ -755,8 +760,9 @@ decrementer_iSeries_masked: .globl hardware_interrupt_iSeries_masked hardware_interrupt_iSeries_masked: mtcrf 0x80,r9 /* Restore regs */ - ld r11,PACALPPACA+LPPACASRR0(r13) - ld r12,PACALPPACA+LPPACASRR1(r13) + ld r12,PACALPPACAPTR(r13) + ld r11,LPPACASRR0(r12) + ld r12,LPPACASRR1(r12) mtspr SPRN_SRR0,r11 mtspr SPRN_SRR1,r12 ld r9,PACA_EXGEN+EX_R9(r13) @@ -995,7 +1001,8 @@ _GLOBAL(slb_miss_realmode) ld r3,PACA_EXSLB+EX_R3(r13) lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ #ifdef CONFIG_PPC_ISERIES - ld r11,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ + ld r11,PACALPPACAPTR(r13) + ld r11,LPPACASRR0(r11) /* get SRR0 value */ #endif /* CONFIG_PPC_ISERIES */ mtlr r10 diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 5651032d870..d1fffce86df 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -238,14 +238,10 @@ void do_IRQ(struct pt_regs *regs) irq_exit(); #ifdef CONFIG_PPC_ISERIES - { - struct paca_struct *lpaca = get_paca(); - - if (lpaca->lppaca.int_dword.fields.decr_int) { - lpaca->lppaca.int_dword.fields.decr_int = 0; - /* Signal a fake decrementer interrupt */ - timer_interrupt(regs); - } + if (get_lppaca()->int_dword.fields.decr_int) { + get_lppaca()->int_dword.fields.decr_int = 0; + /* Signal a fake decrementer interrupt */ + timer_interrupt(regs); } #endif } diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index 9dda16ccde7..1ae96a8ed7e 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c @@ -55,15 +55,13 @@ static unsigned long get_purr(void) { unsigned long sum_purr = 0; int cpu; - struct paca_struct *lpaca; for_each_cpu(cpu) { - lpaca = paca + cpu; - sum_purr += lpaca->lppaca.emulated_time_base; + sum_purr += lppaca[cpu].emulated_time_base; #ifdef PURR_DEBUG printk(KERN_INFO "get_purr for cpu (%d) has value (%ld) \n", - cpu, lpaca->lppaca.emulated_time_base); + cpu, lppaca[cpu].emulated_time_base); #endif } return sum_purr; @@ -79,12 +77,11 @@ static int lparcfg_data(struct seq_file *m, void *v) unsigned long pool_id, lp_index; int shared, entitled_capacity, max_entitled_capacity; int processors, max_processors; - struct paca_struct *lpaca = get_paca(); unsigned long purr = get_purr(); seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS); - shared = (int)(lpaca->lppaca_ptr->shared_proc); + shared = (int)(get_lppaca()->shared_proc); seq_printf(m, "serial_number=%c%c%c%c%c%c%c\n", e2a(xItExtVpdPanel.mfgID[2]), e2a(xItExtVpdPanel.mfgID[3]), @@ -402,7 +399,7 @@ static int lparcfg_data(struct seq_file *m, void *v) (h_resource >> 0 * 8) & 0xffff); /* pool related entries are apropriate for shared configs */ - if (paca[0].lppaca.shared_proc) { + if (lppaca[0].shared_proc) { h_pic(&pool_idle_time, &pool_procs); @@ -451,7 +448,7 @@ static int lparcfg_data(struct seq_file *m, void *v) seq_printf(m, "partition_potential_processors=%d\n", partition_potential_processors); - seq_printf(m, "shared_processor_mode=%d\n", paca[0].lppaca.shared_proc); + seq_printf(m, "shared_processor_mode=%d\n", lppaca[0].shared_proc); return 0; } diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c index 999bdd81676..5d1b708086b 100644 --- a/arch/powerpc/kernel/paca.c +++ b/arch/powerpc/kernel/paca.c @@ -25,6 +25,28 @@ * field correctly */ extern unsigned long __toc_start; +/* + * iSeries structure which the hypervisor knows about - this structure + * should not cross a page boundary. The vpa_init/register_vpa call + * is now known to fail if the lppaca structure crosses a page + * boundary. The lppaca is also used on POWER5 pSeries boxes. The + * lppaca is 640 bytes long, and cannot readily change since the + * hypervisor knows its layout, so a 1kB alignment will suffice to + * ensure that it doesn't cross a page boundary. + */ +struct lppaca lppaca[] = { + [0 ... (NR_CPUS-1)] = { + .desc = 0xd397d781, /* "LpPa" */ + .size = sizeof(struct lppaca), + .dyn_proc_status = 2, + .decr_val = 0x00ff0000, + .fpregs_in_use = 1, + .end_of_quantum = 0xfffffffffffffffful, + .slb_count = 64, + .vmxregs_in_use = 0, + }, +}; + /* The Paca is an array with one entry per processor. Each contains an * lppaca, which contains the information shared between the * hypervisor and Linux. @@ -35,27 +57,17 @@ extern unsigned long __toc_start; * processor (not thread). */ #define PACA_INIT_COMMON(number, start, asrr, asrv) \ + .lppaca_ptr = &lppaca[number], \ .lock_token = 0x8000, \ .paca_index = (number), /* Paca Index */ \ .kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL, \ .stab_real = (asrr), /* Real pointer to segment table */ \ .stab_addr = (asrv), /* Virt pointer to segment table */ \ .cpu_start = (start), /* Processor start */ \ - .hw_cpu_id = 0xffff, \ - .lppaca = { \ - .desc = 0xd397d781, /* "LpPa" */ \ - .size = sizeof(struct lppaca), \ - .dyn_proc_status = 2, \ - .decr_val = 0x00ff0000, \ - .fpregs_in_use = 1, \ - .end_of_quantum = 0xfffffffffffffffful, \ - .slb_count = 64, \ - .vmxregs_in_use = 0, \ - }, \ + .hw_cpu_id = 0xffff, #ifdef CONFIG_PPC_ISERIES #define PACA_INIT_ISERIES(number) \ - .lppaca_ptr = &paca[number].lppaca, \ .reg_save_ptr = &iseries_reg_save[number], #define PACA_INIT(number) \ diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 56f50e91bdd..c4a294d657b 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -431,7 +431,7 @@ void timer_interrupt(struct pt_regs * regs) profile_tick(CPU_PROFILING, regs); #ifdef CONFIG_PPC_ISERIES - get_paca()->lppaca.int_dword.fields.decr_int = 0; + get_lppaca()->int_dword.fields.decr_int = 0; #endif while ((ticks = tb_ticks_since(per_cpu(last_jiffy, cpu))) diff --git a/arch/powerpc/lib/locks.c b/arch/powerpc/lib/locks.c index 35bd03c41dd..8362fa272ca 100644 --- a/arch/powerpc/lib/locks.c +++ b/arch/powerpc/lib/locks.c @@ -28,15 +28,13 @@ void __spin_yield(raw_spinlock_t *lock) { unsigned int lock_value, holder_cpu, yield_count; - struct paca_struct *holder_paca; lock_value = lock->slock; if (lock_value == 0) return; holder_cpu = lock_value & 0xffff; BUG_ON(holder_cpu >= NR_CPUS); - holder_paca = &paca[holder_cpu]; - yield_count = holder_paca->lppaca.yield_count; + yield_count = lppaca[holder_cpu].yield_count; if ((yield_count & 1) == 0) return; /* virtual cpu is currently running */ rmb(); @@ -60,15 +58,13 @@ void __rw_yield(raw_rwlock_t *rw) { int lock_value; unsigned int holder_cpu, yield_count; - struct paca_struct *holder_paca; lock_value = rw->lock; if (lock_value >= 0) return; /* no write lock at present */ holder_cpu = lock_value & 0xffff; BUG_ON(holder_cpu >= NR_CPUS); - holder_paca = &paca[holder_cpu]; - yield_count = holder_paca->lppaca.yield_count; + yield_count = lppaca[holder_cpu].yield_count; if ((yield_count & 1) == 0) return; /* virtual cpu is currently running */ rmb(); diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index 83442ea7747..be3fbfc24e6 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c @@ -334,14 +334,12 @@ int __init iSeries_allocate_IRQ(HvBusNumber bus, */ int iSeries_get_irq(struct pt_regs *regs) { - struct paca_struct *lpaca; /* -2 means ignore this interrupt */ int irq = -2; - lpaca = get_paca(); #ifdef CONFIG_SMP - if (lpaca->lppaca.int_dword.fields.ipi_cnt) { - lpaca->lppaca.int_dword.fields.ipi_cnt = 0; + if (get_lppaca()->int_dword.fields.ipi_cnt) { + get_lppaca()->int_dword.fields.ipi_cnt = 0; iSeries_smp_message_recv(regs); } #endif /* CONFIG_SMP */ diff --git a/arch/powerpc/platforms/iseries/misc.S b/arch/powerpc/platforms/iseries/misc.S index dfe7aa1ba09..7641fc7e550 100644 --- a/arch/powerpc/platforms/iseries/misc.S +++ b/arch/powerpc/platforms/iseries/misc.S @@ -44,7 +44,8 @@ _GLOBAL(local_irq_restore) /* Check pending interrupts */ /* A decrementer, IPI or PMC interrupt may have occurred * while we were in the hypervisor (which enables) */ - ld r4,PACALPPACA+LPPACAANYINT(r13) + ld r4,PACALPPACAPTR(r13) + ld r4,LPPACAANYINT(r4) cmpdi r4,0 beqlr diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index c6bbe5c2510..3f8790146b0 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -538,7 +538,7 @@ static unsigned long __init build_iSeries_Memory_Map(void) */ static void __init iSeries_setup_arch(void) { - if (get_paca()->lppaca.shared_proc) { + if (get_lppaca()->shared_proc) { ppc_md.idle_loop = iseries_shared_idle; printk(KERN_INFO "Using shared processor idle loop\n"); } else { @@ -647,7 +647,7 @@ static void yield_shared_processor(void) * The decrementer stops during the yield. Force a fake decrementer * here and let the timer_interrupt code sort out the actual time. */ - get_paca()->lppaca.int_dword.fields.decr_int = 1; + get_lppaca()->int_dword.fields.decr_int = 1; process_iSeries_events(); } @@ -883,7 +883,7 @@ void dt_cpus(struct iseries_flat_dt *dt) pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE); for (i = 0; i < NR_CPUS; i++) { - if (paca[i].lppaca.dyn_proc_status >= 2) + if (lppaca[i].dyn_proc_status >= 2) continue; snprintf(p, 32 - (p - buf), "@%d", i); @@ -891,7 +891,7 @@ void dt_cpus(struct iseries_flat_dt *dt) dt_prop_str(dt, "device_type", "cpu"); - index = paca[i].lppaca.dyn_hv_phys_proc_index; + index = lppaca[i].dyn_hv_phys_proc_index; d = &xIoHriProcessorVpd[index]; dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024); diff --git a/arch/powerpc/platforms/iseries/smp.c b/arch/powerpc/platforms/iseries/smp.c index fcb094ec6ae..6f9d407a709 100644 --- a/arch/powerpc/platforms/iseries/smp.c +++ b/arch/powerpc/platforms/iseries/smp.c @@ -91,7 +91,7 @@ static void smp_iSeries_kick_cpu(int nr) BUG_ON((nr < 0) || (nr >= NR_CPUS)); /* Verify that our partition has a processor nr */ - if (paca[nr].lppaca.dyn_proc_status >= 2) + if (lppaca[nr].dyn_proc_status >= 2) return; /* The processor is currently spinning, waiting diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 1fe445ab78a..8952528d31a 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -254,11 +254,11 @@ out: void vpa_init(int cpu) { int hwcpu = get_hard_smp_processor_id(cpu); - unsigned long vpa = __pa(&paca[cpu].lppaca); + unsigned long vpa = __pa(&lppaca[cpu]); long ret; if (cpu_has_feature(CPU_FTR_ALTIVEC)) - paca[cpu].lppaca.vmxregs_in_use = 1; + lppaca[cpu].vmxregs_in_use = 1; ret = register_vpa(hwcpu, vpa); diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 68b7f086d63..da6cebaf72c 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -190,7 +190,7 @@ static void pseries_lpar_enable_pmcs(void) /* instruct hypervisor to maintain PMCs */ if (firmware_has_feature(FW_FEATURE_SPLPAR)) - get_paca()->lppaca.pmcregs_in_use = 1; + get_lppaca()->pmcregs_in_use = 1; } static void __init pSeries_setup_arch(void) @@ -234,7 +234,7 @@ static void __init pSeries_setup_arch(void) /* Choose an idle loop */ if (firmware_has_feature(FW_FEATURE_SPLPAR)) { vpa_init(boot_cpuid); - if (get_paca()->lppaca.shared_proc) { + if (get_lppaca()->shared_proc) { printk(KERN_INFO "Using shared processor idle loop\n"); ppc_md.idle_loop = pseries_shared_idle; } else { @@ -444,10 +444,10 @@ DECLARE_PER_CPU(unsigned long, smt_snooze_delay); static inline void dedicated_idle_sleep(unsigned int cpu) { - struct paca_struct *ppaca = &paca[cpu ^ 1]; + struct lppaca *plppaca = &lppaca[cpu ^ 1]; /* Only sleep if the other thread is not idle */ - if (!(ppaca->lppaca.idle)) { + if (!(plppaca->idle)) { local_irq_disable(); /* @@ -480,7 +480,6 @@ static inline void dedicated_idle_sleep(unsigned int cpu) static void pseries_dedicated_idle(void) { - struct paca_struct *lpaca = get_paca(); unsigned int cpu = smp_processor_id(); unsigned long start_snooze; unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay); @@ -491,7 +490,7 @@ static void pseries_dedicated_idle(void) * Indicate to the HV that we are idle. Now would be * a good time to find other work to dispatch. */ - lpaca->lppaca.idle = 1; + get_lppaca()->idle = 1; if (!need_resched()) { start_snooze = get_tb() + @@ -518,7 +517,7 @@ static void pseries_dedicated_idle(void) HMT_medium(); } - lpaca->lppaca.idle = 0; + get_lppaca()->idle = 0; ppc64_runlatch_on(); preempt_enable_no_resched(); @@ -532,7 +531,6 @@ static void pseries_dedicated_idle(void) static void pseries_shared_idle(void) { - struct paca_struct *lpaca = get_paca(); unsigned int cpu = smp_processor_id(); while (1) { @@ -540,7 +538,7 @@ static void pseries_shared_idle(void) * Indicate to the HV that we are idle. Now would be * a good time to find other work to dispatch. */ - lpaca->lppaca.idle = 1; + get_lppaca()->idle = 1; while (!need_resched() && !cpu_is_offline(cpu)) { local_irq_disable(); @@ -564,7 +562,7 @@ static void pseries_shared_idle(void) HMT_medium(); } - lpaca->lppaca.idle = 0; + get_lppaca()->idle = 0; ppc64_runlatch_on(); preempt_enable_no_resched(); @@ -588,7 +586,7 @@ static void pseries_kexec_cpu_down(int crash_shutdown, int secondary) { /* Don't risk a hypervisor call if we're crashing */ if (!crash_shutdown) { - unsigned long vpa = __pa(&get_paca()->lppaca); + unsigned long vpa = __pa(get_lppaca()); if (unregister_vpa(hard_smp_processor_id(), vpa)) { printk("VPA deregistration of cpu %u (hw_cpu_id %d) " diff --git a/include/asm-powerpc/lppaca.h b/include/asm-powerpc/lppaca.h index ff82ea7c482..cd9f11f1ef1 100644 --- a/include/asm-powerpc/lppaca.h +++ b/include/asm-powerpc/lppaca.h @@ -29,7 +29,9 @@ //---------------------------------------------------------------------------- #include -struct lppaca { +/* The Hypervisor barfs if the lppaca crosses a page boundary. A 1k + * alignment is sufficient to prevent this */ +struct __attribute__((__aligned__(0x400))) lppaca { //============================================================================= // CACHE_LINE_1 0x0000 - 0x007F Contains read-only data // NOTE: The xDynXyz fields are fields that will be dynamically changed by @@ -129,5 +131,7 @@ struct lppaca { u8 pmc_save_area[256]; // PMC interrupt Area x00-xFF }; +extern struct lppaca lppaca[]; + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_LPPACA_H */ diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h index a64b4d425da..c9add8f1ad9 100644 --- a/include/asm-powerpc/paca.h +++ b/include/asm-powerpc/paca.h @@ -23,6 +23,7 @@ register struct paca_struct *local_paca asm("r13"); #define get_paca() local_paca +#define get_lppaca() (get_paca()->lppaca_ptr) struct task_struct; @@ -95,19 +96,6 @@ struct paca_struct { u64 saved_r1; /* r1 save for RTAS calls */ u64 saved_msr; /* MSR saved here by enter_rtas */ u8 proc_enabled; /* irq soft-enable flag */ - - /* - * iSeries structure which the hypervisor knows about - - * this structure should not cross a page boundary. - * The vpa_init/register_vpa call is now known to fail if the - * lppaca structure crosses a page boundary. - * The lppaca is also used on POWER5 pSeries boxes. - * The lppaca is 640 bytes long, and cannot readily change - * since the hypervisor knows its layout, so a 1kB - * alignment will suffice to ensure that it doesn't - * cross a page boundary. - */ - struct lppaca lppaca __attribute__((__aligned__(0x400))); }; extern struct paca_struct paca[]; diff --git a/include/asm-powerpc/spinlock.h b/include/asm-powerpc/spinlock.h index 754900901cd..26b8744ed52 100644 --- a/include/asm-powerpc/spinlock.h +++ b/include/asm-powerpc/spinlock.h @@ -80,7 +80,7 @@ static int __inline__ __raw_spin_trylock(raw_spinlock_t *lock) #if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES) /* We only yield to the hypervisor if we are in shared processor mode */ -#define SHARED_PROCESSOR (get_paca()->lppaca.shared_proc) +#define SHARED_PROCESSOR (get_lppaca()->shared_proc) extern void __spin_yield(raw_spinlock_t *lock); extern void __rw_yield(raw_rwlock_t *lock); #else /* SPLPAR || ISERIES */ diff --git a/include/asm-powerpc/time.h b/include/asm-powerpc/time.h index d9b86a17271..baddc9ab57a 100644 --- a/include/asm-powerpc/time.h +++ b/include/asm-powerpc/time.h @@ -175,11 +175,10 @@ static inline void set_dec(int val) set_dec_cpu6(val); #else #ifdef CONFIG_PPC_ISERIES - struct paca_struct *lpaca = get_paca(); int cur_dec; - if (lpaca->lppaca.shared_proc) { - lpaca->lppaca.virtual_decr = val; + if (get_lppaca()->shared_proc) { + get_lppaca()->virtual_decr = val; cur_dec = get_dec(); if (cur_dec > val) HvCall_setVirtualDecr(); -- GitLab From 144b9c135b963bcb7f242c7b83bff930620d3161 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Fri, 13 Jan 2006 15:37:17 +1100 Subject: [PATCH 064/465] [PATCH] powerpc: use lwsync in atomics, bitops, lock functions eieio is only a store - store ordering. When used to order an unlock operation loads may leak out of the critical region. This is potentially buggy, one example is if a user wants to atomically read a couple of values. We can solve this with an lwsync which orders everything except store - load. I removed the (now unused) EIEIO_ON_SMP macros and the c versions isync_on_smp and eieio_on_smp now we dont use them. I also removed some old comments that were used to identify inline spinlocks in assembly, they dont make sense now our locks are out of line. Another interesting thing was that read_unlock was using an eieio even though the rest of the spinlock code had already been converted to use lwsync. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- include/asm-powerpc/atomic.h | 20 ++++++++++---------- include/asm-powerpc/bitops.h | 6 +++--- include/asm-powerpc/futex.h | 2 +- include/asm-powerpc/spinlock.h | 19 ++++++++++--------- include/asm-powerpc/synch.h | 23 ++++------------------- include/asm-powerpc/system.h | 8 ++++---- 6 files changed, 32 insertions(+), 46 deletions(-) diff --git a/include/asm-powerpc/atomic.h b/include/asm-powerpc/atomic.h index 248f9aec959..9ce51ba54c1 100644 --- a/include/asm-powerpc/atomic.h +++ b/include/asm-powerpc/atomic.h @@ -36,7 +36,7 @@ static __inline__ int atomic_add_return(int a, atomic_t *v) int t; __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1: lwarx %0,0,%2 # atomic_add_return\n\ add %0,%1,%0\n" PPC405_ERR77(0,%2) @@ -72,7 +72,7 @@ static __inline__ int atomic_sub_return(int a, atomic_t *v) int t; __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1: lwarx %0,0,%2 # atomic_sub_return\n\ subf %0,%1,%0\n" PPC405_ERR77(0,%2) @@ -106,7 +106,7 @@ static __inline__ int atomic_inc_return(atomic_t *v) int t; __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1: lwarx %0,0,%1 # atomic_inc_return\n\ addic %0,%0,1\n" PPC405_ERR77(0,%1) @@ -150,7 +150,7 @@ static __inline__ int atomic_dec_return(atomic_t *v) int t; __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1: lwarx %0,0,%1 # atomic_dec_return\n\ addic %0,%0,-1\n" PPC405_ERR77(0,%1) @@ -204,7 +204,7 @@ static __inline__ int atomic_dec_if_positive(atomic_t *v) int t; __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1: lwarx %0,0,%1 # atomic_dec_if_positive\n\ addic. %0,%0,-1\n\ blt- 2f\n" @@ -253,7 +253,7 @@ static __inline__ long atomic64_add_return(long a, atomic64_t *v) long t; __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1: ldarx %0,0,%2 # atomic64_add_return\n\ add %0,%1,%0\n\ stdcx. %0,0,%2 \n\ @@ -287,7 +287,7 @@ static __inline__ long atomic64_sub_return(long a, atomic64_t *v) long t; __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1: ldarx %0,0,%2 # atomic64_sub_return\n\ subf %0,%1,%0\n\ stdcx. %0,0,%2 \n\ @@ -319,7 +319,7 @@ static __inline__ long atomic64_inc_return(atomic64_t *v) long t; __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1: ldarx %0,0,%1 # atomic64_inc_return\n\ addic %0,%0,1\n\ stdcx. %0,0,%1 \n\ @@ -361,7 +361,7 @@ static __inline__ long atomic64_dec_return(atomic64_t *v) long t; __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1: ldarx %0,0,%1 # atomic64_dec_return\n\ addic %0,%0,-1\n\ stdcx. %0,0,%1\n\ @@ -386,7 +386,7 @@ static __inline__ long atomic64_dec_if_positive(atomic64_t *v) long t; __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1: ldarx %0,0,%1 # atomic64_dec_if_positive\n\ addic. %0,%0,-1\n\ blt- 2f\n\ diff --git a/include/asm-powerpc/bitops.h b/include/asm-powerpc/bitops.h index 1996eaa8aea..bf6941a810b 100644 --- a/include/asm-powerpc/bitops.h +++ b/include/asm-powerpc/bitops.h @@ -112,7 +112,7 @@ static __inline__ int test_and_set_bit(unsigned long nr, unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1:" PPC_LLARX "%0,0,%3 # test_and_set_bit\n" "or %1,%0,%2 \n" PPC405_ERR77(0,%3) @@ -134,7 +134,7 @@ static __inline__ int test_and_clear_bit(unsigned long nr, unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1:" PPC_LLARX "%0,0,%3 # test_and_clear_bit\n" "andc %1,%0,%2 \n" PPC405_ERR77(0,%3) @@ -156,7 +156,7 @@ static __inline__ int test_and_change_bit(unsigned long nr, unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1:" PPC_LLARX "%0,0,%3 # test_and_change_bit\n" "xor %1,%0,%2 \n" PPC405_ERR77(0,%3) diff --git a/include/asm-powerpc/futex.h b/include/asm-powerpc/futex.h index f0319d50b12..39e85f320a7 100644 --- a/include/asm-powerpc/futex.h +++ b/include/asm-powerpc/futex.h @@ -11,7 +11,7 @@ #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ __asm__ __volatile ( \ - SYNC_ON_SMP \ + LWSYNC_ON_SMP \ "1: lwarx %0,0,%2\n" \ insn \ PPC405_ERR77(0, %2) \ diff --git a/include/asm-powerpc/spinlock.h b/include/asm-powerpc/spinlock.h index 26b8744ed52..895cb6d3a42 100644 --- a/include/asm-powerpc/spinlock.h +++ b/include/asm-powerpc/spinlock.h @@ -46,7 +46,7 @@ static __inline__ unsigned long __spin_trylock(raw_spinlock_t *lock) token = LOCK_TOKEN; __asm__ __volatile__( -"1: lwarx %0,0,%2 # __spin_trylock\n\ +"1: lwarx %0,0,%2\n\ cmpwi 0,%0,0\n\ bne- 2f\n\ stwcx. %1,0,%2\n\ @@ -124,8 +124,8 @@ static void __inline__ __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long static __inline__ void __raw_spin_unlock(raw_spinlock_t *lock) { - __asm__ __volatile__(SYNC_ON_SMP" # __raw_spin_unlock" - : : :"memory"); + __asm__ __volatile__("# __raw_spin_unlock\n\t" + LWSYNC_ON_SMP: : :"memory"); lock->slock = 0; } @@ -167,7 +167,7 @@ static long __inline__ __read_trylock(raw_rwlock_t *rw) long tmp; __asm__ __volatile__( -"1: lwarx %0,0,%1 # read_trylock\n" +"1: lwarx %0,0,%1\n" __DO_SIGN_EXTEND " addic. %0,%0,1\n\ ble- 2f\n" @@ -192,7 +192,7 @@ static __inline__ long __write_trylock(raw_rwlock_t *rw) token = WRLOCK_TOKEN; __asm__ __volatile__( -"1: lwarx %0,0,%2 # write_trylock\n\ +"1: lwarx %0,0,%2\n\ cmpwi 0,%0,0\n\ bne- 2f\n" PPC405_ERR77(0,%1) @@ -249,8 +249,9 @@ static void __inline__ __raw_read_unlock(raw_rwlock_t *rw) long tmp; __asm__ __volatile__( - "eieio # read_unlock\n\ -1: lwarx %0,0,%1\n\ + "# read_unlock\n\t" + LWSYNC_ON_SMP +"1: lwarx %0,0,%1\n\ addic %0,%0,-1\n" PPC405_ERR77(0,%1) " stwcx. %0,0,%1\n\ @@ -262,8 +263,8 @@ static void __inline__ __raw_read_unlock(raw_rwlock_t *rw) static __inline__ void __raw_write_unlock(raw_rwlock_t *rw) { - __asm__ __volatile__(SYNC_ON_SMP" # write_unlock" - : : :"memory"); + __asm__ __volatile__("# write_unlock\n\t" + LWSYNC_ON_SMP: : :"memory"); rw->lock = 0; } diff --git a/include/asm-powerpc/synch.h b/include/asm-powerpc/synch.h index 794870ab8fd..c90d9d9aae7 100644 --- a/include/asm-powerpc/synch.h +++ b/include/asm-powerpc/synch.h @@ -2,6 +2,8 @@ #define _ASM_POWERPC_SYNCH_H #ifdef __KERNEL__ +#include + #ifdef __powerpc64__ #define __SUBARCH_HAS_LWSYNC #endif @@ -12,20 +14,12 @@ # define LWSYNC sync #endif - -/* - * Arguably the bitops and *xchg operations don't imply any memory barrier - * or SMP ordering, but in fact a lot of drivers expect them to imply - * both, since they do on x86 cpus. - */ #ifdef CONFIG_SMP -#define EIEIO_ON_SMP "eieio\n" #define ISYNC_ON_SMP "\n\tisync" -#define SYNC_ON_SMP __stringify(LWSYNC) "\n" +#define LWSYNC_ON_SMP __stringify(LWSYNC) "\n" #else -#define EIEIO_ON_SMP #define ISYNC_ON_SMP -#define SYNC_ON_SMP +#define LWSYNC_ON_SMP #endif static inline void eieio(void) @@ -38,14 +32,5 @@ static inline void isync(void) __asm__ __volatile__ ("isync" : : : "memory"); } -#ifdef CONFIG_SMP -#define eieio_on_smp() eieio() -#define isync_on_smp() isync() -#else -#define eieio_on_smp() __asm__ __volatile__("": : :"memory") -#define isync_on_smp() __asm__ __volatile__("": : :"memory") -#endif - #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_SYNCH_H */ - diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h index 9b822afa7d0..d9bf53653b1 100644 --- a/include/asm-powerpc/system.h +++ b/include/asm-powerpc/system.h @@ -212,7 +212,7 @@ __xchg_u32(volatile void *p, unsigned long val) unsigned long prev; __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1: lwarx %0,0,%2 \n" PPC405_ERR77(0,%2) " stwcx. %3,0,%2 \n\ @@ -232,7 +232,7 @@ __xchg_u64(volatile void *p, unsigned long val) unsigned long prev; __asm__ __volatile__( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1: ldarx %0,0,%2 \n" PPC405_ERR77(0,%2) " stdcx. %3,0,%2 \n\ @@ -287,7 +287,7 @@ __cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new) unsigned int prev; __asm__ __volatile__ ( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1: lwarx %0,0,%2 # __cmpxchg_u32\n\ cmpw 0,%0,%3\n\ bne- 2f\n" @@ -311,7 +311,7 @@ __cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new) unsigned long prev; __asm__ __volatile__ ( - EIEIO_ON_SMP + LWSYNC_ON_SMP "1: ldarx %0,0,%2 # __cmpxchg_u64\n\ cmpd 0,%0,%3\n\ bne- 2f\n\ -- GitLab From b11fa580ac06b34944a2b46a44ebce2c284e1a76 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Fri, 13 Jan 2006 16:51:52 +1100 Subject: [PATCH 065/465] [PATCH] powerpc: reformat atomic_add_unless It makes my eyes hurt. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- include/asm-powerpc/atomic.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/include/asm-powerpc/atomic.h b/include/asm-powerpc/atomic.h index 9ce51ba54c1..147a38dcc76 100644 --- a/include/asm-powerpc/atomic.h +++ b/include/asm-powerpc/atomic.h @@ -176,19 +176,19 @@ static __inline__ int atomic_dec_return(atomic_t *v) * Atomically adds @a to @v, so long as it was not @u. * Returns non-zero if @v was not @u, and zero otherwise. */ -#define atomic_add_unless(v, a, u) \ -({ \ - int c, old; \ - c = atomic_read(v); \ - for (;;) { \ - if (unlikely(c == (u))) \ - break; \ - old = atomic_cmpxchg((v), c, c + (a)); \ - if (likely(old == c)) \ - break; \ - c = old; \ - } \ - c != (u); \ +#define atomic_add_unless(v, a, u) \ +({ \ + int c, old; \ + c = atomic_read(v); \ + for (;;) { \ + if (unlikely(c == (u))) \ + break; \ + old = atomic_cmpxchg((v), c, c + (a)); \ + if (likely(old == c)) \ + break; \ + c = old; \ + } \ + c != (u); \ }) #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) -- GitLab From a5ed425cd30c0c2abac4039ae11b38520aa130c2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 13 Jan 2006 14:10:19 -0200 Subject: [PATCH 066/465] V4L/DVB (3355): removed uneeded init on structs like static int foo=0 - Static vars are equal to zero by default. Removed unnecessary =0 from them, saving some data space Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/bt8xx/bt878.c | 2 +- drivers/media/dvb/ttpci/av7110.c | 4 ++-- drivers/media/video/bt832.c | 2 +- drivers/media/video/btcx-risc.c | 2 +- drivers/media/video/bttv-cards.c | 6 ++--- drivers/media/video/bttv-driver.c | 27 +++++++++++----------- drivers/media/video/bttv-i2c.c | 6 ++--- drivers/media/video/cx25840/cx25840-core.c | 2 +- drivers/media/video/cx88/cx88-alsa.c | 4 ++-- drivers/media/video/msp3400-driver.c | 10 ++++---- drivers/media/video/saa7134/saa7134-core.c | 2 +- 11 files changed, 33 insertions(+), 34 deletions(-) diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c index f2957145003..a04bb61f21f 100644 --- a/drivers/media/dvb/bt8xx/bt878.c +++ b/drivers/media/dvb/bt8xx/bt878.c @@ -542,7 +542,7 @@ static struct pci_driver bt878_pci_driver = { .remove = bt878_remove, }; -static int bt878_pci_driver_registered = 0; +static int bt878_pci_driver_registered; /*******************************/ /* Module management functions */ diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 327a8089193..27494901975 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -81,7 +81,7 @@ static int adac = DVB_ADAC_TI; static int hw_sections; static int rgb_on; static int volume = 255; -static int budgetpatch = 0; +static int budgetpatch; module_param_named(debug, av7110_debug, int, 0644); MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)"); @@ -103,7 +103,7 @@ MODULE_PARM_DESC(budgetpatch, "use budget-patch hardware modification: default 0 static void restart_feeds(struct av7110 *av7110); -static int av7110_num = 0; +static int av7110_num; #define FE_FUNC_OVERRIDE(fe_func, av7110_copy, av7110_func) \ {\ diff --git a/drivers/media/video/bt832.c b/drivers/media/video/bt832.c index 07c78f1f7a4..cc54b62f460 100644 --- a/drivers/media/video/bt832.c +++ b/drivers/media/video/bt832.c @@ -43,7 +43,7 @@ static unsigned short normal_i2c[] = { I2C_BT832_ALT1>>1, I2C_BT832_ALT2>>1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; -int debug = 0; /* debug output */ +int debug; /* debug output */ module_param(debug, int, 0644); /* ---------------------------------------------------------------------- */ diff --git a/drivers/media/video/btcx-risc.c b/drivers/media/video/btcx-risc.c index a48de3c0e3f..b4aca724927 100644 --- a/drivers/media/video/btcx-risc.c +++ b/drivers/media/video/btcx-risc.c @@ -37,7 +37,7 @@ MODULE_DESCRIPTION("some code shared by bttv and cx88xx drivers"); MODULE_AUTHOR("Gerd Knorr"); MODULE_LICENSE("GPL"); -static unsigned int debug = 0; +static unsigned int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"debug messages, default is 0 (no)"); diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 65323e78d5f..9749d6ed623 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -92,8 +92,8 @@ static void identify_by_eeprom(struct bttv *btv, static int __devinit pvr_boot(struct bttv *btv); /* config variables */ -static unsigned int triton1=0; -static unsigned int vsfx=0; +static unsigned int triton1; +static unsigned int vsfx; static unsigned int latency = UNSET; int no_overlay=-1; @@ -106,7 +106,7 @@ static struct bttv *master[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = NULL }; #ifdef MODULE static unsigned int autoload = 1; #else -static unsigned int autoload = 0; +static unsigned int autoload; #endif static unsigned int gpiomask = UNSET; static unsigned int audioall = UNSET; diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index 0e697034678..1c6cfe95454 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -48,47 +48,46 @@ unsigned int bttv_num; /* number of Bt848s in use */ struct bttv bttvs[BTTV_MAX]; -unsigned int bttv_debug = 0; +unsigned int bttv_debug; unsigned int bttv_verbose = 1; -unsigned int bttv_gpio = 0; +unsigned int bttv_gpio; /* config variables */ #ifdef __BIG_ENDIAN static unsigned int bigendian=1; #else -static unsigned int bigendian=0; +static unsigned int bigendian; #endif static unsigned int radio[BTTV_MAX]; -static unsigned int irq_debug = 0; +static unsigned int irq_debug; static unsigned int gbuffers = 8; static unsigned int gbufsize = 0x208000; static int video_nr = -1; static int radio_nr = -1; static int vbi_nr = -1; -static int debug_latency = 0; +static int debug_latency; -static unsigned int fdsr = 0; +static unsigned int fdsr; /* options */ -static unsigned int combfilter = 0; -static unsigned int lumafilter = 0; +static unsigned int combfilter; +static unsigned int lumafilter; static unsigned int automute = 1; -static unsigned int chroma_agc = 0; +static unsigned int chroma_agc; static unsigned int adc_crush = 1; static unsigned int whitecrush_upper = 0xCF; static unsigned int whitecrush_lower = 0x7F; -static unsigned int vcr_hack = 0; -static unsigned int irq_iswitch = 0; +static unsigned int vcr_hack; +static unsigned int irq_iswitch; static unsigned int uv_ratio = 50; -static unsigned int full_luma_range = 0; -static unsigned int coring = 0; +static unsigned int full_luma_range; +static unsigned int coring; extern int no_overlay; /* API features (turn on/off stuff for testing) */ static unsigned int v4l2 = 1; - /* insmod args */ module_param(bttv_verbose, int, 0644); module_param(bttv_gpio, int, 0644); diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c index 748d630c7fe..614c1201855 100644 --- a/drivers/media/video/bttv-i2c.c +++ b/drivers/media/video/bttv-i2c.c @@ -41,9 +41,9 @@ static struct i2c_client bttv_i2c_client_template; static int attach_inform(struct i2c_client *client); -static int i2c_debug = 0; -static int i2c_hw = 0; -static int i2c_scan = 0; +static int i2c_debug; +static int i2c_hw; +static int i2c_scan; module_param(i2c_debug, int, 0644); module_param(i2c_hw, int, 0444); module_param(i2c_scan, int, 0444); diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 1d75a42629d..0da744c1d23 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -43,7 +43,7 @@ MODULE_LICENSE("GPL"); static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; -int cx25840_debug = 0; +int cx25840_debug; module_param_named(debug,cx25840_debug, int, 0644); diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index 7695b521eb3..fd8bc718f0e 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c @@ -116,7 +116,7 @@ MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{Conexant,23881}," "{{Conexant,23882}," "{{Conexant,23883}"); -static unsigned int debug = 0; +static unsigned int debug; module_param(debug,int,0644); MODULE_PARM_DESC(debug,"enable debug messages"); @@ -653,7 +653,7 @@ static void snd_cx88_dev_free(snd_card_t * card) * Alsa Constructor - Component probe */ -static int devno=0; +static int devno; static int __devinit snd_cx88_create(snd_card_t *card, struct pci_dev *pci, snd_cx88_card_t **rchip) { diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index 9b05a0ab776..09ff25b554b 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c @@ -66,12 +66,12 @@ MODULE_LICENSE("GPL"); /* module parameters */ static int opmode = OPMODE_AUTO; -int msp_debug = 0; /* msp_debug output */ -int msp_once = 0; /* no continous stereo monitoring */ -int msp_amsound = 0; /* hard-wire AM sound at 6.5 Hz (france), - the autoscan seems work well only with FM... */ +int msp_debug; /* msp_debug output */ +int msp_once; /* no continous stereo monitoring */ +int msp_amsound; /* hard-wire AM sound at 6.5 Hz (france), + the autoscan seems work well only with FM... */ int msp_standard = 1; /* Override auto detect of audio msp_standard, if needed. */ -int msp_dolby = 0; +int msp_dolby; int msp_stereo_thresh = 0x190; /* a2 threshold for stereo/bilingual (msp34xxg only) 0x00a0-0x03c0 */ diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 3983a6524ca..3dd42efe369 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -140,7 +140,7 @@ static int pending_call(struct notifier_block *self, unsigned long state, return NOTIFY_DONE; } -static int pending_registered=0; +static int pending_registered; static struct notifier_block pending_notifier = { .notifier_call = pending_call, }; -- GitLab From 9b565eb794eec1ccd9edcc7263ebe5b3245a1e65 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn / snakebyte Date: Fri, 13 Jan 2006 14:10:23 -0200 Subject: [PATCH 067/465] V4L/DVB (3354a): Remove old MODULE_PARM in media/video/ Changes MODULE_PARM usage to module_param Signed-off-by: Eric Sesterhenn Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/arv.c | 6 +++--- drivers/media/video/planb.c | 4 ++-- drivers/media/video/saa6588.c | 10 +++++----- drivers/media/video/saa711x.c | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index 7d5a068353f..994b75fe165 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c @@ -129,9 +129,9 @@ static unsigned char yuv[MAX_AR_FRAME_BYTES]; static int freq = DEFAULT_FREQ; /* BCLK: available 50 or 70 (MHz) */ static int vga = 0; /* default mode(0:QVGA mode, other:VGA mode) */ static int vga_interlace = 0; /* 0 is normal mode for, else interlace mode */ -MODULE_PARM(freq, "i"); -MODULE_PARM(vga, "i"); -MODULE_PARM(vga_interlace, "i"); +module_param(freq, int, 0); +module_param(vga, int, 0); +module_param(vga_interlace, int, 0); static int ar_initialize(struct video_device *dev); diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c index b19c33434ea..f3fc361bec9 100644 --- a/drivers/media/video/planb.c +++ b/drivers/media/video/planb.c @@ -76,9 +76,9 @@ static volatile struct planb_registers *planb_regs; static int def_norm = PLANB_DEF_NORM; /* default norm */ static int video_nr = -1; -MODULE_PARM(def_norm, "i"); +module_param(def_norm, int, 0); MODULE_PARM_DESC(def_norm, "Default startup norm (0=PAL, 1=NTSC, 2=SECAM)"); -MODULE_PARM(video_nr,"i"); +module_param(video_nr, int, 0); MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index e70b17ef36e..d17395c4f55 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/video/saa6588.c @@ -50,15 +50,15 @@ static unsigned int rbds = 0; static unsigned int plvl = 0; static unsigned int bufblocks = 100; -MODULE_PARM(debug, "i"); +module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable debug messages"); -MODULE_PARM(xtal, "i"); +module_param(xtal, int, 0); MODULE_PARM_DESC(xtal, "select oscillator frequency (0..3), default 0"); -MODULE_PARM(rbds, "i"); +module_param(rbds, int, 0); MODULE_PARM_DESC(rbds, "select mode, 0=RDS, 1=RBDS, default 0"); -MODULE_PARM(plvl, "i"); +module_param(plvl, int, 0); MODULE_PARM_DESC(plvl, "select pause level (0..3), default 0"); -MODULE_PARM(bufblocks, "i"); +module_param(bufblocks, int, 0); MODULE_PARM_DESC(bufblocks, "number of buffered blocks, default 100"); MODULE_DESCRIPTION("v4l2 driver module for SAA6588 RDS decoder"); diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c index ae53063875f..6c161f2f5e2 100644 --- a/drivers/media/video/saa711x.c +++ b/drivers/media/video/saa711x.c @@ -52,7 +52,7 @@ MODULE_LICENSE("GPL"); #include static int debug = 0; -MODULE_PARM(debug, "i"); +module_param(debug, int, 0644); MODULE_PARM_DESC(debug, " Set the default Debug level. Default: 0 (Off) - (0-1)"); -- GitLab From bd5f0ac930168899003952110c45d110958a5c55 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 13 Jan 2006 14:10:24 -0200 Subject: [PATCH 068/465] V4L/DVB (3354e): bttv semaphore to mutex conversion Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. build-tested. Signed-off-by: Ingo Molnar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bttv-driver.c | 60 +++++++++++++++---------------- drivers/media/video/bttvp.h | 5 +-- 2 files changed, 33 insertions(+), 32 deletions(-) diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index 1c6cfe95454..aa4c4c52188 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -684,16 +684,16 @@ int check_alloc_btres(struct bttv *btv, struct bttv_fh *fh, int bit) return 1; /* is it free? */ - down(&btv->reslock); + mutex_lock(&btv->reslock); if (btv->resources & bit) { /* no, someone else uses it */ - up(&btv->reslock); + mutex_unlock(&btv->reslock); return 0; } /* it's free, grab it */ fh->resources |= bit; btv->resources |= bit; - up(&btv->reslock); + mutex_unlock(&btv->reslock); return 1; } @@ -716,10 +716,10 @@ void free_btres(struct bttv *btv, struct bttv_fh *fh, int bits) /* trying to free ressources not allocated by us ... */ printk("bttv: BUG! (btres)\n"); } - down(&btv->reslock); + mutex_lock(&btv->reslock); fh->resources &= ~bits; btv->resources &= ~bits; - up(&btv->reslock); + mutex_unlock(&btv->reslock); } /* ----------------------------------------------------------------------- */ @@ -1536,12 +1536,12 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) case VIDIOCSFREQ: { unsigned long *freq = arg; - down(&btv->lock); + mutex_lock(&btv->lock); btv->freq=*freq; bttv_call_i2c_clients(btv,VIDIOCSFREQ,freq); if (btv->has_matchbox && btv->radio_user) tea5757_set_freq(btv,*freq); - up(&btv->lock); + mutex_unlock(&btv->lock); return 0; } @@ -1571,10 +1571,10 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) if (v->mode >= BTTV_TVNORMS) return -EINVAL; - down(&btv->lock); + mutex_lock(&btv->lock); set_tvnorm(btv,v->mode); bttv_call_i2c_clients(btv,cmd,v); - up(&btv->lock); + mutex_unlock(&btv->lock); return 0; } @@ -1611,17 +1611,17 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) if (v->norm >= BTTV_TVNORMS) return -EINVAL; - down(&btv->lock); + mutex_lock(&btv->lock); if (channel == btv->input && v->norm == btv->tvnorm) { /* nothing to do */ - up(&btv->lock); + mutex_unlock(&btv->lock); return 0; } btv->tvnorm = v->norm; set_input(btv,v->channel); - up(&btv->lock); + mutex_unlock(&btv->lock); return 0; } @@ -1634,14 +1634,14 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) v->flags |= VIDEO_AUDIO_MUTABLE; v->mode = VIDEO_SOUND_MONO; - down(&btv->lock); + mutex_lock(&btv->lock); bttv_call_i2c_clients(btv,cmd,v); /* card specific hooks */ if (btv->audio_hook) btv->audio_hook(btv,v,0); - up(&btv->lock); + mutex_unlock(&btv->lock); return 0; } case VIDIOCSAUDIO: @@ -1652,7 +1652,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) if (audio >= bttv_tvcards[btv->c.type].audio_inputs) return -EINVAL; - down(&btv->lock); + mutex_lock(&btv->lock); audio_mux(btv, (v->flags&VIDEO_AUDIO_MUTE) ? AUDIO_MUTE : AUDIO_UNMUTE); bttv_call_i2c_clients(btv,cmd,v); @@ -1660,7 +1660,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) if (btv->audio_hook) btv->audio_hook(btv,v,1); - up(&btv->lock); + mutex_unlock(&btv->lock); return 0; } @@ -1694,10 +1694,10 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) if (i == BTTV_TVNORMS) return -EINVAL; - down(&btv->lock); + mutex_lock(&btv->lock); set_tvnorm(btv,i); i2c_vidiocschan(btv); - up(&btv->lock); + mutex_unlock(&btv->lock); return 0; } case VIDIOC_QUERYSTD: @@ -1755,9 +1755,9 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) if (*i > bttv_tvcards[btv->c.type].video_inputs) return -EINVAL; - down(&btv->lock); + mutex_lock(&btv->lock); set_input(btv,*i); - up(&btv->lock); + mutex_unlock(&btv->lock); return 0; } @@ -1769,7 +1769,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) return -EINVAL; if (0 != t->index) return -EINVAL; - down(&btv->lock); + mutex_lock(&btv->lock); memset(t,0,sizeof(*t)); strcpy(t->name, "Television"); t->type = V4L2_TUNER_ANALOG_TV; @@ -1804,7 +1804,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) } } /* FIXME: fill capability+audmode */ - up(&btv->lock); + mutex_unlock(&btv->lock); return 0; } case VIDIOC_S_TUNER: @@ -1815,7 +1815,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) return -EINVAL; if (0 != t->index) return -EINVAL; - down(&btv->lock); + mutex_lock(&btv->lock); { struct video_audio va; memset(&va, 0, sizeof(struct video_audio)); @@ -1832,7 +1832,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) if (btv->audio_hook) btv->audio_hook(btv,&va,1); } - up(&btv->lock); + mutex_unlock(&btv->lock); return 0; } @@ -1853,12 +1853,12 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) return -EINVAL; if (unlikely (f->type != V4L2_TUNER_ANALOG_TV)) return -EINVAL; - down(&btv->lock); + mutex_lock(&btv->lock); btv->freq = f->frequency; bttv_call_i2c_clients(btv,VIDIOCSFREQ,&btv->freq); if (btv->has_matchbox && btv->radio_user) tea5757_set_freq(btv,btv->freq); - up(&btv->lock); + mutex_unlock(&btv->lock); return 0; } case VIDIOC_LOG_STATUS: @@ -3156,7 +3156,7 @@ static int radio_open(struct inode *inode, struct file *file) return -ENODEV; dprintk("bttv%d: open called (radio)\n",btv->c.nr); - down(&btv->lock); + mutex_lock(&btv->lock); btv->radio_user++; @@ -3165,7 +3165,7 @@ static int radio_open(struct inode *inode, struct file *file) bttv_call_i2c_clients(btv,AUDC_SET_RADIO,&btv->tuner_type); audio_mux(btv,AUDIO_RADIO); - up(&btv->lock); + mutex_unlock(&btv->lock); return 0; } @@ -3920,8 +3920,8 @@ static int __devinit bttv_probe(struct pci_dev *dev, sprintf(btv->c.name,"bttv%d",btv->c.nr); /* initialize structs / fill in defaults */ - init_MUTEX(&btv->lock); - init_MUTEX(&btv->reslock); + mutex_init(&btv->lock); + mutex_init(&btv->reslock); spin_lock_init(&btv->s_lock); spin_lock_init(&btv->gpio_lock); init_waitqueue_head(&btv->gpioq); diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h index dd00c20ab95..9cb72f176f7 100644 --- a/drivers/media/video/bttvp.h +++ b/drivers/media/video/bttvp.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -309,9 +310,9 @@ struct bttv { /* locking */ spinlock_t s_lock; - struct semaphore lock; + struct mutex lock; int resources; - struct semaphore reslock; + struct mutex reslock; #ifdef VIDIOC_G_PRIORITY struct v4l2_prio_state prio; #endif -- GitLab From 45bf2daaa32027f44180078bd5c5fb9ac04840f9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 13 Jan 2006 14:10:24 -0200 Subject: [PATCH 069/465] V4L/DVB (3356): Include missing MODULE_* macros - Include missing MODULE_* macros. - Fixed cx88_vp3054_i2c: module license 'unspecified' taints kernel. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-vp3054-i2c.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.c b/drivers/media/video/cx88/cx88-vp3054-i2c.c index 372cd29cedb..751a754a45e 100644 --- a/drivers/media/video/cx88/cx88-vp3054-i2c.c +++ b/drivers/media/video/cx88/cx88-vp3054-i2c.c @@ -32,6 +32,10 @@ #include "cx88-vp3054-i2c.h" +MODULE_DESCRIPTION("driver for cx2388x VP3054 design"); +MODULE_AUTHOR("Chris Pascoe "); +MODULE_LICENSE("GPL"); + /* ----------------------------------------------------------------------- */ static void vp3054_bit_setscl(void *data, int state) -- GitLab From 5486a145a94918707b1d6a53f55e7b9d1b13e237 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 13 Jan 2006 14:10:24 -0200 Subject: [PATCH 070/465] V4L/DVB (3357): Build cx88-alsa when CONFIG_VIDEO_CX88_ALSA is selected. - Build cx88-alsa when CONFIG_VIDEO_CX88_ALSA is selected. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile index e4b2134fe56..6e5eaa22619 100644 --- a/drivers/media/video/cx88/Makefile +++ b/drivers/media/video/cx88/Makefile @@ -5,6 +5,7 @@ cx8802-objs := cx88-mpeg.o obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o cx8802.o cx88-blackbird.o obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o cx88-vp3054-i2c.o +obj-$(CONFIG_VIDEO_CX88_ALSA) += cx88-alsa.o EXTRA_CFLAGS += -I$(src)/.. EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core -- GitLab From f4efb4dbf21c78939e32d96cad145421c8b5f106 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 13 Jan 2006 14:10:25 -0200 Subject: [PATCH 071/465] V4L/DVB (3358): Updated MODULE_AUTHOR - Updated MODULE_AUTHOR Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/cxusb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 18d169836c9..a7fb06f4cd3 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -691,6 +691,8 @@ module_init (cxusb_module_init); module_exit (cxusb_module_exit); MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Michael Krufky "); +MODULE_AUTHOR("Chris Pascoe "); MODULE_DESCRIPTION("Driver for Conexant USB2.0 hybrid reference design"); MODULE_VERSION("1.0-alpha"); MODULE_LICENSE("GPL"); -- GitLab From 7b0ac9cdd42b254ae2ec0f6c1cc6389655e4ba96 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 13 Jan 2006 14:10:25 -0200 Subject: [PATCH 072/465] V4L/DVB (3359): Redesign tuners struct for maximum flexibility - Tunertype struct redefined to allow one or more tuner_params structs per tuner definition, one for each video standard. - Each tuner_params struct has an element containing an arbitrary amount of tuner_ranges. (this is needed for dvb tuners - to be handled later) - A tuner_range may be referenced by multiple tuner_params structs. There are many duplicates in here. Reusing tuner_range structs, rather than defining new ones for each tuner, will cut down on memory usage, and is preferred when possible. - tunertype struct contains an element, has_tda988x. We must set this for all tunertypes that contain a tda988x chip, and then we can remove this setting from the various card structs. - Improves tuners array memory usage efficiency. - Right now, all tuners are using the first tuner_params[] array element for analog mode. In the future, we will be merging similar tuner definitions together, such that each tuner definition will have a tuner_params struct for each available video standard. At that point, the tuner_params[] array element will be chosen based on the video standard in use. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Makefile | 3 +- drivers/media/video/tuner-simple.c | 750 +-------------- drivers/media/video/tuner-types.c | 1376 ++++++++++++++++++++++++++++ include/media/tuner-types.h | 41 + include/media/tuner.h | 1 + 5 files changed, 1444 insertions(+), 727 deletions(-) create mode 100644 drivers/media/video/tuner-types.c create mode 100644 include/media/tuner-types.h diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index dd24896906f..faf728366c4 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -8,7 +8,8 @@ bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \ zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.o zr36067-objs := zoran_procfs.o zoran_device.o \ zoran_driver.o zoran_card.o -tuner-objs := tuner-core.o tuner-simple.o mt20xx.o tda8290.o tea5767.o +tuner-objs := tuner-core.o tuner-types.o tuner-simple.o \ + mt20xx.o tda8290.o tea5767.o msp3400-objs := msp3400-driver.o msp3400-kthreads.o diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index e5fb7436583..3879262cf4c 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -79,722 +79,16 @@ MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner"); #define TUNER_PLL_LOCKED 0x40 #define TUNER_STEREO_MK3 0x04 -#define TUNER_MAX_RANGES 3 - -/* ---------------------------------------------------------------------- */ - -struct tunertype -{ - char *name; - - int count; - struct { - unsigned short thresh; - unsigned char cb; - } ranges[TUNER_MAX_RANGES]; - unsigned char config; -}; - -/* - * The floats in the tuner struct are computed at compile time - * by gcc and cast back to integers. Thus we don't violate the - * "no float in kernel" rule. +#define TUNER_PARAM_ANALOG 0 /* to be removed */ +/* FIXME: + * Right now, all tuners are using the first tuner_params[] array element + * for analog mode. In the future, we will be merging similar tuner + * definitions together, such that each tuner definition will have a + * tuner_params struct for each available video standard. At that point, + * TUNER_PARAM_ANALOG will be removed, and the tuner_params[] array + * element will be chosen based on the video standard in use. + * */ -static struct tunertype tuners[] = { - /* 0-9 */ - [TUNER_TEMIC_PAL] = { /* TEMIC PAL */ - .name = "Temic PAL (4002 FH5)", - .count = 3, - .ranges = { - { 16 * 140.25 /*MHz*/, 0x02, }, - { 16 * 463.25 /*MHz*/, 0x04, }, - { 16 * 999.99 , 0x01, }, - }, - .config = 0x8e, - }, - [TUNER_PHILIPS_PAL_I] = { /* Philips PAL_I */ - .name = "Philips PAL_I (FI1246 and compatibles)", - .count = 3, - .ranges = { - { 16 * 140.25 /*MHz*/, 0xa0, }, - { 16 * 463.25 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, - }, - .config = 0x8e, - }, - [TUNER_PHILIPS_NTSC] = { /* Philips NTSC */ - .name = "Philips NTSC (FI1236,FM1236 and compatibles)", - .count = 3, - .ranges = { - { 16 * 157.25 /*MHz*/, 0xa0, }, - { 16 * 451.25 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, - }, - .config = 0x8e, - }, - [TUNER_PHILIPS_SECAM] = { /* Philips SECAM */ - .name = "Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF)", - .count = 3, - .ranges = { - { 16 * 168.25 /*MHz*/, 0xa7, }, - { 16 * 447.25 /*MHz*/, 0x97, }, - { 16 * 999.99 , 0x37, }, - }, - .config = 0x8e, - }, - [TUNER_ABSENT] = { /* Tuner Absent */ - .name = "NoTuner", - .count = 1, - .ranges = { - { 0, 0x00, }, - }, - .config = 0x00, - }, - [TUNER_PHILIPS_PAL] = { /* Philips PAL */ - .name = "Philips PAL_BG (FI1216 and compatibles)", - .count = 3, - .ranges = { - { 16 * 168.25 /*MHz*/, 0xa0, }, - { 16 * 447.25 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, - }, - .config = 0x8e, - }, - [TUNER_TEMIC_NTSC] = { /* TEMIC NTSC */ - .name = "Temic NTSC (4032 FY5)", - .count = 3, - .ranges = { - { 16 * 157.25 /*MHz*/, 0x02, }, - { 16 * 463.25 /*MHz*/, 0x04, }, - { 16 * 999.99 , 0x01, }, - }, - .config = 0x8e, - }, - [TUNER_TEMIC_PAL_I] = { /* TEMIC PAL_I */ - .name = "Temic PAL_I (4062 FY5)", - .count = 3, - .ranges = { - { 16 * 170.00 /*MHz*/, 0x02, }, - { 16 * 450.00 /*MHz*/, 0x04, }, - { 16 * 999.99 , 0x01, }, - }, - .config = 0x8e, - }, - [TUNER_TEMIC_4036FY5_NTSC] = { /* TEMIC NTSC */ - .name = "Temic NTSC (4036 FY5)", - .count = 3, - .ranges = { - { 16 * 157.25 /*MHz*/, 0xa0, }, - { 16 * 463.25 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, - }, - .config = 0x8e, - }, - [TUNER_ALPS_TSBH1_NTSC] = { /* TEMIC NTSC */ - .name = "Alps HSBH1", - .count = 3, - .ranges = { - { 16 * 137.25 /*MHz*/, 0x01, }, - { 16 * 385.25 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, - }, - .config = 0x8e, - }, - - /* 10-19 */ - [TUNER_ALPS_TSBE1_PAL] = { /* TEMIC PAL */ - .name = "Alps TSBE1", - .count = 3, - .ranges = { - { 16 * 137.25 /*MHz*/, 0x01, }, - { 16 * 385.25 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, - }, - .config = 0x8e, - }, - [TUNER_ALPS_TSBB5_PAL_I] = { /* Alps PAL_I */ - .name = "Alps TSBB5", - .count = 3, - .ranges = { - { 16 * 133.25 /*MHz*/, 0x01, }, - { 16 * 351.25 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, - }, - .config = 0x8e, - }, - [TUNER_ALPS_TSBE5_PAL] = { /* Alps PAL */ - .name = "Alps TSBE5", - .count = 3, - .ranges = { - { 16 * 133.25 /*MHz*/, 0x01, }, - { 16 * 351.25 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, - }, - .config = 0x8e, - }, - [TUNER_ALPS_TSBC5_PAL] = { /* Alps PAL */ - .name = "Alps TSBC5", - .count = 3, - .ranges = { - { 16 * 133.25 /*MHz*/, 0x01, }, - { 16 * 351.25 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, - }, - .config = 0x8e, - }, - [TUNER_TEMIC_4006FH5_PAL] = { /* TEMIC PAL */ - .name = "Temic PAL_BG (4006FH5)", - .count = 3, - .ranges = { - { 16 * 170.00 /*MHz*/, 0xa0, }, - { 16 * 450.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, - }, - .config = 0x8e, - }, - [TUNER_ALPS_TSHC6_NTSC] = { /* Alps NTSC */ - .name = "Alps TSCH6", - .count = 3, - .ranges = { - { 16 * 137.25 /*MHz*/, 0x14, }, - { 16 * 385.25 /*MHz*/, 0x12, }, - { 16 * 999.99 , 0x11, }, - }, - .config = 0x8e, - }, - [TUNER_TEMIC_PAL_DK] = { /* TEMIC PAL */ - .name = "Temic PAL_DK (4016 FY5)", - .count = 3, - .ranges = { - { 16 * 168.25 /*MHz*/, 0xa0, }, - { 16 * 456.25 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, - }, - .config = 0x8e, - }, - [TUNER_PHILIPS_NTSC_M] = { /* Philips NTSC */ - .name = "Philips NTSC_M (MK2)", - .count = 3, - .ranges = { - { 16 * 160.00 /*MHz*/, 0xa0, }, - { 16 * 454.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, - }, - .config = 0x8e, - }, - [TUNER_TEMIC_4066FY5_PAL_I] = { /* TEMIC PAL_I */ - .name = "Temic PAL_I (4066 FY5)", - .count = 3, - .ranges = { - { 16 * 169.00 /*MHz*/, 0xa0, }, - { 16 * 454.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, - }, - .config = 0x8e, - }, - [TUNER_TEMIC_4006FN5_MULTI_PAL] = { /* TEMIC PAL */ - .name = "Temic PAL* auto (4006 FN5)", - .count = 3, - .ranges = { - { 16 * 169.00 /*MHz*/, 0xa0, }, - { 16 * 454.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, - }, - .config = 0x8e, - }, - - /* 20-29 */ - [TUNER_TEMIC_4009FR5_PAL] = { /* TEMIC PAL */ - .name = "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)", - .count = 3, - .ranges = { - { 16 * 141.00 /*MHz*/, 0xa0, }, - { 16 * 464.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, - }, - .config = 0x8e, - }, - [TUNER_TEMIC_4039FR5_NTSC] = { /* TEMIC NTSC */ - .name = "Temic NTSC (4039 FR5)", - .count = 3, - .ranges = { - { 16 * 158.00 /*MHz*/, 0xa0, }, - { 16 * 453.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, - }, - .config = 0x8e, - }, - [TUNER_TEMIC_4046FM5] = { /* TEMIC PAL */ - .name = "Temic PAL/SECAM multi (4046 FM5)", - .count = 3, - .ranges = { - { 16 * 169.00 /*MHz*/, 0xa0, }, - { 16 * 454.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, - }, - .config = 0x8e, - }, - [TUNER_PHILIPS_PAL_DK] = { /* Philips PAL */ - .name = "Philips PAL_DK (FI1256 and compatibles)", - .count = 3, - .ranges = { - { 16 * 170.00 /*MHz*/, 0xa0, }, - { 16 * 450.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, - }, - .config = 0x8e, - }, - [TUNER_PHILIPS_FQ1216ME] = { /* Philips PAL */ - .name = "Philips PAL/SECAM multi (FQ1216ME)", - .count = 3, - .ranges = { - { 16 * 170.00 /*MHz*/, 0xa0, }, - { 16 * 450.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, - }, - .config = 0x8e, - }, - [TUNER_LG_PAL_I_FM] = { /* LGINNOTEK PAL_I */ - .name = "LG PAL_I+FM (TAPC-I001D)", - .count = 3, - .ranges = { - { 16 * 170.00 /*MHz*/, 0xa0, }, - { 16 * 450.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, - }, - .config = 0x8e, - }, - [TUNER_LG_PAL_I] = { /* LGINNOTEK PAL_I */ - .name = "LG PAL_I (TAPC-I701D)", - .count = 3, - .ranges = { - { 16 * 170.00 /*MHz*/, 0xa0, }, - { 16 * 450.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, - }, - .config = 0x8e, - }, - [TUNER_LG_NTSC_FM] = { /* LGINNOTEK NTSC */ - .name = "LG NTSC+FM (TPI8NSR01F)", - .count = 3, - .ranges = { - { 16 * 210.00 /*MHz*/, 0xa0, }, - { 16 * 497.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, - }, - .config = 0x8e, - }, - [TUNER_LG_PAL_FM] = { /* LGINNOTEK PAL */ - .name = "LG PAL_BG+FM (TPI8PSB01D)", - .count = 3, - .ranges = { - { 16 * 170.00 /*MHz*/, 0xa0, }, - { 16 * 450.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, - }, - .config = 0x8e, - }, - [TUNER_LG_PAL] = { /* LGINNOTEK PAL */ - .name = "LG PAL_BG (TPI8PSB11D)", - .count = 3, - .ranges = { - { 16 * 170.00 /*MHz*/, 0xa0, }, - { 16 * 450.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, - }, - .config = 0x8e, - }, - - /* 30-39 */ - [TUNER_TEMIC_4009FN5_MULTI_PAL_FM] = { /* TEMIC PAL */ - .name = "Temic PAL* auto + FM (4009 FN5)", - .count = 3, - .ranges = { - { 16 * 141.00 /*MHz*/, 0xa0, }, - { 16 * 464.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, - }, - .config = 0x8e, - }, - [TUNER_SHARP_2U5JF5540_NTSC] = { /* SHARP NTSC */ - .name = "SHARP NTSC_JP (2U5JF5540)", - .count = 3, - .ranges = { - { 16 * 137.25 /*MHz*/, 0x01, }, - { 16 * 317.25 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, - }, - .config = 0x8e, - }, - [TUNER_Samsung_PAL_TCPM9091PD27] = { /* Samsung PAL */ - .name = "Samsung PAL TCPM9091PD27", - .count = 3, - .ranges = { - { 16 * 169 /*MHz*/, 0xa0, }, - { 16 * 464 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, - }, - .config = 0x8e, - }, - [TUNER_MT2032] = { /* Microtune PAL|NTSC */ - .name = "MT20xx universal", - /* see mt20xx.c for details */ }, - [TUNER_TEMIC_4106FH5] = { /* TEMIC PAL */ - .name = "Temic PAL_BG (4106 FH5)", - .count = 3, - .ranges = { - { 16 * 141.00 /*MHz*/, 0xa0, }, - { 16 * 464.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, - }, - .config = 0x8e, - }, - [TUNER_TEMIC_4012FY5] = { /* TEMIC PAL */ - .name = "Temic PAL_DK/SECAM_L (4012 FY5)", - .count = 3, - .ranges = { - { 16 * 140.25 /*MHz*/, 0x02, }, - { 16 * 463.25 /*MHz*/, 0x04, }, - { 16 * 999.99 , 0x01, }, - }, - .config = 0x8e, - }, - [TUNER_TEMIC_4136FY5] = { /* TEMIC NTSC */ - .name = "Temic NTSC (4136 FY5)", - .count = 3, - .ranges = { - { 16 * 158.00 /*MHz*/, 0xa0, }, - { 16 * 453.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, - }, - .config = 0x8e, - }, - [TUNER_LG_PAL_NEW_TAPC] = { /* LGINNOTEK PAL */ - .name = "LG PAL (newer TAPC series)", - .count = 3, - .ranges = { - { 16 * 170.00 /*MHz*/, 0x01, }, - { 16 * 450.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, - }, - .config = 0x8e, - }, - [TUNER_PHILIPS_FM1216ME_MK3] = { /* Philips PAL */ - .name = "Philips PAL/SECAM multi (FM1216ME MK3)", - .count = 3, - .ranges = { - { 16 * 158.00 /*MHz*/, 0x01, }, - { 16 * 442.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, - }, - .config = 0x8e, - }, - [TUNER_LG_NTSC_NEW_TAPC] = { /* LGINNOTEK NTSC */ - .name = "LG NTSC (newer TAPC series)", - .count = 3, - .ranges = { - { 16 * 170.00 /*MHz*/, 0x01, }, - { 16 * 450.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, - }, - .config = 0x8e, - }, - - /* 40-49 */ - [TUNER_HITACHI_NTSC] = { /* HITACHI NTSC */ - .name = "HITACHI V7-J180AT", - .count = 3, - .ranges = { - { 16 * 170.00 /*MHz*/, 0x01, }, - { 16 * 450.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, - }, - .config = 0x8e, - }, - [TUNER_PHILIPS_PAL_MK] = { /* Philips PAL */ - .name = "Philips PAL_MK (FI1216 MK)", - .count = 3, - .ranges = { - { 16 * 140.25 /*MHz*/, 0x01, }, - { 16 * 463.25 /*MHz*/, 0xc2, }, - { 16 * 999.99 , 0xcf, }, - }, - .config = 0x8e, - }, - [TUNER_PHILIPS_ATSC] = { /* Philips ATSC */ - .name = "Philips 1236D ATSC/NTSC dual in", - .count = 3, - .ranges = { - { 16 * 157.25 /*MHz*/, 0xa0, }, - { 16 * 454.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, - }, - .config = 0x8e, - }, - [TUNER_PHILIPS_FM1236_MK3] = { /* Philips NTSC */ - .name = "Philips NTSC MK3 (FM1236MK3 or FM1236/F)", - .count = 3, - .ranges = { - { 16 * 160.00 /*MHz*/, 0x01, }, - { 16 * 442.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, - }, - .config = 0x8e, - }, - [TUNER_PHILIPS_4IN1] = { /* Philips NTSC */ - .name = "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)", - .count = 3, - .ranges = { - { 16 * 160.00 /*MHz*/, 0x01, }, - { 16 * 442.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, - }, - .config = 0x8e, - }, - [TUNER_MICROTUNE_4049FM5] = { /* Microtune PAL */ - .name = "Microtune 4049 FM5", - .count = 3, - .ranges = { - { 16 * 141.00 /*MHz*/, 0xa0, }, - { 16 * 464.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, - }, - .config = 0x8e, - }, - [TUNER_PANASONIC_VP27] = { /* Panasonic NTSC */ - .name = "Panasonic VP27s/ENGE4324D", - .count = 3, - .ranges = { - { 16 * 160.00 /*MHz*/, 0x01, }, - { 16 * 454.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, - }, - .config = 0xce, - }, - [TUNER_LG_NTSC_TAPE] = { /* LGINNOTEK NTSC */ - .name = "LG NTSC (TAPE series)", - .count = 3, - .ranges = { - { 16 * 160.00 /*MHz*/, 0x01, }, - { 16 * 442.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, - }, - .config = 0x8e, - }, - [TUNER_TNF_8831BGFF] = { /* Philips PAL */ - .name = "Tenna TNF 8831 BGFF)", - .count = 3, - .ranges = { - { 16 * 161.25 /*MHz*/, 0xa0, }, - { 16 * 463.25 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, - }, - .config = 0x8e, - }, - [TUNER_MICROTUNE_4042FI5] = { /* Microtune NTSC */ - .name = "Microtune 4042 FI5 ATSC/NTSC dual in", - .count = 3, - .ranges = { - { 16 * 162.00 /*MHz*/, 0xa2, }, - { 16 * 457.00 /*MHz*/, 0x94, }, - { 16 * 999.99 , 0x31, }, - }, - .config = 0x8e, - }, - - /* 50-59 */ - [TUNER_TCL_2002N] = { /* TCL NTSC */ - .name = "TCL 2002N", - .count = 3, - .ranges = { - { 16 * 172.00 /*MHz*/, 0x01, }, - { 16 * 448.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, - }, - .config = 0x8e, - }, - [TUNER_PHILIPS_FM1256_IH3] = { /* Philips PAL */ - .name = "Philips PAL/SECAM_D (FM 1256 I-H3)", - .count = 3, - .ranges = { - { 16 * 160.00 /*MHz*/, 0x01, }, - { 16 * 442.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, - }, - .config = 0x8e, - }, - [TUNER_THOMSON_DTT7610] = { /* THOMSON ATSC */ - .name = "Thomson DTT 7610 (ATSC/NTSC)", - .count = 3, - .ranges = { - { 16 * 157.25 /*MHz*/, 0x39, }, - { 16 * 454.00 /*MHz*/, 0x3a, }, - { 16 * 999.99 , 0x3c, }, - }, - .config = 0x8e, - }, - [TUNER_PHILIPS_FQ1286] = { /* Philips NTSC */ - .name = "Philips FQ1286", - .count = 3, - .ranges = { - { 16 * 160.00 /*MHz*/, 0x41, }, - { 16 * 454.00 /*MHz*/, 0x42, }, - { 16 * 999.99 , 0x04, }, - }, - .config = 0x8e, - }, - [TUNER_PHILIPS_TDA8290] = { /* Philips PAL|NTSC */ - .name = "tda8290+75", - /* see tda8290.c for details */ }, - [TUNER_TCL_2002MB] = { /* TCL PAL */ - .name = "TCL 2002MB", - .count = 3, - .ranges = { - { 16 * 170.00 /*MHz*/, 0x01, }, - { 16 * 450.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, - }, - .config = 0xce, - }, - [TUNER_PHILIPS_FQ1216AME_MK4] = { /* Philips PAL */ - .name = "Philips PAL/SECAM multi (FQ1216AME MK4)", - .count = 3, - .ranges = { - { 16 * 160.00 /*MHz*/, 0x01, }, - { 16 * 442.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, - }, - .config = 0xce, - }, - [TUNER_PHILIPS_FQ1236A_MK4] = { /* Philips NTSC */ - .name = "Philips FQ1236A MK4", - .count = 3, - .ranges = { - { 16 * 160.00 /*MHz*/, 0x01, }, - { 16 * 442.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, - }, - .config = 0x8e, - }, - [TUNER_YMEC_TVF_8531MF] = { /* Philips NTSC */ - .name = "Ymec TVision TVF-8531MF/8831MF/8731MF", - .count = 3, - .ranges = { - { 16 * 160.00 /*MHz*/, 0xa0, }, - { 16 * 454.00 /*MHz*/, 0x90, }, - { 16 * 999.99 , 0x30, }, - }, - .config = 0x8e, - }, - [TUNER_YMEC_TVF_5533MF] = { /* Philips NTSC */ - .name = "Ymec TVision TVF-5533MF", - .count = 3, - .ranges = { - { 16 * 160.00 /*MHz*/, 0x01, }, - { 16 * 454.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, - }, - .config = 0x8e, - }, - - /* 60-69 */ - [TUNER_THOMSON_DTT761X] = { /* THOMSON ATSC */ - /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */ - .name = "Thomson DTT 761X (ATSC/NTSC)", - .count = 3, - .ranges = { - { 16 * 145.25 /*MHz*/, 0x39, }, - { 16 * 415.25 /*MHz*/, 0x3a, }, - { 16 * 999.99 , 0x3c, }, - }, - .config = 0x8e, - }, - [TUNER_TENA_9533_DI] = { /* Philips PAL */ - .name = "Tena TNF9533-D/IF/TNF9533-B/DF", - .count = 3, - .ranges = { - { 16 * 160.25 /*MHz*/, 0x01, }, - { 16 * 464.25 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, - }, - .config = 0x8e, - }, - [TUNER_TEA5767] = { /* Philips RADIO */ - .name = "Philips TEA5767HN FM Radio", - /* see tea5767.c for details */}, - [TUNER_PHILIPS_FMD1216ME_MK3] = { /* Philips PAL */ - .name = "Philips FMD1216ME MK3 Hybrid Tuner", - .count = 3, - .ranges = { - { 16 * 160.00 /*MHz*/, 0x51, }, - { 16 * 442.00 /*MHz*/, 0x52, }, - { 16 * 999.99 , 0x54, }, - }, - .config = 0x86, - }, - [TUNER_LG_TDVS_H062F] = { /* LGINNOTEK ATSC */ - .name = "LG TDVS-H062F/TUA6034", - .count = 3, - .ranges = { - { 16 * 160.00 /*MHz*/, 0x01 }, - { 16 * 455.00 /*MHz*/, 0x02 }, - { 16 * 999.99 , 0x04 }, - }, - .config = 0x8e, - }, - [TUNER_YMEC_TVF66T5_B_DFF] = { /* Philips PAL */ - .name = "Ymec TVF66T5-B/DFF", - .count = 3, - .ranges = { - { 16 * 160.25 /*MHz*/, 0x01, }, - { 16 * 464.25 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, - }, - .config = 0x8e, - }, - [TUNER_LG_NTSC_TALN_MINI] = { /* LGINNOTEK NTSC */ - .name = "LG NTSC (TALN mini series)", - .count = 3, - .ranges = { - { 16 * 137.25 /*MHz*/, 0x01, }, - { 16 * 373.25 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x08, }, - }, - .config = 0x8e, - }, - [TUNER_PHILIPS_TD1316] = { /* Philips PAL */ - .name = "Philips TD1316 Hybrid Tuner", - .count = 3, - .ranges = { - { 16 * 160.00 /*MHz*/, 0xa1, }, - { 16 * 442.00 /*MHz*/, 0xa2, }, - { 16 * 999.99 , 0xa4, }, - }, - .config = 0xc8, - }, - [TUNER_PHILIPS_TUV1236D] = { /* Philips ATSC */ - .name = "Philips TUV1236D ATSC/NTSC dual in", - .count = 3, - .ranges = { - { 16 * 157.25 /*MHz*/, 0x01, }, - { 16 * 454.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, - }, - .config = 0xce, - }, - [TUNER_TNF_5335MF] = { /* Philips NTSC */ - .name = "Tena TNF 5335 MF", - .count = 3, - .ranges = { - { 16 * 157.25 /*MHz*/, 0x01, }, - { 16 * 454.00 /*MHz*/, 0x02, }, - { 16 * 999.99 , 0x04, }, - }, - .config = 0x8e, - }, -}; - -unsigned const int tuner_count = ARRAY_SIZE(tuners); /* ---------------------------------------------------------------------- */ @@ -843,15 +137,17 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) u16 div; struct tunertype *tun; unsigned char buffer[4]; - int rc, IFPCoff, i; + int rc, IFPCoff, i, j; tun = &tuners[t->type]; - for (i = 0; i < tun->count; i++) { - if (freq > tun->ranges[i].thresh) + j = TUNER_PARAM_ANALOG; + + for (i = 0; i < tun->params[j].count; i++) { + if (freq > tun->params[j].ranges[i].limit) continue; break; } - config = tun->ranges[i].cb; + config = tun->params[j].ranges[i].cb; /* i == 0 -> VHF_LO */ /* i == 1 -> VHF_HI */ /* i == 2 -> UHF */ @@ -914,7 +210,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) case TUNER_MICROTUNE_4042FI5: /* Set the charge pump for fast tuning */ - tun->config |= TUNER_CHARGE_PUMP; + tun->params[j].config |= TUNER_CHARGE_PUMP; break; case TUNER_PHILIPS_TUV1236D: @@ -989,14 +285,14 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) div); if (t->type == TUNER_PHILIPS_SECAM && freq < t->freq) { - buffer[0] = tun->config; + buffer[0] = tun->params[j].config; buffer[1] = config; buffer[2] = (div>>8) & 0x7f; buffer[3] = div & 0xff; } else { buffer[0] = (div>>8) & 0x7f; buffer[1] = div & 0xff; - buffer[2] = tun->config; + buffer[2] = tun->params[j].config; buffer[3] = config; } tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", @@ -1024,10 +320,10 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) } /* Set the charge pump for optimized phase noise figure */ - tun->config &= ~TUNER_CHARGE_PUMP; + tun->params[j].config &= ~TUNER_CHARGE_PUMP; buffer[0] = (div>>8) & 0x7f; buffer[1] = div & 0xff; - buffer[2] = tun->config; + buffer[2] = tun->params[j].config; buffer[3] = config; tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", buffer[0],buffer[1],buffer[2],buffer[3]); @@ -1043,11 +339,13 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) struct tuner *t = i2c_get_clientdata(c); unsigned char buffer[4]; unsigned div; - int rc; + int rc, j; tun = &tuners[t->type]; + j = TUNER_PARAM_ANALOG; + div = (20 * freq / 16000) + (int)(20*10.7); /* IF 10.7 MHz */ - buffer[2] = (tun->config & ~TUNER_RATIO_MASK) | TUNER_RATIO_SELECT_50; /* 50 kHz step */ + buffer[2] = (tun->params[j].config & ~TUNER_RATIO_MASK) | TUNER_RATIO_SELECT_50; /* 50 kHz step */ switch (t->type) { case TUNER_TENA_9533_DI: diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c new file mode 100644 index 00000000000..de9d4925d8e --- /dev/null +++ b/drivers/media/video/tuner-types.c @@ -0,0 +1,1376 @@ +/* + * + * i2c tv tuner chip device type database. + * + */ + +#include +#include +#include + +/* ---------------------------------------------------------------------- */ + +/* + * The floats in the tuner struct are computed at compile time + * by gcc and cast back to integers. Thus we don't violate the + * "no float in kernel" rule. + * + * A tuner_range may be referenced by multiple tuner_params structs. + * There are many duplicates in here. Reusing tuner_range structs, + * rather than defining new ones for each tuner, will cut down on + * memory usage, and is preferred when possible. + * + * Each tuner_params array may contain one or more elements, one + * for each video standard. + * + * FIXME: Some tuner_range definitions are duplicated, and + * should be eliminated. + * + * FIXME: tunertype struct contains an element, has_tda988x. + * We must set this for all tunertypes that contain a tda988x + * chip, and then we can remove this setting from the various + * card structs. + */ + +/* 0-9 */ +/* ------------ TUNER_TEMIC_PAL - TEMIC PAL ------------ */ + +static struct tuner_range tuner_temic_pal_ranges[] = { + { 16 * 140.25 /*MHz*/, 0x02, }, + { 16 * 463.25 /*MHz*/, 0x04, }, + { 16 * 999.99 , 0x01, }, +}; + +static struct tuner_params tuner_temic_pal_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_temic_pal_ranges, + .count = ARRAY_SIZE(tuner_temic_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PHILIPS_PAL_I - Philips PAL_I ------------ */ + +static struct tuner_range tuner_philips_pal_i_ranges[] = { + { 16 * 140.25 /*MHz*/, 0xa0, }, + { 16 * 463.25 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_philips_pal_i_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_philips_pal_i_ranges, + .count = ARRAY_SIZE(tuner_philips_pal_i_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PHILIPS_NTSC - Philips NTSC ------------ */ + +static struct tuner_range tuner_philips_ntsc_ranges[] = { + { 16 * 157.25 /*MHz*/, 0xa0, }, + { 16 * 451.25 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_philips_ntsc_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_philips_ntsc_ranges, + .count = ARRAY_SIZE(tuner_philips_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PHILIPS_SECAM - Philips SECAM ------------ */ + +static struct tuner_range tuner_philips_secam_ranges[] = { + { 16 * 168.25 /*MHz*/, 0xa7, }, + { 16 * 447.25 /*MHz*/, 0x97, }, + { 16 * 999.99 , 0x37, }, +}; + +static struct tuner_params tuner_philips_secam_params[] = { + { + .type = TUNER_PARAM_TYPE_SECAM, + .ranges = tuner_philips_secam_ranges, + .count = ARRAY_SIZE(tuner_philips_secam_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PHILIPS_PAL - Philips PAL ------------ */ + +static struct tuner_range tuner_philips_pal_ranges[] = { + { 16 * 168.25 /*MHz*/, 0xa0, }, + { 16 * 447.25 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_philips_pal_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_philips_pal_ranges, + .count = ARRAY_SIZE(tuner_philips_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_TEMIC_NTSC - TEMIC NTSC ------------ */ + +static struct tuner_range tuner_temic_ntsc_ranges[] = { + { 16 * 157.25 /*MHz*/, 0x02, }, + { 16 * 463.25 /*MHz*/, 0x04, }, + { 16 * 999.99 , 0x01, }, +}; + +static struct tuner_params tuner_temic_ntsc_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_temic_ntsc_ranges, + .count = ARRAY_SIZE(tuner_temic_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_TEMIC_PAL_I - TEMIC PAL_I ------------ */ + +static struct tuner_range tuner_temic_pal_i_ranges[] = { + { 16 * 170.00 /*MHz*/, 0x02, }, + { 16 * 450.00 /*MHz*/, 0x04, }, + { 16 * 999.99 , 0x01, }, +}; + +static struct tuner_params tuner_temic_pal_i_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_temic_pal_i_ranges, + .count = ARRAY_SIZE(tuner_temic_pal_i_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_TEMIC_4036FY5_NTSC - TEMIC NTSC ------------ */ + +static struct tuner_range tuner_temic_4036fy5_ntsc_ranges[] = { + { 16 * 157.25 /*MHz*/, 0xa0, }, + { 16 * 463.25 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_temic_4036fy5_ntsc_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_temic_4036fy5_ntsc_ranges, + .count = ARRAY_SIZE(tuner_temic_4036fy5_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_ALPS_TSBH1_NTSC - TEMIC NTSC ------------ */ + +static struct tuner_range tuner_alps_tsb_1_ranges[] = { + { 16 * 137.25 /*MHz*/, 0x01, }, + { 16 * 385.25 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, +}; + +static struct tuner_params tuner_alps_tsbh1_ntsc_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_alps_tsb_1_ranges, + .count = ARRAY_SIZE(tuner_alps_tsb_1_ranges), + .config = 0x8e, + }, +}; + +/* 10-19 */ +/* ------------ TUNER_ALPS_TSBE1_PAL - TEMIC PAL ------------ */ + +static struct tuner_params tuner_alps_tsb_1_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_alps_tsb_1_ranges, + .count = ARRAY_SIZE(tuner_alps_tsb_1_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_ALPS_TSBB5_PAL_I - Alps PAL_I ------------ */ + +static struct tuner_range tuner_alps_tsb_5_pal_ranges[] = { + { 16 * 133.25 /*MHz*/, 0x01, }, + { 16 * 351.25 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, +}; + +static struct tuner_params tuner_alps_tsbb5_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_alps_tsb_5_pal_ranges, + .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_ALPS_TSBE5_PAL - Alps PAL ------------ */ + +static struct tuner_params tuner_alps_tsbe5_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_alps_tsb_5_pal_ranges, + .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_ALPS_TSBC5_PAL - Alps PAL ------------ */ + +static struct tuner_params tuner_alps_tsbc5_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_alps_tsb_5_pal_ranges, + .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_TEMIC_4006FH5_PAL - TEMIC PAL ------------ */ + +static struct tuner_range tuner_temic_4006fh5_pal_ranges[] = { + { 16 * 170.00 /*MHz*/, 0xa0, }, + { 16 * 450.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_temic_4006fh5_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_temic_4006fh5_pal_ranges, + .count = ARRAY_SIZE(tuner_temic_4006fh5_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_ALPS_TSHC6_NTSC - Alps NTSC ------------ */ + +static struct tuner_range tuner_alps_tshc6_ntsc_ranges[] = { + { 16 * 137.25 /*MHz*/, 0x14, }, + { 16 * 385.25 /*MHz*/, 0x12, }, + { 16 * 999.99 , 0x11, }, +}; + +static struct tuner_params tuner_alps_tshc6_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_alps_tshc6_ntsc_ranges, + .count = ARRAY_SIZE(tuner_alps_tshc6_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_TEMIC_PAL_DK - TEMIC PAL ------------ */ + +static struct tuner_range tuner_temic_pal_dk_ranges[] = { + { 16 * 168.25 /*MHz*/, 0xa0, }, + { 16 * 456.25 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_temic_pal_dk_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_temic_pal_dk_ranges, + .count = ARRAY_SIZE(tuner_temic_pal_dk_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PHILIPS_NTSC_M - Philips NTSC ------------ */ + +static struct tuner_range tuner_philips_ntsc_m_ranges[] = { + { 16 * 160.00 /*MHz*/, 0xa0, }, + { 16 * 454.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_philips_ntsc_m_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_philips_ntsc_m_ranges, + .count = ARRAY_SIZE(tuner_philips_ntsc_m_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_TEMIC_4066FY5_PAL_I - TEMIC PAL_I ------------ */ + +static struct tuner_range tuner_temic_40x6f_5_pal_ranges[] = { + { 16 * 169.00 /*MHz*/, 0xa0, }, + { 16 * 454.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_temic_4066fy5_pal_i_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_temic_40x6f_5_pal_ranges, + .count = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_TEMIC_4006FN5_MULTI_PAL - TEMIC PAL ------------ */ + +static struct tuner_params tuner_temic_4006fn5_multi_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_temic_40x6f_5_pal_ranges, + .count = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges), + .config = 0x8e, + }, +}; + +/* 20-29 */ +/* ------------ TUNER_TEMIC_4009FR5_PAL - TEMIC PAL ------------ */ + +static struct tuner_range tuner_temic_4009f_5_pal_ranges[] = { + { 16 * 141.00 /*MHz*/, 0xa0, }, + { 16 * 464.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_temic_4009f_5_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_temic_4009f_5_pal_ranges, + .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_TEMIC_4039FR5_NTSC - TEMIC NTSC ------------ */ + +static struct tuner_range tuner_temic_4039fr5_ntsc_ranges[] = { + { 16 * 158.00 /*MHz*/, 0xa0, }, + { 16 * 453.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_temic_4039fr5_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_temic_4039fr5_ntsc_ranges, + .count = ARRAY_SIZE(tuner_temic_4039fr5_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_TEMIC_4046FM5 - TEMIC PAL ------------ */ + +static struct tuner_range tuner_temic_4046fm5_pal_ranges[] = { + { 16 * 169.00 /*MHz*/, 0xa0, }, + { 16 * 454.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_temic_4046fm5_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_temic_4046fm5_pal_ranges, + .count = ARRAY_SIZE(tuner_temic_4046fm5_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PHILIPS_PAL_DK - Philips PAL ------------ */ + +static struct tuner_range tuner_lg_pal_ranges[] = { + { 16 * 170.00 /*MHz*/, 0xa0, }, + { 16 * 450.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_philips_pal_dk_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_lg_pal_ranges, + .count = ARRAY_SIZE(tuner_lg_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PHILIPS_FQ1216ME - Philips PAL ------------ */ + +static struct tuner_params tuner_philips_fq1216me_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_lg_pal_ranges, + .count = ARRAY_SIZE(tuner_lg_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_LG_PAL_I_FM - LGINNOTEK PAL_I ------------ */ + +static struct tuner_params tuner_lg_pal_i_fm_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_lg_pal_ranges, + .count = ARRAY_SIZE(tuner_lg_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_LG_PAL_I - LGINNOTEK PAL_I ------------ */ + +static struct tuner_params tuner_lg_pal_i_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_lg_pal_ranges, + .count = ARRAY_SIZE(tuner_lg_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_LG_NTSC_FM - LGINNOTEK NTSC ------------ */ + +static struct tuner_range tuner_lg_ntsc_fm_ranges[] = { + { 16 * 210.00 /*MHz*/, 0xa0, }, + { 16 * 497.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_lg_ntsc_fm_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_lg_ntsc_fm_ranges, + .count = ARRAY_SIZE(tuner_lg_ntsc_fm_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_LG_PAL_FM - LGINNOTEK PAL ------------ */ + +static struct tuner_params tuner_lg_pal_fm_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_lg_pal_ranges, + .count = ARRAY_SIZE(tuner_lg_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_LG_PAL - LGINNOTEK PAL ------------ */ + +static struct tuner_params tuner_lg_pal_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_lg_pal_ranges, + .count = ARRAY_SIZE(tuner_lg_pal_ranges), + .config = 0x8e, + }, +}; + +/* 30-39 */ +/* ------------ TUNER_TEMIC_4009FN5_MULTI_PAL_FM - TEMIC PAL ------------ */ + +static struct tuner_params tuner_temic_4009_fn5_multi_pal_fm_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_temic_4009f_5_pal_ranges, + .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_SHARP_2U5JF5540_NTSC - SHARP NTSC ------------ */ + +static struct tuner_range tuner_sharp_2u5jf5540_ntsc_ranges[] = { + { 16 * 137.25 /*MHz*/, 0x01, }, + { 16 * 317.25 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, +}; + +static struct tuner_params tuner_sharp_2u5jf5540_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_sharp_2u5jf5540_ntsc_ranges, + .count = ARRAY_SIZE(tuner_sharp_2u5jf5540_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_Samsung_PAL_TCPM9091PD27 - Samsung PAL ------------ */ + +static struct tuner_range tuner_samsung_pal_tcpm9091pd27_ranges[] = { + { 16 * 169 /*MHz*/, 0xa0, }, + { 16 * 464 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_samsung_pal_tcpm9091pd27_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_samsung_pal_tcpm9091pd27_ranges, + .count = ARRAY_SIZE(tuner_samsung_pal_tcpm9091pd27_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_TEMIC_4106FH5 - TEMIC PAL ------------ */ + +static struct tuner_params tuner_temic_4106fh5_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_temic_4009f_5_pal_ranges, + .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_TEMIC_4012FY5 - TEMIC PAL ------------ */ + +static struct tuner_range tuner_temic_4012fy5_pal_ranges[] = { + { 16 * 140.25 /*MHz*/, 0x02, }, + { 16 * 463.25 /*MHz*/, 0x04, }, + { 16 * 999.99 , 0x01, }, +}; + +static struct tuner_params tuner_temic_4012fy5_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_temic_4012fy5_pal_ranges, + .count = ARRAY_SIZE(tuner_temic_4012fy5_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_TEMIC_4136FY5 - TEMIC NTSC ------------ */ + +static struct tuner_range tuner_temic_4136_fy5_ntsc_ranges[] = { + { 16 * 158.00 /*MHz*/, 0xa0, }, + { 16 * 453.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_temic_4136_fy5_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_temic_4136_fy5_ntsc_ranges, + .count = ARRAY_SIZE(tuner_temic_4136_fy5_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_LG_PAL_NEW_TAPC - LGINNOTEK PAL ------------ */ + +static struct tuner_range tuner_lg_new_tapc_ranges[] = { + { 16 * 170.00 /*MHz*/, 0x01, }, + { 16 * 450.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, +}; + +static struct tuner_params tuner_lg_pal_new_tapc_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_lg_new_tapc_ranges, + .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PHILIPS_FM1216ME_MK3 - Philips PAL ------------ */ + +static struct tuner_range tuner_fm1216me_mk3_pal_ranges[] = { + { 16 * 158.00 /*MHz*/, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, +}; + +static struct tuner_params tuner_fm1216me_mk3_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_fm1216me_mk3_pal_ranges, + .count = ARRAY_SIZE(tuner_fm1216me_mk3_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_LG_NTSC_NEW_TAPC - LGINNOTEK NTSC ------------ */ + +static struct tuner_params tuner_lg_ntsc_new_tapc_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_lg_new_tapc_ranges, + .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges), + .config = 0x8e, + }, +}; + +/* 40-49 */ +/* ------------ TUNER_HITACHI_NTSC - HITACHI NTSC ------------ */ + +static struct tuner_params tuner_hitachi_ntsc_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_lg_new_tapc_ranges, + .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PHILIPS_PAL_MK - Philips PAL ------------ */ + +static struct tuner_range tuner_philips_pal_mk_pal_ranges[] = { + { 16 * 140.25 /*MHz*/, 0x01, }, + { 16 * 463.25 /*MHz*/, 0xc2, }, + { 16 * 999.99 , 0xcf, }, +}; + +static struct tuner_params tuner_philips_pal_mk_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_philips_pal_mk_pal_ranges, + .count = ARRAY_SIZE(tuner_philips_pal_mk_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PHILIPS_ATSC - Philips ATSC ------------ */ + +static struct tuner_range tuner_philips_atsc_ranges[] = { + { 16 * 157.25 /*MHz*/, 0xa0, }, + { 16 * 454.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_philips_atsc_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_philips_atsc_ranges, + .count = ARRAY_SIZE(tuner_philips_atsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PHILIPS_FM1236_MK3 - Philips NTSC ------------ */ + +static struct tuner_range tuner_fm1236_mk3_ntsc_ranges[] = { + { 16 * 160.00 /*MHz*/, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, +}; + +static struct tuner_params tuner_fm1236_mk3_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_fm1236_mk3_ntsc_ranges, + .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PHILIPS_4IN1 - Philips NTSC ------------ */ + +static struct tuner_range tuner_philips_4in1_ntsc_ranges[] = { + { 16 * 160.00 /*MHz*/, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, +}; + +static struct tuner_params tuner_philips_4in1_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_philips_4in1_ntsc_ranges, + .count = ARRAY_SIZE(tuner_philips_4in1_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_MICROTUNE_4049FM5 - Microtune PAL ------------ */ + +static struct tuner_params tuner_microtune_4049_fm5_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_temic_4009f_5_pal_ranges, + .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PANASONIC_VP27 - Panasonic NTSC ------------ */ + +static struct tuner_range tuner_panasonic_vp27_ntsc_ranges[] = { + { 16 * 160.00 /*MHz*/, 0x01, }, + { 16 * 454.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, +}; + +static struct tuner_params tuner_panasonic_vp27_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_panasonic_vp27_ntsc_ranges, + .count = ARRAY_SIZE(tuner_panasonic_vp27_ntsc_ranges), + .config = 0xce, + }, +}; + +/* ------------ TUNER_LG_NTSC_TAPE - LGINNOTEK NTSC ------------ */ + +static struct tuner_range tuner_lg_ntsc_tape_ranges[] = { + { 16 * 160.00 /*MHz*/, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, +}; + +static struct tuner_params tuner_lg_ntsc_tape_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_lg_ntsc_tape_ranges, + .count = ARRAY_SIZE(tuner_lg_ntsc_tape_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_TNF_8831BGFF - Philips PAL ------------ */ + +static struct tuner_range tuner_tnf_8831bgff_pal_ranges[] = { + { 16 * 161.25 /*MHz*/, 0xa0, }, + { 16 * 463.25 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_tnf_8831bgff_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_tnf_8831bgff_pal_ranges, + .count = ARRAY_SIZE(tuner_tnf_8831bgff_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_MICROTUNE_4042FI5 - Microtune NTSC ------------ */ + +static struct tuner_range tuner_microtune_4042fi5_ntsc_ranges[] = { + { 16 * 162.00 /*MHz*/, 0xa2, }, + { 16 * 457.00 /*MHz*/, 0x94, }, + { 16 * 999.99 , 0x31, }, +}; + +static struct tuner_params tuner_microtune_4042fi5_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_microtune_4042fi5_ntsc_ranges, + .count = ARRAY_SIZE(tuner_microtune_4042fi5_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* 50-59 */ +/* ------------ TUNER_TCL_2002N - TCL NTSC ------------ */ + +static struct tuner_range tuner_tcl_2002n_ntsc_ranges[] = { + { 16 * 172.00 /*MHz*/, 0x01, }, + { 16 * 448.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, +}; + +static struct tuner_params tuner_tcl_2002n_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_tcl_2002n_ntsc_ranges, + .count = ARRAY_SIZE(tuner_tcl_2002n_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PHILIPS_FM1256_IH3 - Philips PAL ------------ */ + +static struct tuner_range tuner_philips_fm1256_ih3_pal_ranges[] = { + { 16 * 160.00 /*MHz*/, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, +}; + +static struct tuner_params tuner_philips_fm1256_ih3_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_philips_fm1256_ih3_pal_ranges, + .count = ARRAY_SIZE(tuner_philips_fm1256_ih3_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_THOMSON_DTT7610 - THOMSON ATSC ------------ */ + +static struct tuner_range tuner_thomson_dtt7610_ntsc_ranges[] = { + { 16 * 157.25 /*MHz*/, 0x39, }, + { 16 * 454.00 /*MHz*/, 0x3a, }, + { 16 * 999.99 , 0x3c, }, +}; + +static struct tuner_params tuner_thomson_dtt7610_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_thomson_dtt7610_ntsc_ranges, + .count = ARRAY_SIZE(tuner_thomson_dtt7610_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PHILIPS_FQ1286 - Philips NTSC ------------ */ + +static struct tuner_range tuner_philips_fq1286_ntsc_ranges[] = { + { 16 * 160.00 /*MHz*/, 0x41, }, + { 16 * 454.00 /*MHz*/, 0x42, }, + { 16 * 999.99 , 0x04, }, +}; + +static struct tuner_params tuner_philips_fq1286_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_philips_fq1286_ntsc_ranges, + .count = ARRAY_SIZE(tuner_philips_fq1286_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_TCL_2002MB - TCL PAL ------------ */ + +static struct tuner_range tuner_tcl_2002mb_pal_ranges[] = { + { 16 * 170.00 /*MHz*/, 0x01, }, + { 16 * 450.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, +}; + +static struct tuner_params tuner_tcl_2002mb_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_tcl_2002mb_pal_ranges, + .count = ARRAY_SIZE(tuner_tcl_2002mb_pal_ranges), + .config = 0xce, + }, +}; + +/* ------------ TUNER_PHILIPS_FQ1216AME_MK4 - Philips PAL ------------ */ + +static struct tuner_range tuner_philips_fq12_6a___mk4_ranges[] = { + { 16 * 160.00 /*MHz*/, 0x01, }, + { 16 * 442.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, +}; + +static struct tuner_params tuner_philips_fq1216ame_mk4_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_philips_fq12_6a___mk4_ranges, + .count = ARRAY_SIZE(tuner_philips_fq12_6a___mk4_ranges), + .config = 0xce, + }, +}; + +/* ------------ TUNER_PHILIPS_FQ1236A_MK4 - Philips NTSC ------------ */ + +static struct tuner_params tuner_philips_fq1236a_mk4_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_philips_fq12_6a___mk4_ranges, + .count = ARRAY_SIZE(tuner_philips_fq12_6a___mk4_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_YMEC_TVF_8531MF - Philips NTSC ------------ */ + +static struct tuner_range tuner_ymec_tvf_8531mf_ntsc_ranges[] = { + { 16 * 160.00 /*MHz*/, 0xa0, }, + { 16 * 454.00 /*MHz*/, 0x90, }, + { 16 * 999.99 , 0x30, }, +}; + +static struct tuner_params tuner_ymec_tvf_8531mf_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_ymec_tvf_8531mf_ntsc_ranges, + .count = ARRAY_SIZE(tuner_ymec_tvf_8531mf_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_YMEC_TVF_5533MF - Philips NTSC ------------ */ + +static struct tuner_range tuner_ymec_tvf_5533mf_ntsc_ranges[] = { + { 16 * 160.00 /*MHz*/, 0x01, }, + { 16 * 454.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, +}; + +static struct tuner_params tuner_ymec_tvf_5533mf_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_ymec_tvf_5533mf_ntsc_ranges, + .count = ARRAY_SIZE(tuner_ymec_tvf_5533mf_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* 60-69 */ +/* ------------ TUNER_THOMSON_DTT761X - THOMSON ATSC ------------ */ +/* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */ + +static struct tuner_range tuner_thomson_dtt761x_ntsc_ranges[] = { + { 16 * 145.25 /*MHz*/, 0x39, }, + { 16 * 415.25 /*MHz*/, 0x3a, }, + { 16 * 999.99 , 0x3c, }, +}; + + +static struct tuner_params tuner_thomson_dtt761x_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_thomson_dtt761x_ntsc_ranges, + .count = ARRAY_SIZE(tuner_thomson_dtt761x_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_TENA_9533_DI - Philips PAL ------------ */ + +static struct tuner_range tuner_tuner_tena_9533_di_pal_ranges[] = { + { 16 * 160.25 /*MHz*/, 0x01, }, + { 16 * 464.25 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, +}; + +static struct tuner_params tuner_tena_9533_di_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_tuner_tena_9533_di_pal_ranges, + .count = ARRAY_SIZE(tuner_tuner_tena_9533_di_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PHILIPS_FMD1216ME_MK3 - Philips PAL ------------ */ + +static struct tuner_range tuner_philips_fmd1216me_mk3_pal_ranges[] = { + { 16 * 160.00 /*MHz*/, 0x51, }, + { 16 * 442.00 /*MHz*/, 0x52, }, + { 16 * 999.99 , 0x54, }, +}; + + +static struct tuner_params tuner_tuner_philips_fmd1216me_mk3_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_philips_fmd1216me_mk3_pal_ranges, + .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_pal_ranges), + .config = 0x86, + }, +}; + + +/* ------------ TUNER_LG_TDVS_H062F - INFINEON ATSC ------------ */ + +static struct tuner_range tuner_tua6034_ntsc_ranges[] = { + { 16 * 160.00 /*MHz*/, 0x01 }, + { 16 * 455.00 /*MHz*/, 0x02 }, + { 16 * 999.99 , 0x04 }, +}; + + +static struct tuner_params tuner_tua6034_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_tua6034_ntsc_ranges, + .count = ARRAY_SIZE(tuner_tua6034_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_YMEC_TVF66T5_B_DFF - Philips PAL ------------ */ + +static struct tuner_range tuner_ymec_tvf66t5_b_dff_pal_ranges[] = { + { 16 * 160.25 /*MHz*/, 0x01, }, + { 16 * 464.25 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, +}; + +static struct tuner_params tuner_ymec_tvf66t5_b_dff_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_ymec_tvf66t5_b_dff_pal_ranges, + .count = ARRAY_SIZE(tuner_ymec_tvf66t5_b_dff_pal_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_LG_NTSC_TALN_MINI - LGINNOTEK NTSC ------------ */ + +static struct tuner_range tuner_lg_taln_mini_ntsc_ranges[] = { + { 16 * 137.25 /*MHz*/, 0x01, }, + { 16 * 373.25 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, +}; + +static struct tuner_params tuner_lg_taln_mini_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_lg_taln_mini_ntsc_ranges, + .count = ARRAY_SIZE(tuner_lg_taln_mini_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* ------------ TUNER_PHILIPS_TD1316 - Philips PAL ------------ */ + +static struct tuner_range tuner_philips_td1316_pal_ranges[] = { + { 16 * 160.00 /*MHz*/, 0xa1, }, + { 16 * 442.00 /*MHz*/, 0xa2, }, + { 16 * 999.99 , 0xa4, }, +}; + +static struct tuner_params tuner_philips_td1316_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_philips_td1316_pal_ranges, + .count = ARRAY_SIZE(tuner_philips_td1316_pal_ranges), + .config = 0xc8, + }, +}; + +/* ------------ TUNER_PHILIPS_TUV1236D - Philips ATSC ------------ */ + +static struct tuner_range tuner_tuv1236d_ntsc_ranges[] = { + { 16 * 157.25 /*MHz*/, 0x01, }, + { 16 * 454.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, +}; + + +static struct tuner_params tuner_tuner_tuv1236d_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_tuv1236d_ntsc_ranges, + .count = ARRAY_SIZE(tuner_tuv1236d_ntsc_ranges), + .config = 0xce, + }, +}; + +/* ------------ TUNER_TNF_5335MF - Philips NTSC ------------ */ + +static struct tuner_range tuner_tnf_5335mf_ntsc_ranges[] = { + { 16 * 157.25 /*MHz*/, 0x01, }, + { 16 * 454.00 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x04, }, +}; + +static struct tuner_params tuner_tnf_5335mf_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_tnf_5335mf_ntsc_ranges, + .count = ARRAY_SIZE(tuner_tnf_5335mf_ntsc_ranges), + .config = 0x8e, + }, +}; + +/* --------------------------------------------------------------------- */ + +struct tunertype tuners[] = { + /* 0-9 */ + [TUNER_TEMIC_PAL] = { /* TEMIC PAL */ + .name = "Temic PAL (4002 FH5)", + .params = tuner_temic_pal_params, + }, + [TUNER_PHILIPS_PAL_I] = { /* Philips PAL_I */ + .name = "Philips PAL_I (FI1246 and compatibles)", + .params = tuner_philips_pal_i_params, + }, + [TUNER_PHILIPS_NTSC] = { /* Philips NTSC */ + .name = "Philips NTSC (FI1236,FM1236 and compatibles)", + .params = tuner_philips_ntsc_params, + }, + [TUNER_PHILIPS_SECAM] = { /* Philips SECAM */ + .name = "Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF)", + .params = tuner_philips_secam_params, + }, + [TUNER_ABSENT] = { /* Tuner Absent */ + .name = "NoTuner", + }, + [TUNER_PHILIPS_PAL] = { /* Philips PAL */ + .name = "Philips PAL_BG (FI1216 and compatibles)", + .params = tuner_philips_pal_params, + }, + [TUNER_TEMIC_NTSC] = { /* TEMIC NTSC */ + .name = "Temic NTSC (4032 FY5)", + .params = tuner_temic_ntsc_params, + }, + [TUNER_TEMIC_PAL_I] = { /* TEMIC PAL_I */ + .name = "Temic PAL_I (4062 FY5)", + .params = tuner_temic_pal_i_params, + }, + [TUNER_TEMIC_4036FY5_NTSC] = { /* TEMIC NTSC */ + .name = "Temic NTSC (4036 FY5)", + .params = tuner_temic_4036fy5_ntsc_params, + }, + [TUNER_ALPS_TSBH1_NTSC] = { /* TEMIC NTSC */ + .name = "Alps HSBH1", + .params = tuner_alps_tsbh1_ntsc_params, + }, + + /* 10-19 */ + [TUNER_ALPS_TSBE1_PAL] = { /* TEMIC PAL */ + .name = "Alps TSBE1", + .params = tuner_alps_tsb_1_params, + }, + [TUNER_ALPS_TSBB5_PAL_I] = { /* Alps PAL_I */ + .name = "Alps TSBB5", + .params = tuner_alps_tsbb5_params, + }, + [TUNER_ALPS_TSBE5_PAL] = { /* Alps PAL */ + .name = "Alps TSBE5", + .params = tuner_alps_tsbe5_params, + }, + [TUNER_ALPS_TSBC5_PAL] = { /* Alps PAL */ + .name = "Alps TSBC5", + .params = tuner_alps_tsbc5_params, + }, + [TUNER_TEMIC_4006FH5_PAL] = { /* TEMIC PAL */ + .name = "Temic PAL_BG (4006FH5)", + .params = tuner_temic_4006fh5_params, + }, + [TUNER_ALPS_TSHC6_NTSC] = { /* Alps NTSC */ + .name = "Alps TSCH6", + .params = tuner_alps_tshc6_params, + }, + [TUNER_TEMIC_PAL_DK] = { /* TEMIC PAL */ + .name = "Temic PAL_DK (4016 FY5)", + .params = tuner_temic_pal_dk_params, + }, + [TUNER_PHILIPS_NTSC_M] = { /* Philips NTSC */ + .name = "Philips NTSC_M (MK2)", + .params = tuner_philips_ntsc_m_params, + }, + [TUNER_TEMIC_4066FY5_PAL_I] = { /* TEMIC PAL_I */ + .name = "Temic PAL_I (4066 FY5)", + .params = tuner_temic_4066fy5_pal_i_params, + }, + [TUNER_TEMIC_4006FN5_MULTI_PAL] = { /* TEMIC PAL */ + .name = "Temic PAL* auto (4006 FN5)", + .params = tuner_temic_4006fn5_multi_params, + }, + + /* 20-29 */ + [TUNER_TEMIC_4009FR5_PAL] = { /* TEMIC PAL */ + .name = "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)", + .params = tuner_temic_4009f_5_params, + }, + [TUNER_TEMIC_4039FR5_NTSC] = { /* TEMIC NTSC */ + .name = "Temic NTSC (4039 FR5)", + .params = tuner_temic_4039fr5_params, + }, + [TUNER_TEMIC_4046FM5] = { /* TEMIC PAL */ + .name = "Temic PAL/SECAM multi (4046 FM5)", + .params = tuner_temic_4046fm5_params, + }, + [TUNER_PHILIPS_PAL_DK] = { /* Philips PAL */ + .name = "Philips PAL_DK (FI1256 and compatibles)", + .params = tuner_philips_pal_dk_params, + }, + [TUNER_PHILIPS_FQ1216ME] = { /* Philips PAL */ + .name = "Philips PAL/SECAM multi (FQ1216ME)", + .params = tuner_philips_fq1216me_params, + }, + [TUNER_LG_PAL_I_FM] = { /* LGINNOTEK PAL_I */ + .name = "LG PAL_I+FM (TAPC-I001D)", + .params = tuner_lg_pal_i_fm_params, + }, + [TUNER_LG_PAL_I] = { /* LGINNOTEK PAL_I */ + .name = "LG PAL_I (TAPC-I701D)", + .params = tuner_lg_pal_i_params, + }, + [TUNER_LG_NTSC_FM] = { /* LGINNOTEK NTSC */ + .name = "LG NTSC+FM (TPI8NSR01F)", + .params = tuner_lg_ntsc_fm_params, + }, + [TUNER_LG_PAL_FM] = { /* LGINNOTEK PAL */ + .name = "LG PAL_BG+FM (TPI8PSB01D)", + .params = tuner_lg_pal_fm_params, + }, + [TUNER_LG_PAL] = { /* LGINNOTEK PAL */ + .name = "LG PAL_BG (TPI8PSB11D)", + .params = tuner_lg_pal_params, + }, + + /* 30-39 */ + [TUNER_TEMIC_4009FN5_MULTI_PAL_FM] = { /* TEMIC PAL */ + .name = "Temic PAL* auto + FM (4009 FN5)", + .params = tuner_temic_4009_fn5_multi_pal_fm_params, + }, + [TUNER_SHARP_2U5JF5540_NTSC] = { /* SHARP NTSC */ + .name = "SHARP NTSC_JP (2U5JF5540)", + .params = tuner_sharp_2u5jf5540_params, + }, + [TUNER_Samsung_PAL_TCPM9091PD27] = { /* Samsung PAL */ + .name = "Samsung PAL TCPM9091PD27", + .params = tuner_samsung_pal_tcpm9091pd27_params, + }, + [TUNER_MT2032] = { /* Microtune PAL|NTSC */ + .name = "MT20xx universal", + /* see mt20xx.c for details */ }, + [TUNER_TEMIC_4106FH5] = { /* TEMIC PAL */ + .name = "Temic PAL_BG (4106 FH5)", + .params = tuner_temic_4106fh5_params, + }, + [TUNER_TEMIC_4012FY5] = { /* TEMIC PAL */ + .name = "Temic PAL_DK/SECAM_L (4012 FY5)", + .params = tuner_temic_4012fy5_params, + }, + [TUNER_TEMIC_4136FY5] = { /* TEMIC NTSC */ + .name = "Temic NTSC (4136 FY5)", + .params = tuner_temic_4136_fy5_params, + }, + [TUNER_LG_PAL_NEW_TAPC] = { /* LGINNOTEK PAL */ + .name = "LG PAL (newer TAPC series)", + .params = tuner_lg_pal_new_tapc_params, + }, + [TUNER_PHILIPS_FM1216ME_MK3] = { /* Philips PAL */ + .name = "Philips PAL/SECAM multi (FM1216ME MK3)", + .params = tuner_fm1216me_mk3_params, + }, + [TUNER_LG_NTSC_NEW_TAPC] = { /* LGINNOTEK NTSC */ + .name = "LG NTSC (newer TAPC series)", + .params = tuner_lg_ntsc_new_tapc_params, + }, + + /* 40-49 */ + [TUNER_HITACHI_NTSC] = { /* HITACHI NTSC */ + .name = "HITACHI V7-J180AT", + .params = tuner_hitachi_ntsc_params, + }, + [TUNER_PHILIPS_PAL_MK] = { /* Philips PAL */ + .name = "Philips PAL_MK (FI1216 MK)", + .params = tuner_philips_pal_mk_params, + }, + [TUNER_PHILIPS_ATSC] = { /* Philips ATSC */ + .name = "Philips 1236D ATSC/NTSC dual in", + .params = tuner_philips_atsc_params, + }, + [TUNER_PHILIPS_FM1236_MK3] = { /* Philips NTSC */ + .name = "Philips NTSC MK3 (FM1236MK3 or FM1236/F)", + .params = tuner_fm1236_mk3_params, + }, + [TUNER_PHILIPS_4IN1] = { /* Philips NTSC */ + .name = "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)", + .params = tuner_philips_4in1_params, + }, + [TUNER_MICROTUNE_4049FM5] = { /* Microtune PAL */ + .name = "Microtune 4049 FM5", + .params = tuner_microtune_4049_fm5_params, + }, + [TUNER_PANASONIC_VP27] = { /* Panasonic NTSC */ + .name = "Panasonic VP27s/ENGE4324D", + .params = tuner_panasonic_vp27_params, + }, + [TUNER_LG_NTSC_TAPE] = { /* LGINNOTEK NTSC */ + .name = "LG NTSC (TAPE series)", + .params = tuner_lg_ntsc_tape_params, + }, + [TUNER_TNF_8831BGFF] = { /* Philips PAL */ + .name = "Tenna TNF 8831 BGFF)", + .params = tuner_tnf_8831bgff_params, + }, + [TUNER_MICROTUNE_4042FI5] = { /* Microtune NTSC */ + .name = "Microtune 4042 FI5 ATSC/NTSC dual in", + .params = tuner_microtune_4042fi5_params, + }, + + /* 50-59 */ + [TUNER_TCL_2002N] = { /* TCL NTSC */ + .name = "TCL 2002N", + .params = tuner_tcl_2002n_params, + }, + [TUNER_PHILIPS_FM1256_IH3] = { /* Philips PAL */ + .name = "Philips PAL/SECAM_D (FM 1256 I-H3)", + .params = tuner_philips_fm1256_ih3_params, + }, + [TUNER_THOMSON_DTT7610] = { /* THOMSON ATSC */ + .name = "Thomson DTT 7610 (ATSC/NTSC)", + .params = tuner_thomson_dtt7610_params, + }, + [TUNER_PHILIPS_FQ1286] = { /* Philips NTSC */ + .name = "Philips FQ1286", + .params = tuner_philips_fq1286_params, + }, + [TUNER_PHILIPS_TDA8290] = { /* Philips PAL|NTSC */ + .name = "tda8290+75", + /* see tda8290.c for details */ }, + [TUNER_TCL_2002MB] = { /* TCL PAL */ + .name = "TCL 2002MB", + .params = tuner_tcl_2002mb_params, + }, + [TUNER_PHILIPS_FQ1216AME_MK4] = { /* Philips PAL */ + .name = "Philips PAL/SECAM multi (FQ1216AME MK4)", + .params = tuner_philips_fq1216ame_mk4_params, + }, + [TUNER_PHILIPS_FQ1236A_MK4] = { /* Philips NTSC */ + .name = "Philips FQ1236A MK4", + .params = tuner_philips_fq1236a_mk4_params, + }, + [TUNER_YMEC_TVF_8531MF] = { /* Philips NTSC */ + .name = "Ymec TVision TVF-8531MF/8831MF/8731MF", + .params = tuner_ymec_tvf_8531mf_params, + }, + [TUNER_YMEC_TVF_5533MF] = { /* Philips NTSC */ + .name = "Ymec TVision TVF-5533MF", + .params = tuner_ymec_tvf_5533mf_params, + }, + + /* 60-69 */ + [TUNER_THOMSON_DTT761X] = { /* THOMSON ATSC */ + /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */ + .name = "Thomson DTT 761X (ATSC/NTSC)", + .params = tuner_thomson_dtt761x_params, + }, + [TUNER_TENA_9533_DI] = { /* Philips PAL */ + .name = "Tena TNF9533-D/IF/TNF9533-B/DF", + .params = tuner_tena_9533_di_params, + }, + [TUNER_TEA5767] = { /* Philips RADIO */ + .name = "Philips TEA5767HN FM Radio", + /* see tea5767.c for details */ + }, + [TUNER_PHILIPS_FMD1216ME_MK3] = { /* Philips PAL */ + .name = "Philips FMD1216ME MK3 Hybrid Tuner", + .params = tuner_tuner_philips_fmd1216me_mk3_params, + }, + [TUNER_LG_TDVS_H062F] = { /* LGINNOTEK ATSC */ + .name = "LG TDVS-H062F/TUA6034", + .params = tuner_tua6034_params, + }, + [TUNER_YMEC_TVF66T5_B_DFF] = { /* Philips PAL */ + .name = "Ymec TVF66T5-B/DFF", + .params = tuner_ymec_tvf66t5_b_dff_params, + }, + [TUNER_LG_NTSC_TALN_MINI] = { /* LGINNOTEK NTSC */ + .name = "LG NTSC (TALN mini series)", + .params = tuner_lg_taln_mini_params, + }, + [TUNER_PHILIPS_TD1316] = { /* Philips PAL */ + .name = "Philips TD1316 Hybrid Tuner", + .params = tuner_philips_td1316_params, + }, + [TUNER_PHILIPS_TUV1236D] = { /* Philips ATSC */ + .name = "Philips TUV1236D ATSC/NTSC dual in", + .params = tuner_tuner_tuv1236d_params, + }, + [TUNER_TNF_5335MF] = { /* Philips NTSC */ + .name = "Tena TNF 5335 MF", + .params = tuner_tnf_5335mf_params, + }, +}; + +unsigned const int tuner_count = ARRAY_SIZE(tuners); diff --git a/include/media/tuner-types.h b/include/media/tuner-types.h new file mode 100644 index 00000000000..9f6e4a98c40 --- /dev/null +++ b/include/media/tuner-types.h @@ -0,0 +1,41 @@ +/* + * descriptions for simple tuners. + */ + +#ifndef __TUNER_TYPES_H__ +#define __TUNER_TYPES_H__ + +enum param_type { + TUNER_PARAM_TYPE_RADIO, \ + TUNER_PARAM_TYPE_PAL, \ + TUNER_PARAM_TYPE_SECAM, \ + TUNER_PARAM_TYPE_NTSC, \ + TUNER_PARAM_TYPE_ATSC, \ + TUNER_PARAM_TYPE_DVBT, \ + TUNER_PARAM_TYPE_DVBS, \ + TUNER_PARAM_TYPE_DVBC +}; + +struct tuner_range { + unsigned short limit; + unsigned char cb; +}; + +struct tuner_params { + enum param_type type; + unsigned char config; /* to be moved into struct tuner_range for dvb-pll merge */ + + unsigned int count; + struct tuner_range *ranges; +}; + +struct tunertype { + char *name; + unsigned int has_tda988x:1; + struct tuner_params *params; +}; + +extern struct tunertype tuners[]; +extern unsigned const int tuner_count; + +#endif diff --git a/include/media/tuner.h b/include/media/tuner.h index 27cbf08c931..c88b506971c 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -23,6 +23,7 @@ #define _TUNER_H #include +#include #define ADDR_UNSET (255) -- GitLab From b3d37042d7d33baf0247d1df31031e64427f39b3 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 13 Jan 2006 14:10:25 -0200 Subject: [PATCH 073/465] V4L/DVB (3363): Add support for Samsung tuner TCPN 2121P30A - Add support for Samsung tuner TCPN 2121P30A, used in Hauppauge PVR-500 cards. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.tuner | 1 + drivers/media/video/tuner-types.c | 24 ++++++++++++++++++++++++ drivers/media/video/tveeprom.c | 2 +- include/media/tuner.h | 1 + 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner index 0bf3d5bf9ef..f6d0cf7b792 100644 --- a/Documentation/video4linux/CARDLIST.tuner +++ b/Documentation/video4linux/CARDLIST.tuner @@ -68,3 +68,4 @@ tuner=66 - LG NTSC (TALN mini series) tuner=67 - Philips TD1316 Hybrid Tuner tuner=68 - Philips TUV1236D ATSC/NTSC dual in tuner=69 - Tena TNF 5335 MF +tuner=70 - Samsung TCPN 2121P30A diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index de9d4925d8e..32c9be4c5ca 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -1077,6 +1077,24 @@ static struct tuner_params tuner_tnf_5335mf_params[] = { }, }; +/* 70-79 */ +/* ------------ TUNER_SAMSUNG_TCPN_2121P30A - Samsung NTSC ------------ */ + +static struct tuner_range tuner_samsung_tcpn_2121p30a_ntsc_ranges[] = { + { 16 * 175.75 /*MHz*/, 0x01, }, + { 16 * 410.25 /*MHz*/, 0x02, }, + { 16 * 999.99 , 0x08, }, +}; + +static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = { + { + .type = TUNER_PARAM_TYPE_NTSC, + .ranges = tuner_samsung_tcpn_2121p30a_ntsc_ranges, + .count = ARRAY_SIZE(tuner_samsung_tcpn_2121p30a_ntsc_ranges), + .config = 0xce, + }, +}; + /* --------------------------------------------------------------------- */ struct tunertype tuners[] = { @@ -1371,6 +1389,12 @@ struct tunertype tuners[] = { .name = "Tena TNF 5335 MF", .params = tuner_tnf_5335mf_params, }, + + /* 70-79 */ + [TUNER_SAMSUNG_TCPN_2121P30A] = { /* Samsung NTSC */ + .name = "Samsung TCPN 2121P30A", + .params = tuner_samsung_tcpn_2121p30a_params, + }, }; unsigned const int tuner_count = ARRAY_SIZE(tuners); diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 5e71a354e87..582551b0969 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -190,7 +190,7 @@ hauppauge_tuner[] = { TUNER_LG_PAL_NEW_TAPC, "TCL 2002MI 3"}, { TUNER_TCL_2002N, "TCL 2002N 6A"}, { TUNER_PHILIPS_FM1236_MK3, "Philips FQ1236 MK3"}, - { TUNER_ABSENT, "Samsung TCPN 2121P30A"}, + { TUNER_SAMSUNG_TCPN_2121P30A, "Samsung TCPN 2121P30A"}, { TUNER_ABSENT, "Samsung TCPE 4121P30A"}, { TUNER_PHILIPS_FM1216ME_MK3, "TCL MFPE05 2"}, /* 90-99 */ diff --git a/include/media/tuner.h b/include/media/tuner.h index c88b506971c..a1d63787bc0 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -115,6 +115,7 @@ #define TUNER_PHILIPS_TUV1236D 68 /* ATI HDTV Wonder */ #define TUNER_TNF_5335MF 69 /* Sabrent Bt848 */ +#define TUNER_SAMSUNG_TCPN_2121P30A 70 /* Hauppauge PVR-500MCE NTSC */ /* tv card specific */ #define TDA9887_PRESENT (1<<0) -- GitLab From c943aa859c392eb4cc76d911daa1f261555075b2 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 13 Jan 2006 14:10:26 -0200 Subject: [PATCH 074/465] V4L/DVB (3364): disable all dvb tuner param_types until we need them - Add param_type dvbs2 - disable all dvb param_types, which will not be needed until we merge dvb-pll. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- include/media/tuner-types.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/include/media/tuner-types.h b/include/media/tuner-types.h index 9f6e4a98c40..64b16b1f192 100644 --- a/include/media/tuner-types.h +++ b/include/media/tuner-types.h @@ -9,11 +9,7 @@ enum param_type { TUNER_PARAM_TYPE_RADIO, \ TUNER_PARAM_TYPE_PAL, \ TUNER_PARAM_TYPE_SECAM, \ - TUNER_PARAM_TYPE_NTSC, \ - TUNER_PARAM_TYPE_ATSC, \ - TUNER_PARAM_TYPE_DVBT, \ - TUNER_PARAM_TYPE_DVBS, \ - TUNER_PARAM_TYPE_DVBC + TUNER_PARAM_TYPE_NTSC }; struct tuner_range { -- GitLab From 8a430d74fea797fc55fef1ad4c21420212b83574 Mon Sep 17 00:00:00 2001 From: Evgeniy Date: Fri, 13 Jan 2006 18:12:15 +0300 Subject: [PATCH 075/465] [PATCH] Fix oops in ufs_fill_super at mount time There's a lack of parenthesis in fs/ufs/utils.h, so instead of the 512th byte of buffer, the usb2 pointer will point to the nth structure of type ufs_super_block_second. This can cause a mount-time oops if you're unlucky (especially with DEBUG_PAGEALLOC, which is how Alexey Dobriyan saw this problem) Signed-off-by: Evgeniy Dushistov Acked-by: Alexey Dobriyan Signed-off-by: Linus Torvalds --- fs/ufs/util.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ufs/util.h b/fs/ufs/util.h index b2640076679..e45ad537987 100644 --- a/fs/ufs/util.h +++ b/fs/ufs/util.h @@ -255,8 +255,8 @@ extern void _ubh_memcpyubh_(struct ufs_sb_private_info *, struct ufs_buffer_head ((struct ufs_super_block_first *)((ubh)->bh[0]->b_data)) #define ubh_get_usb_second(ubh) \ - ((struct ufs_super_block_second *)(ubh)-> \ - bh[UFS_SECTOR_SIZE >> uspi->s_fshift]->b_data + (UFS_SECTOR_SIZE & ~uspi->s_fmask)) + ((struct ufs_super_block_second *)((ubh)->\ + bh[UFS_SECTOR_SIZE >> uspi->s_fshift]->b_data + (UFS_SECTOR_SIZE & ~uspi->s_fmask))) #define ubh_get_usb_third(ubh) \ ((struct ufs_super_block_third *)((ubh)-> \ -- GitLab From 67daf5f11f06b9b15f8320de1d237ccc2e74fe43 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Fri, 13 Jan 2006 14:23:25 +1100 Subject: [PATCH 076/465] [PATCH] Increase AT_VECTOR_SIZE On PowerPC, we want to be able to provide an AT_PLATFORM aux table entry to userspace, so that glibc can choose optimized libraries for the processor we're running on. Unfortunately that would be the 21st aux table entry on powerpc, meaning that the aux table including the terminating null entry would overflow the mm->saved_auxv[] array, leading to userland programs segfaulting. This increases the size of the mm->saved_auxv array to be large enough to accommodate an AT_PLATFORM entry on powerpc. Signed-off-by: Paul Mackerras Signed-off-by: Linus Torvalds --- include/linux/auxvec.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/auxvec.h b/include/linux/auxvec.h index 9a7b374c9fb..d2bc0d66e65 100644 --- a/include/linux/auxvec.h +++ b/include/linux/auxvec.h @@ -26,6 +26,6 @@ #define AT_SECURE 23 /* secure mode boolean */ -#define AT_VECTOR_SIZE 42 /* Size of auxiliary table. */ +#define AT_VECTOR_SIZE 44 /* Size of auxiliary table. */ #endif /* _LINUX_AUXVEC_H */ -- GitLab From 7ae69d2aa4ed3ee8cef18a072346366f019d6a4a Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Fri, 13 Jan 2006 10:03:58 -0800 Subject: [PATCH 077/465] [IA64] Add stub entry to fsys.S for sys_migrate_pages When this new syscall was added to ia64 in commit 39743889aaf76725152f16aa90ca3c45f6d52da3 fsys.S was forgotten. Add a ".data8 0" there to keep it in step. [Reported by Stephane Eranian] Signed-off-by: Tony Luck --- arch/ia64/kernel/fsys.S | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S index 2ddbac6f499..ce423910ca9 100644 --- a/arch/ia64/kernel/fsys.S +++ b/arch/ia64/kernel/fsys.S @@ -903,5 +903,6 @@ fsyscall_table: data8 0 data8 0 data8 0 + data8 0 // 1280 .org fsyscall_table + 8*NR_syscalls // guard against failures to increase NR_syscalls -- GitLab From 246c7e33d51afe99890b2caab7ad482c0296d5ba Mon Sep 17 00:00:00 2001 From: Dean Nelson Date: Thu, 22 Dec 2005 14:32:56 -0600 Subject: [PATCH 078/465] [IA64-SGI] ensure XPC disengage request is processed This patch fixes a problem in XPC disengage processing whereby it was not seeing the request to disengage from a remote partition, so the disengage wasn't happening. The disengagement is suppose to transpire during the time a XPC channel is disconnecting, and should be completed before the channel is declared to be disconnected. Signed-off-by: Dean Nelson Signed-off-by: Tony Luck --- arch/ia64/sn/kernel/xpc.h | 2 +- arch/ia64/sn/kernel/xpc_channel.c | 20 ++++++++++++-------- arch/ia64/sn/kernel/xpc_main.c | 2 +- arch/ia64/sn/kernel/xpc_partition.c | 3 ++- include/asm-ia64/sn/xp.h | 4 +++- 5 files changed, 19 insertions(+), 12 deletions(-) diff --git a/arch/ia64/sn/kernel/xpc.h b/arch/ia64/sn/kernel/xpc.h index 5483a9f227d..66b17b6aa81 100644 --- a/arch/ia64/sn/kernel/xpc.h +++ b/arch/ia64/sn/kernel/xpc.h @@ -707,7 +707,7 @@ extern void xpc_connected_callout(struct xpc_channel *); extern void xpc_deliver_msg(struct xpc_channel *); extern void xpc_disconnect_channel(const int, struct xpc_channel *, enum xpc_retval, unsigned long *); -extern void xpc_disconnecting_callout(struct xpc_channel *); +extern void xpc_disconnect_callout(struct xpc_channel *, enum xpc_retval); extern void xpc_partition_going_down(struct xpc_partition *, enum xpc_retval); extern void xpc_teardown_infrastructure(struct xpc_partition *); diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c index abf4fc2a87b..272ab4deb57 100644 --- a/arch/ia64/sn/kernel/xpc_channel.c +++ b/arch/ia64/sn/kernel/xpc_channel.c @@ -779,6 +779,12 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags) /* both sides are disconnected now */ + if (ch->flags & XPC_C_CONNECTCALLOUT) { + spin_unlock_irqrestore(&ch->lock, *irq_flags); + xpc_disconnect_callout(ch, xpcDisconnected); + spin_lock_irqsave(&ch->lock, *irq_flags); + } + /* it's now safe to free the channel's message queues */ xpc_free_msgqueues(ch); @@ -1645,7 +1651,7 @@ xpc_disconnect_channel(const int line, struct xpc_channel *ch, void -xpc_disconnecting_callout(struct xpc_channel *ch) +xpc_disconnect_callout(struct xpc_channel *ch, enum xpc_retval reason) { /* * Let the channel's registerer know that the channel is being @@ -1654,15 +1660,13 @@ xpc_disconnecting_callout(struct xpc_channel *ch) */ if (ch->func != NULL) { - dev_dbg(xpc_chan, "ch->func() called, reason=xpcDisconnecting," - " partid=%d, channel=%d\n", ch->partid, ch->number); + dev_dbg(xpc_chan, "ch->func() called, reason=%d, partid=%d, " + "channel=%d\n", reason, ch->partid, ch->number); - ch->func(xpcDisconnecting, ch->partid, ch->number, NULL, - ch->key); + ch->func(reason, ch->partid, ch->number, NULL, ch->key); - dev_dbg(xpc_chan, "ch->func() returned, reason=" - "xpcDisconnecting, partid=%d, channel=%d\n", - ch->partid, ch->number); + dev_dbg(xpc_chan, "ch->func() returned, reason=%d, partid=%d, " + "channel=%d\n", reason, ch->partid, ch->number); } } diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c index b617236524c..6708ef6e061 100644 --- a/arch/ia64/sn/kernel/xpc_main.c +++ b/arch/ia64/sn/kernel/xpc_main.c @@ -773,7 +773,7 @@ xpc_daemonize_kthread(void *args) ch->flags |= XPC_C_DISCONNECTCALLOUT; spin_unlock_irqrestore(&ch->lock, irq_flags); - xpc_disconnecting_callout(ch); + xpc_disconnect_callout(ch, xpcDisconnecting); } else { spin_unlock_irqrestore(&ch->lock, irq_flags); } diff --git a/arch/ia64/sn/kernel/xpc_partition.c b/arch/ia64/sn/kernel/xpc_partition.c index cdd6431853a..cf02a9bcd24 100644 --- a/arch/ia64/sn/kernel/xpc_partition.c +++ b/arch/ia64/sn/kernel/xpc_partition.c @@ -771,7 +771,8 @@ xpc_identify_act_IRQ_req(int nasid) } } - if (!xpc_partition_disengaged(part)) { + if (part->disengage_request_timeout > 0 && + !xpc_partition_disengaged(part)) { /* still waiting on other side to disengage from us */ return; } diff --git a/include/asm-ia64/sn/xp.h b/include/asm-ia64/sn/xp.h index 49faf8f2643..203945ae034 100644 --- a/include/asm-ia64/sn/xp.h +++ b/include/asm-ia64/sn/xp.h @@ -227,7 +227,9 @@ enum xpc_retval { xpcOpenCloseError, /* 50: channel open/close protocol error */ - xpcUnknownReason /* 51: unknown reason -- must be last in list */ + xpcDisconnected, /* 51: channel disconnected (closed) */ + + xpcUnknownReason /* 52: unknown reason -- must be last in list */ }; -- GitLab From 1ecaded80f94f2779160529aef7d6f37a22c2f60 Mon Sep 17 00:00:00 2001 From: Dean Nelson Date: Fri, 6 Jan 2006 09:48:21 -0600 Subject: [PATCH 079/465] [IA64-SGI] cleanup XPC disengage related messages Cleanup the XPC disengage related messages that are printed to the log. Signed-off-by: Dean Nelson Signed-off-by: Tony Luck --- arch/ia64/sn/kernel/xpc.h | 1 + arch/ia64/sn/kernel/xpc_main.c | 87 +++++++++++++++++++++-------- arch/ia64/sn/kernel/xpc_partition.c | 3 + 3 files changed, 68 insertions(+), 23 deletions(-) diff --git a/arch/ia64/sn/kernel/xpc.h b/arch/ia64/sn/kernel/xpc.h index 66b17b6aa81..82e7430be78 100644 --- a/arch/ia64/sn/kernel/xpc.h +++ b/arch/ia64/sn/kernel/xpc.h @@ -663,6 +663,7 @@ extern struct xpc_registration xpc_registrations[]; extern struct device *xpc_part; extern struct device *xpc_chan; extern int xpc_disengage_request_timelimit; +extern int xpc_disengage_request_timedout; extern irqreturn_t xpc_notify_IRQ_handler(int, void *, struct pt_regs *); extern void xpc_dropped_IPI_check(struct xpc_partition *); extern void xpc_activate_partition(struct xpc_partition *); diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c index 6708ef6e061..948206b13f6 100644 --- a/arch/ia64/sn/kernel/xpc_main.c +++ b/arch/ia64/sn/kernel/xpc_main.c @@ -162,6 +162,8 @@ static ctl_table xpc_sys_dir[] = { }; static struct ctl_table_header *xpc_sysctl; +/* non-zero if any remote partition disengage request was timed out */ +int xpc_disengage_request_timedout; /* #of IRQs received */ static atomic_t xpc_act_IRQ_rcvd; @@ -921,9 +923,9 @@ static void xpc_do_exit(enum xpc_retval reason) { partid_t partid; - int active_part_count; + int active_part_count, printed_waiting_msg = 0; struct xpc_partition *part; - unsigned long printmsg_time; + unsigned long printmsg_time, disengage_request_timeout = 0; /* a 'rmmod XPC' and a 'reboot' cannot both end up here together */ @@ -953,7 +955,8 @@ xpc_do_exit(enum xpc_retval reason) /* wait for all partitions to become inactive */ - printmsg_time = jiffies; + printmsg_time = jiffies + (XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ); + xpc_disengage_request_timedout = 0; do { active_part_count = 0; @@ -969,20 +972,39 @@ xpc_do_exit(enum xpc_retval reason) active_part_count++; XPC_DEACTIVATE_PARTITION(part, reason); - } - if (active_part_count == 0) { - break; + if (part->disengage_request_timeout > + disengage_request_timeout) { + disengage_request_timeout = + part->disengage_request_timeout; + } } - if (jiffies >= printmsg_time) { - dev_info(xpc_part, "waiting for partitions to " - "deactivate/disengage, active count=%d, remote " - "engaged=0x%lx\n", active_part_count, - xpc_partition_engaged(1UL << partid)); - - printmsg_time = jiffies + + if (xpc_partition_engaged(-1UL)) { + if (time_after(jiffies, printmsg_time)) { + dev_info(xpc_part, "waiting for remote " + "partitions to disengage, timeout in " + "%ld seconds\n", + (disengage_request_timeout - jiffies) + / HZ); + printmsg_time = jiffies + (XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ); + printed_waiting_msg = 1; + } + + } else if (active_part_count > 0) { + if (printed_waiting_msg) { + dev_info(xpc_part, "waiting for local partition" + " to disengage\n"); + printed_waiting_msg = 0; + } + + } else { + if (!xpc_disengage_request_timedout) { + dev_info(xpc_part, "all partitions have " + "disengaged\n"); + } + break; } /* sleep for a 1/3 of a second or so */ @@ -1028,7 +1050,7 @@ xpc_die_disengage(void) struct xpc_partition *part; partid_t partid; unsigned long engaged; - long time, print_time, disengage_request_timeout; + long time, printmsg_time, disengage_request_timeout; /* keep xpc_hb_checker thread from doing anything (just in case) */ @@ -1055,24 +1077,43 @@ xpc_die_disengage(void) } } - print_time = rtc_time(); - disengage_request_timeout = print_time + + time = rtc_time(); + printmsg_time = time + + (XPC_DISENGAGE_PRINTMSG_INTERVAL * sn_rtc_cycles_per_second); + disengage_request_timeout = time + (xpc_disengage_request_timelimit * sn_rtc_cycles_per_second); /* wait for all other partitions to disengage from us */ - while ((engaged = xpc_partition_engaged(-1UL)) && - (time = rtc_time()) < disengage_request_timeout) { + while (1) { + engaged = xpc_partition_engaged(-1UL); + if (!engaged) { + dev_info(xpc_part, "all partitions have disengaged\n"); + break; + } - if (time >= print_time) { + time = rtc_time(); + if (time >= disengage_request_timeout) { + for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) { + if (engaged & (1UL << partid)) { + dev_info(xpc_part, "disengage from " + "remote partition %d timed " + "out\n", partid); + } + } + break; + } + + if (time >= printmsg_time) { dev_info(xpc_part, "waiting for remote partitions to " - "disengage, engaged=0x%lx\n", engaged); - print_time = time + (XPC_DISENGAGE_PRINTMSG_INTERVAL * + "disengage, timeout in %ld seconds\n", + (disengage_request_timeout - time) / + sn_rtc_cycles_per_second); + printmsg_time = time + + (XPC_DISENGAGE_PRINTMSG_INTERVAL * sn_rtc_cycles_per_second); } } - dev_info(xpc_part, "finished waiting for remote partitions to " - "disengage, engaged=0x%lx\n", engaged); } diff --git a/arch/ia64/sn/kernel/xpc_partition.c b/arch/ia64/sn/kernel/xpc_partition.c index cf02a9bcd24..6bc0409628c 100644 --- a/arch/ia64/sn/kernel/xpc_partition.c +++ b/arch/ia64/sn/kernel/xpc_partition.c @@ -874,6 +874,9 @@ xpc_partition_disengaged(struct xpc_partition *part) * request in a timely fashion, so assume it's dead. */ + dev_info(xpc_part, "disengage from remote partition %d " + "timed out\n", partid); + xpc_disengage_request_timedout = 1; xpc_clear_partition_engaged(1UL << partid); disengaged = 1; } -- GitLab From 0752c670d83362609c7f3f59ffa0e180709c60c2 Mon Sep 17 00:00:00 2001 From: Dean Nelson Date: Tue, 10 Jan 2006 11:07:19 -0600 Subject: [PATCH 080/465] [IA64-SGI] XPC and unregistering from notifier lists Only unregister from notifier lists if XPC is unloading. Signed-off-by: Dean Nelson Signed-off-by: Tony Luck --- arch/ia64/sn/kernel/xpc_main.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c index 948206b13f6..dcac286dab3 100644 --- a/arch/ia64/sn/kernel/xpc_main.c +++ b/arch/ia64/sn/kernel/xpc_main.c @@ -1022,11 +1022,13 @@ xpc_do_exit(enum xpc_retval reason) del_timer_sync(&xpc_hb_timer); DBUG_ON(xpc_vars->heartbeating_to_mask != 0); - /* take ourselves off of the reboot_notifier_list */ - (void) unregister_reboot_notifier(&xpc_reboot_notifier); + if (reason == xpcUnloading) { + /* take ourselves off of the reboot_notifier_list */ + (void) unregister_reboot_notifier(&xpc_reboot_notifier); - /* take ourselves off of the die_notifier list */ - (void) unregister_die_notifier(&xpc_die_notifier); + /* take ourselves off of the die_notifier list */ + (void) unregister_die_notifier(&xpc_die_notifier); + } /* close down protections for IPI operations */ xpc_restrict_IPI_ops(); -- GitLab From 1f4674b2d5f63bac4c393ac4de1d6c1b6b72c09c Mon Sep 17 00:00:00 2001 From: Dean Nelson Date: Tue, 10 Jan 2006 11:08:00 -0600 Subject: [PATCH 081/465] [IA64-SGI] ignoring loss of heartbeat while XPC is in kdebug Allow for the loss of heartbeat while in kdebug to be ignored by remote partitions. Signed-off-by: Dean Nelson Signed-off-by: Tony Luck --- arch/ia64/sn/kernel/xpc_main.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c index dcac286dab3..db57b46bddd 100644 --- a/arch/ia64/sn/kernel/xpc_main.c +++ b/arch/ia64/sn/kernel/xpc_main.c @@ -82,6 +82,9 @@ struct device *xpc_part = &xpc_part_dbg_subname; struct device *xpc_chan = &xpc_chan_dbg_subname; +static int xpc_kdebug_ignore; + + /* systune related variables for /proc/sys directories */ static int xpc_hb_interval = XPC_HB_DEFAULT_INTERVAL; @@ -1148,7 +1151,12 @@ xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused) /* - * This function is called when the system is being rebooted. + * This function is called when the system is being restarted or halted due + * to some sort of system failure. If this is the case we need to notify the + * other partitions to disengage from all references to our memory. + * This function can also be called when our heartbeater could be offlined + * for a time. In this case we need to notify other partitions to not worry + * about the lack of a heartbeat. */ static int xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) @@ -1158,11 +1166,25 @@ xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) case DIE_MACHINE_HALT: xpc_die_disengage(); break; + + case DIE_KDEBUG_ENTER: + /* Should lack of heartbeat be ignored by other partitions? */ + if (!xpc_kdebug_ignore) { + break; + } + /* fall through */ case DIE_MCA_MONARCH_ENTER: case DIE_INIT_MONARCH_ENTER: xpc_vars->heartbeat++; xpc_vars->heartbeat_offline = 1; break; + + case DIE_KDEBUG_LEAVE: + /* Is lack of heartbeat being ignored by other partitions? */ + if (!xpc_kdebug_ignore) { + break; + } + /* fall through */ case DIE_MCA_MONARCH_LEAVE: case DIE_INIT_MONARCH_LEAVE: xpc_vars->heartbeat++; @@ -1387,3 +1409,7 @@ module_param(xpc_disengage_request_timelimit, int, 0); MODULE_PARM_DESC(xpc_disengage_request_timelimit, "Number of seconds to wait " "for disengage request to complete."); +module_param(xpc_kdebug_ignore, int, 0); +MODULE_PARM_DESC(xpc_kdebug_ignore, "Should lack of heartbeat be ignored by " + "other partitions when dropping into kdebug."); + -- GitLab From d6ad033a88b42420ddb6c62c95e42f88d862b246 Mon Sep 17 00:00:00 2001 From: Dean Nelson Date: Tue, 10 Jan 2006 11:08:55 -0600 Subject: [PATCH 082/465] [IA64-SGI] move xpc_system_reboot() Move xpc_system_reboot() to be closer to the file it calls for readability reasons (which are indeed subjective). Signed-off-by: Dean Nelson Signed-off-by: Tony Luck --- arch/ia64/sn/kernel/xpc_main.c | 58 +++++++++++++++++----------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c index db57b46bddd..50a0c09bca8 100644 --- a/arch/ia64/sn/kernel/xpc_main.c +++ b/arch/ia64/sn/kernel/xpc_main.c @@ -1047,7 +1047,35 @@ xpc_do_exit(enum xpc_retval reason) /* - * Called when the system is about to be either restarted or halted. + * This function is called when the system is being rebooted. + */ +static int +xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused) +{ + enum xpc_retval reason; + + + switch (event) { + case SYS_RESTART: + reason = xpcSystemReboot; + break; + case SYS_HALT: + reason = xpcSystemHalt; + break; + case SYS_POWER_OFF: + reason = xpcSystemPoweroff; + break; + default: + reason = xpcSystemGoingDown; + } + + xpc_do_exit(reason); + return NOTIFY_DONE; +} + + +/* + * Notify other partitions to disengage from all references to our memory. */ static void xpc_die_disengage(void) @@ -1122,34 +1150,6 @@ xpc_die_disengage(void) } -/* - * This function is called when the system is being rebooted. - */ -static int -xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused) -{ - enum xpc_retval reason; - - - switch (event) { - case SYS_RESTART: - reason = xpcSystemReboot; - break; - case SYS_HALT: - reason = xpcSystemHalt; - break; - case SYS_POWER_OFF: - reason = xpcSystemPoweroff; - break; - default: - reason = xpcSystemGoingDown; - } - - xpc_do_exit(reason); - return NOTIFY_DONE; -} - - /* * This function is called when the system is being restarted or halted due * to some sort of system failure. If this is the case we need to notify the -- GitLab From 87a149d6bba5949fbc53b8a21189b54748ac9e2a Mon Sep 17 00:00:00 2001 From: Dean Nelson Date: Tue, 10 Jan 2006 11:09:48 -0600 Subject: [PATCH 083/465] [IA64-SGI] move xpc.h to include/asm-ia64/sn Move xpc.h from arch/ia64/sn/kernel to include/asm-ia64/sn without change. Signed-off-by: Dean Nelson Signed-off-by: Tony Luck --- {arch/ia64/sn/kernel => include/asm-ia64/sn}/xpc.h | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {arch/ia64/sn/kernel => include/asm-ia64/sn}/xpc.h (100%) diff --git a/arch/ia64/sn/kernel/xpc.h b/include/asm-ia64/sn/xpc.h similarity index 100% rename from arch/ia64/sn/kernel/xpc.h rename to include/asm-ia64/sn/xpc.h -- GitLab From 9335d48e10d2d07eacaddf889ec1efb8a5a5082e Mon Sep 17 00:00:00 2001 From: Dean Nelson Date: Tue, 10 Jan 2006 11:12:32 -0600 Subject: [PATCH 084/465] [IA64-SGI] move xpc.h to include/asm-ia64/sn (cleanup) Cleanup a few items after moving xpc.h from arch/ia64/sn/kernel to include/asm-ia64/sn. Signed-off-by: Dean Nelson Signed-off-by: Tony Luck --- arch/ia64/sn/kernel/xpc_channel.c | 4 ++-- arch/ia64/sn/kernel/xpc_main.c | 4 ++-- arch/ia64/sn/kernel/xpc_partition.c | 4 ++-- include/asm-ia64/sn/xpc.h | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c index 272ab4deb57..0c0a6890240 100644 --- a/arch/ia64/sn/kernel/xpc_channel.c +++ b/arch/ia64/sn/kernel/xpc_channel.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved. */ @@ -24,7 +24,7 @@ #include #include #include -#include "xpc.h" +#include /* diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c index 50a0c09bca8..8930586e0eb 100644 --- a/arch/ia64/sn/kernel/xpc_main.c +++ b/arch/ia64/sn/kernel/xpc_main.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved. */ @@ -59,7 +59,7 @@ #include #include #include -#include "xpc.h" +#include /* define two XPC debug device structures to be used with dev_dbg() et al */ diff --git a/arch/ia64/sn/kernel/xpc_partition.c b/arch/ia64/sn/kernel/xpc_partition.c index 6bc0409628c..88a730e6cfd 100644 --- a/arch/ia64/sn/kernel/xpc_partition.c +++ b/arch/ia64/sn/kernel/xpc_partition.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved. */ @@ -28,7 +28,7 @@ #include #include #include -#include "xpc.h" +#include /* XPC is exiting flag */ diff --git a/include/asm-ia64/sn/xpc.h b/include/asm-ia64/sn/xpc.h index 82e7430be78..87e9cd58851 100644 --- a/include/asm-ia64/sn/xpc.h +++ b/include/asm-ia64/sn/xpc.h @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved. */ @@ -11,8 +11,8 @@ * Cross Partition Communication (XPC) structures and macros. */ -#ifndef _IA64_SN_KERNEL_XPC_H -#define _IA64_SN_KERNEL_XPC_H +#ifndef _ASM_IA64_SN_XPC_H +#define _ASM_IA64_SN_XPC_H #include @@ -1270,5 +1270,5 @@ xpc_check_for_channel_activity(struct xpc_partition *part) } -#endif /* _IA64_SN_KERNEL_XPC_H */ +#endif /* _ASM_IA64_SN_XPC_H */ -- GitLab From bd37e5a951ad2123d3f51f59c407b5242946b6ba Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Thu, 5 Jan 2006 13:19:55 +0100 Subject: [PATCH 085/465] [PATCH] INPUT: add MODALIAS to the event environment input: add MODALIAS to the event environment Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/input/input.c | 55 +++++++++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/drivers/input/input.c b/drivers/input/input.c index fe33ff334e2..4fe3da3c667 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -528,40 +528,56 @@ INPUT_DEV_STRING_ATTR_SHOW(name); INPUT_DEV_STRING_ATTR_SHOW(phys); INPUT_DEV_STRING_ATTR_SHOW(uniq); -static int print_modalias_bits(char *buf, char prefix, unsigned long *arr, +static int print_modalias_bits(char *buf, int size, char prefix, unsigned long *arr, unsigned int min, unsigned int max) { int len, i; - len = sprintf(buf, "%c", prefix); + len = snprintf(buf, size, "%c", prefix); for (i = min; i < max; i++) if (arr[LONG(i)] & BIT(i)) - len += sprintf(buf+len, "%X,", i); + len += snprintf(buf + len, size - len, "%X,", i); return len; } -static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf) +static int print_modalias(char *buf, int size, struct input_dev *id) { - struct input_dev *id = to_input_dev(dev); - ssize_t len = 0; + int len; - len += sprintf(buf+len, "input:b%04Xv%04Xp%04Xe%04X-", + len = snprintf(buf, size, "input:b%04Xv%04Xp%04Xe%04X-", id->id.bustype, id->id.vendor, id->id.product, id->id.version); - len += print_modalias_bits(buf+len, 'e', id->evbit, 0, EV_MAX); - len += print_modalias_bits(buf+len, 'k', id->keybit, + len += print_modalias_bits(buf + len, size - len, 'e', id->evbit, + 0, EV_MAX); + len += print_modalias_bits(buf + len, size - len, 'k', id->keybit, KEY_MIN_INTERESTING, KEY_MAX); - len += print_modalias_bits(buf+len, 'r', id->relbit, 0, REL_MAX); - len += print_modalias_bits(buf+len, 'a', id->absbit, 0, ABS_MAX); - len += print_modalias_bits(buf+len, 'm', id->mscbit, 0, MSC_MAX); - len += print_modalias_bits(buf+len, 'l', id->ledbit, 0, LED_MAX); - len += print_modalias_bits(buf+len, 's', id->sndbit, 0, SND_MAX); - len += print_modalias_bits(buf+len, 'f', id->ffbit, 0, FF_MAX); - len += print_modalias_bits(buf+len, 'w', id->swbit, 0, SW_MAX); - len += sprintf(buf+len, "\n"); + len += print_modalias_bits(buf + len, size - len, 'r', id->relbit, + 0, REL_MAX); + len += print_modalias_bits(buf + len, size - len, 'a', id->absbit, + 0, ABS_MAX); + len += print_modalias_bits(buf + len, size - len, 'm', id->mscbit, + 0, MSC_MAX); + len += print_modalias_bits(buf + len, size - len, 'l', id->ledbit, + 0, LED_MAX); + len += print_modalias_bits(buf + len, size - len, 's', id->sndbit, + 0, SND_MAX); + len += print_modalias_bits(buf + len, size - len, 'f', id->ffbit, + 0, FF_MAX); + len += print_modalias_bits(buf + len, size - len, 'w', id->swbit, + 0, SW_MAX); + return len; +} + +static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf) +{ + struct input_dev *id = to_input_dev(dev); + ssize_t len; + + len = print_modalias(buf, PAGE_SIZE, id); + len += snprintf(buf + len, PAGE_SIZE-len, "\n"); return len; } static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL); @@ -728,8 +744,11 @@ static int input_dev_uevent(struct class_device *cdev, char **envp, if (test_bit(EV_SW, dev->evbit)) INPUT_ADD_HOTPLUG_BM_VAR("SW=", dev->swbit, SW_MAX); - envp[i] = NULL; + envp[i++] = buffer + len; + len += snprintf(buffer + len, buffer_size - len, "MODALIAS="); + len += print_modalias(buffer + len, buffer_size - len, dev) + 1; + envp[i] = NULL; return 0; } -- GitLab From 594c8281f90560faf9632d91bb9d402cbe560e63 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 5 Jan 2006 14:29:51 +0000 Subject: [PATCH 086/465] [PATCH] Add bus_type probe, remove, shutdown methods. Add bus_type probe, remove and shutdown methods to replace the corresponding methods in struct device_driver. This matches the way we handle the suspend/resume methods. Since the bus methods override the device_driver methods, warn if a device driver is registered whose methods will not be called. The long-term idea is to remove the device_driver methods entirely. Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 12 ++++++++++-- drivers/base/driver.c | 5 +++++ drivers/base/power/shutdown.c | 5 ++++- include/linux/device.h | 3 +++ 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 2b905016664..730a9ce0a14 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -78,7 +78,13 @@ int driver_probe_device(struct device_driver * drv, struct device * dev) pr_debug("%s: Matched Device %s with Driver %s\n", drv->bus->name, dev->bus_id, drv->name); dev->driver = drv; - if (drv->probe) { + if (dev->bus->probe) { + ret = dev->bus->probe(dev); + if (ret) { + dev->driver = NULL; + goto ProbeFailed; + } + } else if (drv->probe) { ret = drv->probe(dev); if (ret) { dev->driver = NULL; @@ -203,7 +209,9 @@ static void __device_release_driver(struct device * dev) sysfs_remove_link(&dev->kobj, "driver"); klist_remove(&dev->knode_driver); - if (drv->remove) + if (dev->bus->remove) + dev->bus->remove(dev); + else if (drv->remove) drv->remove(dev); dev->driver = NULL; put_driver(drv); diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 161f3a390d9..b400314e1c6 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -171,6 +171,11 @@ static void klist_devices_put(struct klist_node *n) */ int driver_register(struct device_driver * drv) { + if ((drv->bus->probe && drv->probe) || + (drv->bus->remove && drv->remove) || + (drv->bus->shutdown && drv->shutdown)) { + printk(KERN_WARNING "Driver '%s' needs updating - please use bus_type methods\n", drv->name); + } klist_init(&drv->klist_devices, klist_devices_get, klist_devices_put); init_completion(&drv->unloaded); return bus_add_driver(drv); diff --git a/drivers/base/power/shutdown.c b/drivers/base/power/shutdown.c index f50a08be424..a47bb74da72 100644 --- a/drivers/base/power/shutdown.c +++ b/drivers/base/power/shutdown.c @@ -40,7 +40,10 @@ void device_shutdown(void) down_write(&devices_subsys.rwsem); list_for_each_entry_reverse(dev, &devices_subsys.kset.list, kobj.entry) { - if (dev->driver && dev->driver->shutdown) { + if (dev->bus && dev->bus->shutdown) { + dev_dbg(dev, "shutdown\n"); + dev->bus->shutdown(dev); + } else if (dev->driver && dev->driver->shutdown) { dev_dbg(dev, "shutdown\n"); dev->driver->shutdown(dev); } diff --git a/include/linux/device.h b/include/linux/device.h index 0cdee78e5ce..58df18d9cd3 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -49,6 +49,9 @@ struct bus_type { int (*match)(struct device * dev, struct device_driver * drv); int (*uevent)(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size); + int (*probe)(struct device * dev); + int (*remove)(struct device * dev); + void (*shutdown)(struct device * dev); int (*suspend)(struct device * dev, pm_message_t state); int (*resume)(struct device * dev); }; -- GitLab From b15d686a2b589c9e4f1ea116553e9c3c3d030dae Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 5 Jan 2006 14:30:22 +0000 Subject: [PATCH 087/465] [PATCH] Add pci_bus_type probe and remove methods Move the PCI bus device probe/remove methods to the bus_type structure. We leave the shutdown method alone since there are compatibility issues with that. Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci-driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 7146b69b812..0aa14c92b57 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -380,8 +380,6 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner) /* initialize common driver fields */ drv->driver.name = drv->name; drv->driver.bus = &pci_bus_type; - drv->driver.probe = pci_device_probe; - drv->driver.remove = pci_device_remove; /* FIXME, once all of the existing PCI drivers have been fixed to set * the pci shutdown function, this test can go away. */ if (!drv->driver.shutdown) @@ -513,6 +511,8 @@ struct bus_type pci_bus_type = { .name = "pci", .match = pci_bus_match, .uevent = pci_uevent, + .probe = pci_device_probe, + .remove = pci_device_remove, .suspend = pci_device_suspend, .resume = pci_device_resume, .dev_attrs = pci_dev_attrs, -- GitLab From e08b754161d6de4f91e2d3c805f350b35a95d8b8 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 5 Jan 2006 14:30:57 +0000 Subject: [PATCH 088/465] [PATCH] Add ecard_bus_type probe/remove/shutdown methods Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/kernel/ecard.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c index 96fd91926c9..74ea29c3205 100644 --- a/arch/arm/kernel/ecard.c +++ b/arch/arm/kernel/ecard.c @@ -1147,9 +1147,11 @@ static void ecard_drv_shutdown(struct device *dev) struct ecard_driver *drv = ECARD_DRV(dev->driver); struct ecard_request req; - if (drv->shutdown) - drv->shutdown(ec); - ecard_release(ec); + if (dev->driver) { + if (drv->shutdown) + drv->shutdown(ec); + ecard_release(ec); + } /* * If this card has a loader, call the reset handler. @@ -1164,9 +1166,6 @@ static void ecard_drv_shutdown(struct device *dev) int ecard_register_driver(struct ecard_driver *drv) { drv->drv.bus = &ecard_bus_type; - drv->drv.probe = ecard_drv_probe; - drv->drv.remove = ecard_drv_remove; - drv->drv.shutdown = ecard_drv_shutdown; return driver_register(&drv->drv); } @@ -1195,6 +1194,9 @@ struct bus_type ecard_bus_type = { .name = "ecard", .dev_attrs = ecard_dev_attrs, .match = ecard_match, + .probe = ecard_drv_probe, + .remove = ecard_drv_remove, + .shutdown = ecard_drv_shutdown, }; static int ecard_bus_init(void) -- GitLab From 2876ba4321f0f85c40726b736eeaadf317803f16 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 5 Jan 2006 14:32:32 +0000 Subject: [PATCH 089/465] [PATCH] Add SA1111 bus_type probe/remove methods Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/common/sa1111.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c index d0d6e6d2d64..1475089f9b4 100644 --- a/arch/arm/common/sa1111.c +++ b/arch/arm/common/sa1111.c @@ -1247,14 +1247,14 @@ static int sa1111_bus_remove(struct device *dev) struct bus_type sa1111_bus_type = { .name = "sa1111-rab", .match = sa1111_match, + .probe = sa1111_bus_probe, + .remove = sa1111_bus_remove, .suspend = sa1111_bus_suspend, .resume = sa1111_bus_resume, }; int sa1111_driver_register(struct sa1111_driver *driver) { - driver->drv.probe = sa1111_bus_probe; - driver->drv.remove = sa1111_bus_remove; driver->drv.bus = &sa1111_bus_type; return driver_register(&driver->drv); } -- GitLab From 306955be37dd1b1f232f19766227ccccb83f7873 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 5 Jan 2006 14:33:04 +0000 Subject: [PATCH 090/465] [PATCH] Add locomo bus_type probe/remove methods Signed-off-by: Russell King Signed-off-by: Richard Purdie Signed-off-by: Greg Kroah-Hartman --- arch/arm/common/locomo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c index 1b7eaab02b9..159ad7ed7a4 100644 --- a/arch/arm/common/locomo.c +++ b/arch/arm/common/locomo.c @@ -1103,14 +1103,14 @@ static int locomo_bus_remove(struct device *dev) struct bus_type locomo_bus_type = { .name = "locomo-bus", .match = locomo_match, + .probe = locomo_bus_probe, + .remove = locomo_bus_remove, .suspend = locomo_bus_suspend, .resume = locomo_bus_resume, }; int locomo_driver_register(struct locomo_driver *driver) { - driver->drv.probe = locomo_bus_probe; - driver->drv.remove = locomo_bus_remove; driver->drv.bus = &locomo_bus_type; return driver_register(&driver->drv); } -- GitLab From 5c0784c350516856ed15deb6adf6b053bf427792 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 5 Jan 2006 14:33:35 +0000 Subject: [PATCH 091/465] [PATCH] Add logic module bus_type probe/remove methods Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-integrator/lm.c | 36 +++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/arch/arm/mach-integrator/lm.c b/arch/arm/mach-integrator/lm.c index 5b41e3a724e..622cdc4212d 100644 --- a/arch/arm/mach-integrator/lm.c +++ b/arch/arm/mach-integrator/lm.c @@ -22,20 +22,6 @@ static int lm_match(struct device *dev, struct device_driver *drv) return 1; } -static struct bus_type lm_bustype = { - .name = "logicmodule", - .match = lm_match, -// .suspend = lm_suspend, -// .resume = lm_resume, -}; - -static int __init lm_init(void) -{ - return bus_register(&lm_bustype); -} - -postcore_initcall(lm_init); - static int lm_bus_probe(struct device *dev) { struct lm_device *lmdev = to_lm_device(dev); @@ -49,16 +35,30 @@ static int lm_bus_remove(struct device *dev) struct lm_device *lmdev = to_lm_device(dev); struct lm_driver *lmdrv = to_lm_driver(dev->driver); - lmdrv->remove(lmdev); + if (lmdrv->remove) + lmdrv->remove(lmdev); return 0; } +static struct bus_type lm_bustype = { + .name = "logicmodule", + .match = lm_match, + .probe = lm_bus_probe, + .remove = lm_bus_remove, +// .suspend = lm_bus_suspend, +// .resume = lm_bus_resume, +}; + +static int __init lm_init(void) +{ + return bus_register(&lm_bustype); +} + +postcore_initcall(lm_init); + int lm_driver_register(struct lm_driver *drv) { drv->drv.bus = &lm_bustype; - drv->drv.probe = lm_bus_probe; - drv->drv.remove = lm_bus_remove; - return driver_register(&drv->drv); } -- GitLab From 83dfb8b67522f6cf1fc5771a8be0a9095eea65d4 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 5 Jan 2006 14:34:06 +0000 Subject: [PATCH 092/465] [PATCH] Add tiocx bus_type probe/remove methods Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/ia64/sn/kernel/tiocx.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c index 493fb3f38dc..6a7939b16a1 100644 --- a/arch/ia64/sn/kernel/tiocx.c +++ b/arch/ia64/sn/kernel/tiocx.c @@ -77,12 +77,6 @@ static void tiocx_bus_release(struct device *dev) kfree(to_cx_dev(dev)); } -struct bus_type tiocx_bus_type = { - .name = "tiocx", - .match = tiocx_match, - .uevent = tiocx_uevent, -}; - /** * cx_device_match - Find cx_device in the id table. * @ids: id table from driver @@ -149,6 +143,14 @@ static int cx_driver_remove(struct device *dev) return 0; } +struct bus_type tiocx_bus_type = { + .name = "tiocx", + .match = tiocx_match, + .uevent = tiocx_uevent, + .probe = cx_device_probe, + .remove = cx_driver_remove, +}; + /** * cx_driver_register - Register the driver. * @cx_driver: driver table (cx_drv struct) from driver @@ -162,8 +164,6 @@ int cx_driver_register(struct cx_drv *cx_driver) { cx_driver->driver.name = cx_driver->name; cx_driver->driver.bus = &tiocx_bus_type; - cx_driver->driver.probe = cx_device_probe; - cx_driver->driver.remove = cx_driver_remove; return driver_register(&cx_driver->driver); } -- GitLab From ad3ed31c682d956d2187e562635c55c8c74c1021 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 5 Jan 2006 14:34:38 +0000 Subject: [PATCH 093/465] [PATCH] Add parisc_bus_type probe and remove methods Signed-off-by: Russell King Acked-by: Matthew Wilcox Signed-off-by: Greg Kroah-Hartman --- arch/parisc/kernel/drivers.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c index 1eaa0d37f67..2d804e2d16d 100644 --- a/arch/parisc/kernel/drivers.c +++ b/arch/parisc/kernel/drivers.c @@ -173,8 +173,6 @@ int register_parisc_driver(struct parisc_driver *driver) WARN_ON(driver->drv.probe != NULL); WARN_ON(driver->drv.remove != NULL); - driver->drv.probe = parisc_driver_probe; - driver->drv.remove = parisc_driver_remove; driver->drv.name = driver->name; return driver_register(&driver->drv); @@ -575,6 +573,8 @@ struct bus_type parisc_bus_type = { .name = "parisc", .match = parisc_generic_match, .dev_attrs = parisc_device_attrs, + .probe = parisc_driver_probe, + .remove = parisc_driver_remove, }; /** -- GitLab From 91fb53866d00b4eaeaf1cbfd2237799cb152f742 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 5 Jan 2006 14:35:09 +0000 Subject: [PATCH 094/465] [PATCH] Add ocp_bus_type probe and remove methods Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/ppc/syslib/ocp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/ppc/syslib/ocp.c b/arch/ppc/syslib/ocp.c index 9ccce438bd7..ab34b1d6072 100644 --- a/arch/ppc/syslib/ocp.c +++ b/arch/ppc/syslib/ocp.c @@ -189,6 +189,8 @@ ocp_device_resume(struct device *dev) struct bus_type ocp_bus_type = { .name = "ocp", .match = ocp_device_match, + .probe = ocp_driver_probe, + .remove = ocp_driver_remove, .suspend = ocp_device_suspend, .resume = ocp_device_resume, }; @@ -210,8 +212,6 @@ ocp_register_driver(struct ocp_driver *drv) /* initialize common driver fields */ drv->driver.name = drv->name; drv->driver.bus = &ocp_bus_type; - drv->driver.probe = ocp_device_probe; - drv->driver.remove = ocp_device_remove; /* register with core */ return driver_register(&drv->driver); -- GitLab From c6a09196bab3bc9e515b713193d61e3e87c720f7 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 5 Jan 2006 14:35:42 +0000 Subject: [PATCH 095/465] [PATCH] Add sh_bus_type probe and remove methods Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/sh/kernel/cpu/bus.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/arch/sh/kernel/cpu/bus.c b/arch/sh/kernel/cpu/bus.c index d4fee2a7937..3278d234bb1 100644 --- a/arch/sh/kernel/cpu/bus.c +++ b/arch/sh/kernel/cpu/bus.c @@ -53,21 +53,6 @@ static int sh_bus_resume(struct device *dev) return 0; } -static struct device sh_bus_devices[SH_NR_BUSES] = { - { - .bus_id = SH_BUS_NAME_VIRT, - }, -}; - -struct bus_type sh_bus_types[SH_NR_BUSES] = { - { - .name = SH_BUS_NAME_VIRT, - .match = sh_bus_match, - .suspend = sh_bus_suspend, - .resume = sh_bus_resume, - }, -}; - static int sh_device_probe(struct device *dev) { struct sh_dev *shdev = to_sh_dev(dev); @@ -90,6 +75,23 @@ static int sh_device_remove(struct device *dev) return 0; } +static struct device sh_bus_devices[SH_NR_BUSES] = { + { + .bus_id = SH_BUS_NAME_VIRT, + }, +}; + +struct bus_type sh_bus_types[SH_NR_BUSES] = { + { + .name = SH_BUS_NAME_VIRT, + .match = sh_bus_match, + .probe = sh_bus_probe, + .remove = sh_bus_remove, + .suspend = sh_bus_suspend, + .resume = sh_bus_resume, + }, +}; + int sh_device_register(struct sh_dev *dev) { if (!dev) @@ -133,8 +135,6 @@ int sh_driver_register(struct sh_driver *drv) return -EINVAL; } - drv->drv.probe = sh_device_probe; - drv->drv.remove = sh_device_remove; drv->drv.bus = &sh_bus_types[drv->bus_id]; return driver_register(&drv->drv); -- GitLab From 79f9fb8886d901fd549793a4ad632ece51c68405 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 5 Jan 2006 14:36:16 +0000 Subject: [PATCH 096/465] [PATCH] Add of_platform_bus_type probe and remove methods Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/of_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c index 7065e40e2f4..22d83d4d1af 100644 --- a/arch/powerpc/kernel/of_device.c +++ b/arch/powerpc/kernel/of_device.c @@ -132,6 +132,8 @@ static int of_device_resume(struct device * dev) struct bus_type of_platform_bus_type = { .name = "of_platform", .match = of_platform_bus_match, + .probe = of_device_probe, + .remove = of_device_remove, .suspend = of_device_suspend, .resume = of_device_resume, }; @@ -150,8 +152,6 @@ int of_register_driver(struct of_platform_driver *drv) /* initialize common driver fields */ drv->driver.name = drv->name; drv->driver.bus = &of_platform_bus_type; - drv->driver.probe = of_device_probe; - drv->driver.remove = of_device_remove; /* register with core */ count = driver_register(&drv->driver); -- GitLab From 2f53a80fc0f6287d4bd6cc2422cd095c90f30410 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 5 Jan 2006 14:36:47 +0000 Subject: [PATCH 097/465] [PATCH] Add vio_bus_type probe and remove methods Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/vio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index 13c41495fe0..13c655ba284 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -76,7 +76,7 @@ static void vio_bus_shutdown(struct device *dev) struct vio_dev *viodev = to_vio_dev(dev); struct vio_driver *viodrv = to_vio_driver(dev->driver); - if (viodrv->shutdown) + if (dev->driver && viodrv->shutdown) viodrv->shutdown(viodev); } @@ -91,9 +91,6 @@ int vio_register_driver(struct vio_driver *viodrv) /* fill in 'struct driver' fields */ viodrv->driver.bus = &vio_bus_type; - viodrv->driver.probe = vio_bus_probe; - viodrv->driver.remove = vio_bus_remove; - viodrv->driver.shutdown = vio_bus_shutdown; return driver_register(&viodrv->driver); } @@ -295,4 +292,7 @@ struct bus_type vio_bus_type = { .name = "vio", .uevent = vio_hotplug, .match = vio_bus_match, + .probe = vio_bus_probe, + .remove = vio_bus_remove, + .shutdown = vio_bus_shutdown, }; -- GitLab From 5b34bf88779fa965a134b92ab61688e0d1ddfe1d Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 5 Jan 2006 14:37:18 +0000 Subject: [PATCH 098/465] [PATCH] Add dio_bus_type probe and remove methods Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/dio/dio-driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/dio/dio-driver.c b/drivers/dio/dio-driver.c index ffe6f44ac76..ca8e69d2f64 100644 --- a/drivers/dio/dio-driver.c +++ b/drivers/dio/dio-driver.c @@ -83,7 +83,6 @@ int dio_register_driver(struct dio_driver *drv) /* initialize common driver fields */ drv->driver.name = drv->name; drv->driver.bus = &dio_bus_type; - drv->driver.probe = dio_device_probe; /* register with core */ count = driver_register(&drv->driver); @@ -145,7 +144,8 @@ static int dio_bus_match(struct device *dev, struct device_driver *drv) struct bus_type dio_bus_type = { .name = "dio", - .match = dio_bus_match + .match = dio_bus_match, + .probe = dio_device_probe, }; -- GitLab From b864c7d5d17c171c4ead0791b44ab05d7a21dc0c Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 5 Jan 2006 14:37:50 +0000 Subject: [PATCH 099/465] [PATCH] Add i2c_bus_type probe and remove methods Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/i2c-core.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 52b77477df5..0ce58b50604 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -63,13 +63,6 @@ static int i2c_bus_resume(struct device * dev) return rc; } -struct bus_type i2c_bus_type = { - .name = "i2c", - .match = i2c_device_match, - .suspend = i2c_bus_suspend, - .resume = i2c_bus_resume, -}; - static int i2c_device_probe(struct device *dev) { return -ENODEV; @@ -80,6 +73,15 @@ static int i2c_device_remove(struct device *dev) return 0; } +struct bus_type i2c_bus_type = { + .name = "i2c", + .match = i2c_device_match, + .probe = i2c_device_probe, + .remove = i2c_device_remove, + .suspend = i2c_bus_suspend, + .resume = i2c_bus_resume, +}; + void i2c_adapter_dev_release(struct device *dev) { struct i2c_adapter *adap = dev_to_i2c_adapter(dev); @@ -90,8 +92,6 @@ struct device_driver i2c_adapter_driver = { .owner = THIS_MODULE, .name = "i2c_adapter", .bus = &i2c_bus_type, - .probe = i2c_device_probe, - .remove = i2c_device_remove, }; static void i2c_adapter_class_dev_release(struct class_device *dev) @@ -294,8 +294,6 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) /* add the driver to the list of i2c drivers in the driver core */ driver->driver.owner = owner; driver->driver.bus = &i2c_bus_type; - driver->driver.probe = i2c_device_probe; - driver->driver.remove = i2c_device_remove; res = driver_register(&driver->driver); if (res) -- GitLab From 29a4a20e9fe7459f9d464b8be070ce8b7335be7e Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 5 Jan 2006 14:38:22 +0000 Subject: [PATCH 100/465] [PATCH] Add gameport bus_type probe and remove methods Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/input/gameport/gameport.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index caac6d63d46..b765a155c00 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c @@ -50,9 +50,7 @@ static DECLARE_MUTEX(gameport_sem); static LIST_HEAD(gameport_list); -static struct bus_type gameport_bus = { - .name = "gameport", -}; +static struct bus_type gameport_bus; static void gameport_add_port(struct gameport *gameport); static void gameport_destroy_port(struct gameport *gameport); @@ -703,11 +701,15 @@ static int gameport_driver_remove(struct device *dev) return 0; } +static struct bus_type gameport_bus = { + .name = "gameport", + .probe = gameport_driver_probe, + .remove = gameport_driver_remove, +}; + void __gameport_register_driver(struct gameport_driver *drv, struct module *owner) { drv->driver.bus = &gameport_bus; - drv->driver.probe = gameport_driver_probe; - drv->driver.remove = gameport_driver_remove; gameport_queue_event(drv, owner, GAMEPORT_REGISTER_DRIVER); } -- GitLab From 30226f8199cb7f5ace767f65bcebb85941612dfc Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 5 Jan 2006 14:38:53 +0000 Subject: [PATCH 101/465] [PATCH] Add serio bus_type probe and remove methods Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/input/serio/serio.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 8e530cc970e..2f76813c3a6 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -59,9 +59,7 @@ static DECLARE_MUTEX(serio_sem); static LIST_HEAD(serio_list); -static struct bus_type serio_bus = { - .name = "serio", -}; +static struct bus_type serio_bus; static void serio_add_port(struct serio *serio); static void serio_destroy_port(struct serio *serio); @@ -750,11 +748,15 @@ static int serio_driver_remove(struct device *dev) return 0; } +static struct bus_type serio_bus = { + .name = "serio", + .probe = serio_driver_probe, + .remove = serio_driver_remove, +}; + void __serio_register_driver(struct serio_driver *drv, struct module *owner) { drv->driver.bus = &serio_bus; - drv->driver.probe = serio_driver_probe; - drv->driver.remove = serio_driver_remove; serio_queue_event(drv, owner, SERIO_REGISTER_DRIVER); } -- GitLab From 4866b124a1ded3b94b0cea0bd543f46ffa9a3943 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 5 Jan 2006 14:39:24 +0000 Subject: [PATCH 102/465] [PATCH] Add macio_bus_type probe and remove methods Signed-off-by: Russell King Acked-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- drivers/macintosh/macio_asic.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 2a545ceb523..ed6d3174d66 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c @@ -211,6 +211,9 @@ struct bus_type macio_bus_type = { .name = "macio", .match = macio_bus_match, .uevent = macio_uevent, + .probe = macio_device_probe, + .remove = macio_device_remove, + .shutdown = macio_device_shutdown, .suspend = macio_device_suspend, .resume = macio_device_resume, .dev_attrs = macio_dev_attrs, @@ -528,9 +531,6 @@ int macio_register_driver(struct macio_driver *drv) /* initialize common driver fields */ drv->driver.name = drv->name; drv->driver.bus = &macio_bus_type; - drv->driver.probe = macio_device_probe; - drv->driver.remove = macio_device_remove; - drv->driver.shutdown = macio_device_shutdown; /* register with core */ count = driver_register(&drv->driver); -- GitLab From 413b486e18587fd53c9954252e6648f9450c734e Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 5 Jan 2006 14:39:56 +0000 Subject: [PATCH 103/465] [PATCH] Add MCP bus_type probe and remove methods Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/mfd/mcp-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c index 55ba23075c9..75f401d52fd 100644 --- a/drivers/mfd/mcp-core.c +++ b/drivers/mfd/mcp-core.c @@ -77,6 +77,8 @@ static int mcp_bus_resume(struct device *dev) static struct bus_type mcp_bus_type = { .name = "mcp", .match = mcp_bus_match, + .probe = mcp_bus_probe, + .remove = mcp_bus_remove, .suspend = mcp_bus_suspend, .resume = mcp_bus_resume, }; @@ -227,8 +229,6 @@ EXPORT_SYMBOL(mcp_host_unregister); int mcp_driver_register(struct mcp_driver *mcpdrv) { mcpdrv->drv.bus = &mcp_bus_type; - mcpdrv->drv.probe = mcp_bus_probe; - mcpdrv->drv.remove = mcp_bus_remove; return driver_register(&mcpdrv->drv); } EXPORT_SYMBOL(mcp_driver_register); -- GitLab From 4d0b653cdfde193944784c01fa3359b0a444dcf1 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 5 Jan 2006 14:40:27 +0000 Subject: [PATCH 104/465] [PATCH] Add mmc_bus_type probe and remove methods Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/mmc_sysfs.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c index ec701667abf..a2a35fd946e 100644 --- a/drivers/mmc/mmc_sysfs.c +++ b/drivers/mmc/mmc_sysfs.c @@ -136,17 +136,7 @@ static int mmc_bus_resume(struct device *dev) return ret; } -static struct bus_type mmc_bus_type = { - .name = "mmc", - .dev_attrs = mmc_dev_attrs, - .match = mmc_bus_match, - .uevent = mmc_bus_uevent, - .suspend = mmc_bus_suspend, - .resume = mmc_bus_resume, -}; - - -static int mmc_drv_probe(struct device *dev) +static int mmc_bus_probe(struct device *dev) { struct mmc_driver *drv = to_mmc_driver(dev->driver); struct mmc_card *card = dev_to_mmc_card(dev); @@ -154,7 +144,7 @@ static int mmc_drv_probe(struct device *dev) return drv->probe(card); } -static int mmc_drv_remove(struct device *dev) +static int mmc_bus_remove(struct device *dev) { struct mmc_driver *drv = to_mmc_driver(dev->driver); struct mmc_card *card = dev_to_mmc_card(dev); @@ -164,6 +154,16 @@ static int mmc_drv_remove(struct device *dev) return 0; } +static struct bus_type mmc_bus_type = { + .name = "mmc", + .dev_attrs = mmc_dev_attrs, + .match = mmc_bus_match, + .uevent = mmc_bus_uevent, + .probe = mmc_bus_probe, + .remove = mmc_bus_remove, + .suspend = mmc_bus_suspend, + .resume = mmc_bus_resume, +}; /** * mmc_register_driver - register a media driver @@ -172,8 +172,6 @@ static int mmc_drv_remove(struct device *dev) int mmc_register_driver(struct mmc_driver *drv) { drv->drv.bus = &mmc_bus_type; - drv->drv.probe = mmc_drv_probe; - drv->drv.remove = mmc_drv_remove; return driver_register(&drv->drv); } -- GitLab From 1d0baa3a1c836f0403b318d549fd49ebc73ee631 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 5 Jan 2006 14:40:58 +0000 Subject: [PATCH 105/465] [PATCH] Add pcmcia_bus_type probe and remove methods Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/pcmcia/ds.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 621ec459d27..0a424a4e818 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -311,8 +311,6 @@ int pcmcia_register_driver(struct pcmcia_driver *driver) /* initialize common fields */ driver->drv.bus = &pcmcia_bus_type; driver->drv.owner = driver->owner; - driver->drv.probe = pcmcia_device_probe; - driver->drv.remove = pcmcia_device_remove; return driver_register(&driver->drv); } @@ -1200,6 +1198,8 @@ struct bus_type pcmcia_bus_type = { .uevent = pcmcia_bus_uevent, .match = pcmcia_bus_match, .dev_attrs = pcmcia_dev_attrs, + .probe = pcmcia_device_probe, + .remove = pcmcia_device_remove, .suspend = pcmcia_dev_suspend, .resume = pcmcia_dev_resume, }; -- GitLab From 4681fc320889de4591f945c4fdf08546eb9ab266 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 5 Jan 2006 14:41:37 +0000 Subject: [PATCH 106/465] [PATCH] Add pnp_bus_type probe and remove methods Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/pnp/driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c index 15fb758a9e5..7cafacdd12b 100644 --- a/drivers/pnp/driver.c +++ b/drivers/pnp/driver.c @@ -195,6 +195,8 @@ static int pnp_bus_resume(struct device *dev) struct bus_type pnp_bus_type = { .name = "pnp", .match = pnp_bus_match, + .probe = pnp_device_probe, + .remove = pnp_device_remove, .suspend = pnp_bus_suspend, .resume = pnp_bus_resume, }; @@ -215,8 +217,6 @@ int pnp_register_driver(struct pnp_driver *drv) drv->driver.name = drv->name; drv->driver.bus = &pnp_bus_type; - drv->driver.probe = pnp_device_probe; - drv->driver.remove = pnp_device_remove; count = driver_register(&drv->driver); -- GitLab From f9ccf4569ac4597e9e09d301ca362d90b4a1046d Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 5 Jan 2006 14:42:09 +0000 Subject: [PATCH 107/465] [PATCH] Add ccwgroup_bus_type probe and remove methods Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/s390/cio/ccwgroup.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index e849289d4f3..503a568e47c 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -52,11 +52,7 @@ ccwgroup_uevent (struct device *dev, char **envp, int num_envp, char *buffer, return 0; } -static struct bus_type ccwgroup_bus_type = { - .name = "ccwgroup", - .match = ccwgroup_bus_match, - .uevent = ccwgroup_uevent, -}; +static struct bus_type ccwgroup_bus_type; static inline void __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev) @@ -389,6 +385,14 @@ ccwgroup_remove (struct device *dev) return 0; } +static struct bus_type ccwgroup_bus_type = { + .name = "ccwgroup", + .match = ccwgroup_bus_match, + .uevent = ccwgroup_uevent, + .probe = ccwgroup_probe, + .remove = ccwgroup_remove, +}; + int ccwgroup_driver_register (struct ccwgroup_driver *cdriver) { @@ -396,8 +400,6 @@ ccwgroup_driver_register (struct ccwgroup_driver *cdriver) cdriver->driver = (struct device_driver) { .bus = &ccwgroup_bus_type, .name = cdriver->name, - .probe = ccwgroup_probe, - .remove = ccwgroup_remove, }; return driver_register(&cdriver->driver); -- GitLab From ff2dae79773658eaaab731663ddca9f7975430eb Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 5 Jan 2006 14:42:40 +0000 Subject: [PATCH 108/465] [PATCH] Add superhyway_bus_type probe and remove methods Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/sh/superhyway/superhyway.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c index 7bdab2a7f59..94b22903119 100644 --- a/drivers/sh/superhyway/superhyway.c +++ b/drivers/sh/superhyway/superhyway.c @@ -175,8 +175,6 @@ int superhyway_register_driver(struct superhyway_driver *drv) { drv->drv.name = drv->name; drv->drv.bus = &superhyway_bus_type; - drv->drv.probe = superhyway_device_probe; - drv->drv.remove = superhyway_device_remove; return driver_register(&drv->drv); } @@ -213,6 +211,8 @@ struct bus_type superhyway_bus_type = { #ifdef CONFIG_SYSFS .dev_attrs = superhyway_dev_attrs, #endif + .probe = superhyway_device_probe, + .remove = superhyway_device_remove, }; static int __init superhyway_bus_init(void) -- GitLab From ac33bc3d54936d364c1f979e50f43dfa3f9a13c1 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 5 Jan 2006 14:43:11 +0000 Subject: [PATCH 109/465] [PATCH] Add usb_serial_bus_type probe and remove methods Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/bus.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c index 664139afcfa..e9f9f4bafa1 100644 --- a/drivers/usb/serial/bus.c +++ b/drivers/usb/serial/bus.c @@ -37,11 +37,6 @@ static int usb_serial_device_match (struct device *dev, struct device_driver *dr return 0; } -struct bus_type usb_serial_bus_type = { - .name = "usb-serial", - .match = usb_serial_device_match, -}; - static int usb_serial_device_probe (struct device *dev) { struct usb_serial_driver *driver; @@ -109,14 +104,18 @@ exit: return retval; } +struct bus_type usb_serial_bus_type = { + .name = "usb-serial", + .match = usb_serial_device_match, + .probe = usb_serial_device_probe, + .remove = usb_serial_device_remove, +}; + int usb_serial_bus_register(struct usb_serial_driver *driver) { int retval; driver->driver.bus = &usb_serial_bus_type; - driver->driver.probe = usb_serial_device_probe; - driver->driver.remove = usb_serial_device_remove; - retval = driver_register(&driver->driver); return retval; -- GitLab From b6a01e9bda69aaf22f3a23bafc91c0fb51420a7a Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 5 Jan 2006 14:43:43 +0000 Subject: [PATCH 110/465] [PATCH] Add zorro_bus_type probe and remove methods Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/zorro/zorro-driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/zorro/zorro-driver.c b/drivers/zorro/zorro-driver.c index ccba227676f..fcbee748c59 100644 --- a/drivers/zorro/zorro-driver.c +++ b/drivers/zorro/zorro-driver.c @@ -77,7 +77,6 @@ int zorro_register_driver(struct zorro_driver *drv) /* initialize common driver fields */ drv->driver.name = drv->name; drv->driver.bus = &zorro_bus_type; - drv->driver.probe = zorro_device_probe; /* register with core */ count = driver_register(&drv->driver); @@ -132,7 +131,8 @@ static int zorro_bus_match(struct device *dev, struct device_driver *drv) struct bus_type zorro_bus_type = { .name = "zorro", - .match = zorro_bus_match + .match = zorro_bus_match, + .probe = zorro_device_probe, }; -- GitLab From fc3d3ddd3e628d9f22d4aa56a640d0b31c977a8f Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 5 Jan 2006 14:44:14 +0000 Subject: [PATCH 111/465] [PATCH] Add rio_bus_type probe and remove methods Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/rapidio/rio-driver.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c index dc749609699..5480119ff9d 100644 --- a/drivers/rapidio/rio-driver.c +++ b/drivers/rapidio/rio-driver.c @@ -147,8 +147,6 @@ int rio_register_driver(struct rio_driver *rdrv) /* initialize common driver fields */ rdrv->driver.name = rdrv->name; rdrv->driver.bus = &rio_bus_type; - rdrv->driver.probe = rio_device_probe; - rdrv->driver.remove = rio_device_remove; /* register with core */ return driver_register(&rdrv->driver); @@ -204,7 +202,9 @@ static struct device rio_bus = { struct bus_type rio_bus_type = { .name = "rapidio", .match = rio_match_bus, - .dev_attrs = rio_dev_attrs + .dev_attrs = rio_dev_attrs, + .probe = rio_device_probe, + .remove = rio_device_remove, }; /** -- GitLab From bbbe3a41f7ee529f7f4fdcc1bc1157234bac0766 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 5 Jan 2006 14:44:46 +0000 Subject: [PATCH 112/465] [PATCH] Add Pseudo LLD bus_type probe and remove methods Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/scsi_debug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 3ded9daaf4a..0e529f8171c 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -221,8 +221,6 @@ static struct bus_type pseudo_lld_bus; static struct device_driver sdebug_driverfs_driver = { .name = sdebug_proc_name, .bus = &pseudo_lld_bus, - .probe = sdebug_driver_probe, - .remove = sdebug_driver_remove, }; static const int check_condition_result = @@ -1796,6 +1794,8 @@ static int pseudo_lld_bus_match(struct device *dev, static struct bus_type pseudo_lld_bus = { .name = "pseudo", .match = pseudo_lld_bus_match, + .probe = sdebug_driver_probe, + .remove = sdebug_driver_remove, }; static void sdebug_release_adapter(struct device * dev) -- GitLab From 4031bbe4bbec6c0fe50412ef7fb43a270b0f29f1 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 6 Jan 2006 11:41:00 +0000 Subject: [PATCH 113/465] [PATCH] Add ide_bus_type probe and remove methods Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/ide/ide-cd.c | 14 +++++--------- drivers/ide/ide-disk.c | 22 ++++++++-------------- drivers/ide/ide-floppy.c | 14 +++++--------- drivers/ide/ide-tape.c | 18 +++++++----------- drivers/ide/ide.c | 31 +++++++++++++++++++++++++++++++ include/linux/ide.h | 5 +++++ 6 files changed, 61 insertions(+), 43 deletions(-) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 9b2ebd219ad..ef09a7ef239 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -3256,9 +3256,8 @@ sector_t ide_cdrom_capacity (ide_drive_t *drive) } #endif -static int ide_cd_remove(struct device *dev) +static void ide_cd_remove(ide_drive_t *drive) { - ide_drive_t *drive = to_ide_device(dev); struct cdrom_info *info = drive->driver_data; ide_unregister_subdriver(drive, info->driver); @@ -3266,8 +3265,6 @@ static int ide_cd_remove(struct device *dev) del_gendisk(info->disk); ide_cd_put(info); - - return 0; } static void ide_cd_release(struct kref *kref) @@ -3291,7 +3288,7 @@ static void ide_cd_release(struct kref *kref) kfree(info); } -static int ide_cd_probe(struct device *); +static int ide_cd_probe(ide_drive_t *); #ifdef CONFIG_PROC_FS static int proc_idecd_read_capacity @@ -3317,9 +3314,9 @@ static ide_driver_t ide_cdrom_driver = { .owner = THIS_MODULE, .name = "ide-cdrom", .bus = &ide_bus_type, - .probe = ide_cd_probe, - .remove = ide_cd_remove, }, + .probe = ide_cd_probe, + .remove = ide_cd_remove, .version = IDECD_VERSION, .media = ide_cdrom, .supports_dsc_overlap = 1, @@ -3413,9 +3410,8 @@ static char *ignore = NULL; module_param(ignore, charp, 0400); MODULE_DESCRIPTION("ATAPI CD-ROM Driver"); -static int ide_cd_probe(struct device *dev) +static int ide_cd_probe(ide_drive_t *drive) { - ide_drive_t *drive = to_ide_device(dev); struct cdrom_info *info; struct gendisk *g; struct request_sense sense; diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index cab362ea033..245b508208d 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -997,9 +997,8 @@ static void ide_cacheflush_p(ide_drive_t *drive) printk(KERN_INFO "%s: wcache flush failed!\n", drive->name); } -static int ide_disk_remove(struct device *dev) +static void ide_disk_remove(ide_drive_t *drive) { - ide_drive_t *drive = to_ide_device(dev); struct ide_disk_obj *idkp = drive->driver_data; struct gendisk *g = idkp->disk; @@ -1010,8 +1009,6 @@ static int ide_disk_remove(struct device *dev) ide_cacheflush_p(drive); ide_disk_put(idkp); - - return 0; } static void ide_disk_release(struct kref *kref) @@ -1027,12 +1024,10 @@ static void ide_disk_release(struct kref *kref) kfree(idkp); } -static int ide_disk_probe(struct device *dev); +static int ide_disk_probe(ide_drive_t *drive); -static void ide_device_shutdown(struct device *dev) +static void ide_device_shutdown(ide_drive_t *drive) { - ide_drive_t *drive = container_of(dev, ide_drive_t, gendev); - #ifdef CONFIG_ALPHA /* On Alpha, halt(8) doesn't actually turn the machine off, it puts you into the sort of firmware monitor. Typically, @@ -1054,7 +1049,7 @@ static void ide_device_shutdown(struct device *dev) } printk("Shutdown: %s\n", drive->name); - dev->bus->suspend(dev, PMSG_SUSPEND); + drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND); } static ide_driver_t idedisk_driver = { @@ -1062,10 +1057,10 @@ static ide_driver_t idedisk_driver = { .owner = THIS_MODULE, .name = "ide-disk", .bus = &ide_bus_type, - .probe = ide_disk_probe, - .remove = ide_disk_remove, - .shutdown = ide_device_shutdown, }, + .probe = ide_disk_probe, + .remove = ide_disk_remove, + .shutdown = ide_device_shutdown, .version = IDEDISK_VERSION, .media = ide_disk, .supports_dsc_overlap = 0, @@ -1182,9 +1177,8 @@ static struct block_device_operations idedisk_ops = { MODULE_DESCRIPTION("ATA DISK Driver"); -static int ide_disk_probe(struct device *dev) +static int ide_disk_probe(ide_drive_t *drive) { - ide_drive_t *drive = to_ide_device(dev); struct ide_disk_obj *idkp; struct gendisk *g; diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 5945f551aaa..1f8db9ac05d 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -1871,9 +1871,8 @@ static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy) idefloppy_add_settings(drive); } -static int ide_floppy_remove(struct device *dev) +static void ide_floppy_remove(ide_drive_t *drive) { - ide_drive_t *drive = to_ide_device(dev); idefloppy_floppy_t *floppy = drive->driver_data; struct gendisk *g = floppy->disk; @@ -1882,8 +1881,6 @@ static int ide_floppy_remove(struct device *dev) del_gendisk(g); ide_floppy_put(floppy); - - return 0; } static void ide_floppy_release(struct kref *kref) @@ -1922,16 +1919,16 @@ static ide_proc_entry_t idefloppy_proc[] = { #endif /* CONFIG_PROC_FS */ -static int ide_floppy_probe(struct device *); +static int ide_floppy_probe(ide_drive_t *); static ide_driver_t idefloppy_driver = { .gen_driver = { .owner = THIS_MODULE, .name = "ide-floppy", .bus = &ide_bus_type, - .probe = ide_floppy_probe, - .remove = ide_floppy_remove, }, + .probe = ide_floppy_probe, + .remove = ide_floppy_remove, .version = IDEFLOPPY_VERSION, .media = ide_floppy, .supports_dsc_overlap = 0, @@ -2136,9 +2133,8 @@ static struct block_device_operations idefloppy_ops = { .revalidate_disk= idefloppy_revalidate_disk }; -static int ide_floppy_probe(struct device *dev) +static int ide_floppy_probe(ide_drive_t *drive) { - ide_drive_t *drive = to_ide_device(dev); idefloppy_floppy_t *floppy; struct gendisk *g; diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index fab9b2b0250..0101d0def7c 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -4682,9 +4682,8 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor) idetape_add_settings(drive); } -static int ide_tape_remove(struct device *dev) +static void ide_tape_remove(ide_drive_t *drive) { - ide_drive_t *drive = to_ide_device(dev); idetape_tape_t *tape = drive->driver_data; ide_unregister_subdriver(drive, tape->driver); @@ -4692,8 +4691,6 @@ static int ide_tape_remove(struct device *dev) ide_unregister_region(tape->disk); ide_tape_put(tape); - - return 0; } static void ide_tape_release(struct kref *kref) @@ -4745,16 +4742,16 @@ static ide_proc_entry_t idetape_proc[] = { #endif -static int ide_tape_probe(struct device *); +static int ide_tape_probe(ide_drive_t *); static ide_driver_t idetape_driver = { .gen_driver = { .owner = THIS_MODULE, .name = "ide-tape", .bus = &ide_bus_type, - .probe = ide_tape_probe, - .remove = ide_tape_remove, }, + .probe = ide_tape_probe, + .remove = ide_tape_remove, .version = IDETAPE_VERSION, .media = ide_tape, .supports_dsc_overlap = 1, @@ -4825,9 +4822,8 @@ static struct block_device_operations idetape_block_ops = { .ioctl = idetape_ioctl, }; -static int ide_tape_probe(struct device *dev) +static int ide_tape_probe(ide_drive_t *drive) { - ide_drive_t *drive = to_ide_device(dev); idetape_tape_t *tape; struct gendisk *g; int minor; @@ -4883,9 +4879,9 @@ static int ide_tape_probe(struct device *dev) idetape_setup(drive, tape, minor); class_device_create(idetape_sysfs_class, NULL, - MKDEV(IDETAPE_MAJOR, minor), dev, "%s", tape->name); + MKDEV(IDETAPE_MAJOR, minor), &drive->gendev, "%s", tape->name); class_device_create(idetape_sysfs_class, NULL, - MKDEV(IDETAPE_MAJOR, minor + 128), dev, "n%s", tape->name); + MKDEV(IDETAPE_MAJOR, minor + 128), &drive->gendev, "n%s", tape->name); devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor), S_IFCHR | S_IRUGO | S_IWUGO, diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index ec5a4cb173b..afeb02bbb72 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -1949,10 +1949,41 @@ static int ide_uevent(struct device *dev, char **envp, int num_envp, return 0; } +static int generic_ide_probe(struct device *dev) +{ + ide_drive_t *drive = to_ide_device(dev); + ide_driver_t *drv = to_ide_driver(dev->driver); + + return drv->probe ? drv->probe(drive) : -ENODEV; +} + +static int generic_ide_remove(struct device *dev) +{ + ide_drive_t *drive = to_ide_device(dev); + ide_driver_t *drv = to_ide_driver(dev->driver); + + if (drv->remove) + drv->remove(drive); + + return 0; +} + +static void generic_ide_shutdown(struct device *dev) +{ + ide_drive_t *drive = to_ide_device(dev); + ide_driver_t *drv = to_ide_driver(dev->driver); + + if (dev->driver && drv->shutdown) + drv->shutdown(drive); +} + struct bus_type ide_bus_type = { .name = "ide", .match = ide_bus_match, .uevent = ide_uevent, + .probe = generic_ide_probe, + .remove = generic_ide_remove, + .shutdown = generic_ide_shutdown, .dev_attrs = ide_dev_attrs, .suspend = generic_ide_suspend, .resume = generic_ide_resume, diff --git a/include/linux/ide.h b/include/linux/ide.h index f2e1b5b2289..110b3cfac02 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -983,8 +983,13 @@ typedef struct ide_driver_s { ide_startstop_t (*abort)(ide_drive_t *, struct request *rq); ide_proc_entry_t *proc; struct device_driver gen_driver; + int (*probe)(ide_drive_t *); + void (*remove)(ide_drive_t *); + void (*shutdown)(ide_drive_t *); } ide_driver_t; +#define to_ide_driver(drv) container_of(drv, ide_driver_t, gen_driver) + int generic_ide_ioctl(ide_drive_t *, struct file *, struct block_device *, unsigned, unsigned long); /* -- GitLab From d78967fb035aeb839a047ae69ce5f1ff39288a8d Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 6 Jan 2006 11:41:32 +0000 Subject: [PATCH 114/465] [PATCH] Remove usb gadget generic driver methods USB gadget drivers make no use of these, remove the pointless comments. Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/ether.c | 3 --- drivers/usb/gadget/inode.c | 3 --- drivers/usb/gadget/serial.c | 3 --- drivers/usb/gadget/zero.c | 3 --- 4 files changed, 12 deletions(-) diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 8f402f85e1c..afc84cfb61f 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -2534,9 +2534,6 @@ static struct usb_gadget_driver eth_driver = { .driver = { .name = (char *) shortname, .owner = THIS_MODULE, - // .shutdown = ... - // .suspend = ... - // .resume = ... }, }; diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index c6c279de832..9a4edc5657a 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -1738,9 +1738,6 @@ static struct usb_gadget_driver gadgetfs_driver = { .driver = { .name = (char *) shortname, - // .shutdown = ... - // .suspend = ... - // .resume = ... }, }; diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 2e6926b3345..ba9acd53102 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -374,9 +374,6 @@ static struct usb_gadget_driver gs_gadget_driver = { .disconnect = gs_disconnect, .driver = { .name = GS_SHORT_NAME, - /* .shutdown = ... */ - /* .suspend = ... */ - /* .resume = ... */ }, }; diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 6c58636e914..2fc110d3ad5 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -1303,9 +1303,6 @@ static struct usb_gadget_driver zero_driver = { .driver = { .name = (char *) shortname, .owner = THIS_MODULE, - // .shutdown = ... - // .suspend = ... - // .resume = ... }, }; -- GitLab From 348290a4ae143a692124330942b464ccdb0d0365 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 6 Jan 2006 11:42:03 +0000 Subject: [PATCH 115/465] [PATCH] Add bttv sub bus_type probe and remove methods Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 23 +++++++++++------------ drivers/media/video/bttv-gpio.c | 24 ++++++++++++++++++++++-- drivers/media/video/bttv.h | 2 ++ 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index f65f64b00ff..44fcbe77c8f 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -779,9 +779,8 @@ static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type) return 0; } -static int dvb_bt8xx_probe(struct device *dev) +static int dvb_bt8xx_probe(struct bttv_sub_device *sub) { - struct bttv_sub_device *sub = to_bttv_sub_dev(dev); struct dvb_bt8xx_card *card; struct pci_dev* bttv_pci_dev; int ret; @@ -890,13 +889,13 @@ static int dvb_bt8xx_probe(struct device *dev) return ret; } - dev_set_drvdata(dev, card); + dev_set_drvdata(&sub->dev, card); return 0; } -static int dvb_bt8xx_remove(struct device *dev) +static int dvb_bt8xx_remove(struct bttv_sub_device *sub) { - struct dvb_bt8xx_card *card = dev_get_drvdata(dev); + struct dvb_bt8xx_card *card = dev_get_drvdata(&sub->dev); dprintk("dvb_bt8xx: unloading card%d\n", card->bttv_nr); @@ -919,14 +918,14 @@ static int dvb_bt8xx_remove(struct device *dev) static struct bttv_sub_driver driver = { .drv = { .name = "dvb-bt8xx", - .probe = dvb_bt8xx_probe, - .remove = dvb_bt8xx_remove, - /* FIXME: - * .shutdown = dvb_bt8xx_shutdown, - * .suspend = dvb_bt8xx_suspend, - * .resume = dvb_bt8xx_resume, - */ }, + .probe = dvb_bt8xx_probe, + .remove = dvb_bt8xx_remove, + /* FIXME: + * .shutdown = dvb_bt8xx_shutdown, + * .suspend = dvb_bt8xx_suspend, + * .resume = dvb_bt8xx_resume, + */ }; static int __init dvb_bt8xx_init(void) diff --git a/drivers/media/video/bttv-gpio.c b/drivers/media/video/bttv-gpio.c index d64accc17b0..c4d5e2b70c2 100644 --- a/drivers/media/video/bttv-gpio.c +++ b/drivers/media/video/bttv-gpio.c @@ -47,9 +47,29 @@ static int bttv_sub_bus_match(struct device *dev, struct device_driver *drv) return 0; } +static int bttv_sub_probe(struct device *dev) +{ + struct bttv_sub_device *sdev = to_bttv_sub_dev(dev); + struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver); + + return sub->probe ? sub->probe(sdev) : -ENODEV; +} + +static int bttv_sub_remove(struct device *dev) +{ + struct bttv_sub_device *sdev = to_bttv_sub_dev(dev); + struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver); + + if (sub->remove) + sub->remove(sdev); + return 0; +} + struct bus_type bttv_sub_bus_type = { - .name = "bttv-sub", - .match = &bttv_sub_bus_match, + .name = "bttv-sub", + .match = &bttv_sub_bus_match, + .probe = bttv_sub_probe, + .remove = bttv_sub_remove, }; EXPORT_SYMBOL(bttv_sub_bus_type); diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h index e370d74f2a1..9908c8e0c95 100644 --- a/drivers/media/video/bttv.h +++ b/drivers/media/video/bttv.h @@ -365,6 +365,8 @@ struct bttv_sub_device { struct bttv_sub_driver { struct device_driver drv; char wanted[BUS_ID_SIZE]; + int (*probe)(struct bttv_sub_device *sub); + void (*remove)(struct bttv_sub_device *sub); void (*gpio_irq)(struct bttv_sub_device *sub); }; #define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv) -- GitLab From 8bbace7e686f1536905c703038a7eddfb1520264 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Wed, 11 Jan 2006 10:56:22 +0100 Subject: [PATCH 116/465] [PATCH] Add {css,ccw}_bus_type probe, remove, shutdown methods. The following patch converts css_bus_type and ccw_bus_type to use the new bus_type methods. Signed-off-by: Cornelia Huck CC: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- drivers/s390/cio/css.c | 36 ++++++++++++++++++++++++++-- drivers/s390/cio/css.h | 4 ++++ drivers/s390/cio/device.c | 50 +++++++++++++++++++-------------------- 3 files changed, 62 insertions(+), 28 deletions(-) diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index e565193650c..2d319fb812c 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -542,9 +542,41 @@ css_bus_match (struct device *dev, struct device_driver *drv) return 0; } +static int +css_probe (struct device *dev) +{ + struct subchannel *sch; + + sch = to_subchannel(dev); + sch->driver = container_of (dev->driver, struct css_driver, drv); + return (sch->driver->probe ? sch->driver->probe(sch) : 0); +} + +static int +css_remove (struct device *dev) +{ + struct subchannel *sch; + + sch = to_subchannel(dev); + return (sch->driver->remove ? sch->driver->remove(sch) : 0); +} + +static void +css_shutdown (struct device *dev) +{ + struct subchannel *sch; + + sch = to_subchannel(dev); + if (sch->driver->shutdown) + sch->driver->shutdown(sch); +} + struct bus_type css_bus_type = { - .name = "css", - .match = &css_bus_match, + .name = "css", + .match = css_bus_match, + .probe = css_probe, + .remove = css_remove, + .shutdown = css_shutdown, }; subsys_initcall(init_channel_subsystem); diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h index 251ebd7a7d3..aa5ab5d4547 100644 --- a/drivers/s390/cio/css.h +++ b/drivers/s390/cio/css.h @@ -115,6 +115,7 @@ struct ccw_device_private { * Currently, we only care about I/O subchannels (type 0), these * have a ccw_device connected to them. */ +struct subchannel; struct css_driver { unsigned int subchannel_type; struct device_driver drv; @@ -122,6 +123,9 @@ struct css_driver { int (*notify)(struct device *, int); void (*verify)(struct device *); void (*termination)(struct device *); + int (*probe)(struct subchannel *); + int (*remove)(struct subchannel *); + void (*shutdown)(struct subchannel *); }; /* diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index fa3e4c0a253..eb73605a052 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -107,33 +107,29 @@ ccw_uevent (struct device *dev, char **envp, int num_envp, return 0; } -struct bus_type ccw_bus_type = { - .name = "ccw", - .match = &ccw_bus_match, - .uevent = &ccw_uevent, -}; +struct bus_type ccw_bus_type; -static int io_subchannel_probe (struct device *); -static int io_subchannel_remove (struct device *); +static int io_subchannel_probe (struct subchannel *); +static int io_subchannel_remove (struct subchannel *); void io_subchannel_irq (struct device *); static int io_subchannel_notify(struct device *, int); static void io_subchannel_verify(struct device *); static void io_subchannel_ioterm(struct device *); -static void io_subchannel_shutdown(struct device *); +static void io_subchannel_shutdown(struct subchannel *); struct css_driver io_subchannel_driver = { .subchannel_type = SUBCHANNEL_TYPE_IO, .drv = { .name = "io_subchannel", .bus = &css_bus_type, - .probe = &io_subchannel_probe, - .remove = &io_subchannel_remove, - .shutdown = &io_subchannel_shutdown, }, .irq = io_subchannel_irq, .notify = io_subchannel_notify, .verify = io_subchannel_verify, .termination = io_subchannel_ioterm, + .probe = io_subchannel_probe, + .remove = io_subchannel_remove, + .shutdown = io_subchannel_shutdown, }; struct workqueue_struct *ccw_device_work; @@ -803,14 +799,12 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch) } static int -io_subchannel_probe (struct device *pdev) +io_subchannel_probe (struct subchannel *sch) { - struct subchannel *sch; struct ccw_device *cdev; int rc; unsigned long flags; - sch = to_subchannel(pdev); if (sch->dev.driver_data) { /* * This subchannel already has an associated ccw_device. @@ -846,7 +840,7 @@ io_subchannel_probe (struct device *pdev) memset(cdev->private, 0, sizeof(struct ccw_device_private)); atomic_set(&cdev->private->onoff, 0); cdev->dev = (struct device) { - .parent = pdev, + .parent = &sch->dev, .release = ccw_device_release, }; INIT_LIST_HEAD(&cdev->private->kick_work.entry); @@ -859,7 +853,7 @@ io_subchannel_probe (struct device *pdev) return -ENODEV; } - rc = io_subchannel_recog(cdev, to_subchannel(pdev)); + rc = io_subchannel_recog(cdev, sch); if (rc) { spin_lock_irqsave(&sch->lock, flags); sch->dev.driver_data = NULL; @@ -883,17 +877,17 @@ ccw_device_unregister(void *data) } static int -io_subchannel_remove (struct device *dev) +io_subchannel_remove (struct subchannel *sch) { struct ccw_device *cdev; unsigned long flags; - if (!dev->driver_data) + if (!sch->dev.driver_data) return 0; - cdev = dev->driver_data; + cdev = sch->dev.driver_data; /* Set ccw device to not operational and drop reference. */ spin_lock_irqsave(cdev->ccwlock, flags); - dev->driver_data = NULL; + sch->dev.driver_data = NULL; cdev->private->state = DEV_STATE_NOT_OPER; spin_unlock_irqrestore(cdev->ccwlock, flags); /* @@ -948,14 +942,12 @@ io_subchannel_ioterm(struct device *dev) } static void -io_subchannel_shutdown(struct device *dev) +io_subchannel_shutdown(struct subchannel *sch) { - struct subchannel *sch; struct ccw_device *cdev; int ret; - sch = to_subchannel(dev); - cdev = dev->driver_data; + cdev = sch->dev.driver_data; if (cio_is_console(sch->schid)) return; @@ -1129,6 +1121,14 @@ ccw_device_remove (struct device *dev) return 0; } +struct bus_type ccw_bus_type = { + .name = "ccw", + .match = ccw_bus_match, + .uevent = ccw_uevent, + .probe = ccw_device_probe, + .remove = ccw_device_remove, +}; + int ccw_driver_register (struct ccw_driver *cdriver) { @@ -1136,8 +1136,6 @@ ccw_driver_register (struct ccw_driver *cdriver) drv->bus = &ccw_bus_type; drv->name = cdriver->name; - drv->probe = ccw_device_probe; - drv->remove = ccw_device_remove; return driver_register(drv); } -- GitLab From 2d7b5a70e01ff8b1b054d8313362e454e3057c5a Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 27 Dec 2005 19:45:58 +0100 Subject: [PATCH 117/465] [PATCH] platform-device-del typo fix Please fold this typo fix into platform-device-del.patch, as was discussed earlier on LKML: http://lkml.org/lkml/2005/12/10/76 Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 0f81731bdfa..461554a0251 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -327,7 +327,7 @@ EXPORT_SYMBOL_GPL(platform_device_register); * @pdev: platform device we're unregistering * * Unregistration is done in 2 steps. Fisrt we release all resources - * and remove it from the sybsystem, then we drop reference count by + * and remove it from the subsystem, then we drop reference count by * calling platform_device_put(). */ void platform_device_unregister(struct platform_device * pdev) -- GitLab From 9c08a938ce5a3e1c9d5f764dc6ae844cb1af76ff Mon Sep 17 00:00:00 2001 From: Michael Richardson Date: Mon, 9 Jan 2006 01:04:51 -0800 Subject: [PATCH 118/465] [PATCH] device_shutdown can loop if the driver frees itself This patch changes device_shutdown() to use the newly introduced safe reverse list traversal. We experienced loops on system reboot if we had removed and re-inserted our device from the device list. We noticed this problem on PPC405. Our PCI IDE device comes and goes a lot. Our hypothesis was that there was a loop caused by the driver->shutdown freeing memory. It is possible that we do something wrong as well, but being unable to reboot is kind of nasty. Signed-off-by: Michael Richardson Cc: Patrick Mochel Cc: David Howells Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/base/power/shutdown.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/base/power/shutdown.c b/drivers/base/power/shutdown.c index a47bb74da72..c2475f3134e 100644 --- a/drivers/base/power/shutdown.c +++ b/drivers/base/power/shutdown.c @@ -35,10 +35,10 @@ extern int sysdev_shutdown(void); */ void device_shutdown(void) { - struct device * dev; + struct device * dev, *devn; down_write(&devices_subsys.rwsem); - list_for_each_entry_reverse(dev, &devices_subsys.kset.list, + list_for_each_entry_safe_reverse(dev, devn, &devices_subsys.kset.list, kobj.entry) { if (dev->bus && dev->bus->shutdown) { dev_dbg(dev, "shutdown\n"); -- GitLab From dd29c7277126db6884df42d41f2fbe2ebc10041e Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 13 Jan 2006 20:51:43 +0000 Subject: [PATCH 119/465] [ARM] 3257/1: ixp2000: map in scratch and sram Patch from Lennert Buytenhek For the ixp2000 netdev driver, we need to map in a chunk of SRAM (to store the transmit and receive descriptors) and the scratch get/put area (so that we can use the scratchpad rings in the cpu for managing the descriptors.) These are the final two mappings needed for the netdev driver and the last missing piece for the driver in mainline to work. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King --- arch/arm/mach-ixp2000/core.c | 10 ++++++++++ include/asm-arm/arch-ixp2000/ixp2000-regs.h | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c index 6851abaf552..cfd5bef3190 100644 --- a/arch/arm/mach-ixp2000/core.c +++ b/arch/arm/mach-ixp2000/core.c @@ -105,6 +105,16 @@ static struct map_desc ixp2000_io_desc[] __initdata = { .pfn = __phys_to_pfn(IXP2000_MSF_PHYS_BASE), .length = IXP2000_MSF_SIZE, .type = MT_IXP2000_DEVICE, + }, { + .virtual = IXP2000_SCRATCH_RING_VIRT_BASE, + .pfn = __phys_to_pfn(IXP2000_SCRATCH_RING_PHYS_BASE), + .length = IXP2000_SCRATCH_RING_SIZE, + .type = MT_IXP2000_DEVICE, + }, { + .virtual = IXP2000_SRAM0_VIRT_BASE, + .pfn = __phys_to_pfn(IXP2000_SRAM0_PHYS_BASE), + .length = IXP2000_SRAM0_SIZE, + .type = MT_IXP2000_DEVICE, }, { .virtual = IXP2000_PCI_IO_VIRT_BASE, .pfn = __phys_to_pfn(IXP2000_PCI_IO_PHYS_BASE), diff --git a/include/asm-arm/arch-ixp2000/ixp2000-regs.h b/include/asm-arm/arch-ixp2000/ixp2000-regs.h index 8cf70ff160a..2b57f91b4eb 100644 --- a/include/asm-arm/arch-ixp2000/ixp2000-regs.h +++ b/include/asm-arm/arch-ixp2000/ixp2000-regs.h @@ -26,6 +26,8 @@ * fc000000 da000000 16M PCI CFG0 * fd000000 d8000000 16M PCI I/O * fe[0-7]00000 8M per-platform mappings + * fe900000 80000000 1M SRAM #0 (first MB) + * fea00000 cb400000 1M SCRATCH ring get/put * feb00000 c8000000 1M MSF * fec00000 df000000 1M PCI CSRs * fed00000 de000000 1M PCI CREG @@ -91,6 +93,14 @@ #define IXP2000_MSF_VIRT_BASE 0xfeb00000 #define IXP2000_MSF_SIZE 0x00100000 +#define IXP2000_SCRATCH_RING_PHYS_BASE 0xcb400000 +#define IXP2000_SCRATCH_RING_VIRT_BASE 0xfea00000 +#define IXP2000_SCRATCH_RING_SIZE 0x00100000 + +#define IXP2000_SRAM0_PHYS_BASE 0x80000000 +#define IXP2000_SRAM0_VIRT_BASE 0xfe900000 +#define IXP2000_SRAM0_SIZE 0x00100000 + #define IXP2000_PCI_IO_PHYS_BASE 0xd8000000 #define IXP2000_PCI_IO_VIRT_BASE 0xfd000000 #define IXP2000_PCI_IO_SIZE 0x01000000 -- GitLab From 3261e362f603cf2649f90e9ad2d1a1f98f69291a Mon Sep 17 00:00:00 2001 From: Matt Reimer Date: Fri, 13 Jan 2006 20:51:44 +0000 Subject: [PATCH 120/465] [ARM] 3258/1: IMX serial: fix parity Patch from Matt Reimer IMX serial parity generation doesn't work because of a simple logic error. This patch fixes it and now Bluetooth works on R1000. Signed-off-by: Matt Reimer Signed-off-by: Russell King --- drivers/serial/imx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 5c098be9346..587cc6a9511 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -499,7 +499,7 @@ imx_set_termios(struct uart_port *port, struct termios *termios, ucr2 |= UCR2_STPB; if (termios->c_cflag & PARENB) { ucr2 |= UCR2_PREN; - if (!(termios->c_cflag & PARODD)) + if (termios->c_cflag & PARODD) ucr2 |= UCR2_PROE; } -- GitLab From 2df96b34aae08e0aa688ef7a8444febb8ec44172 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 13 Jan 2006 20:51:46 +0000 Subject: [PATCH 121/465] [ARM] 3259/1: remove phys_ram from struct machine_desc (part 1) Patch from Nicolas Pitre This field is redundent since it must be equal to PHYS_OFFSET anyway. First, let's use PHYS_OFFSET directly instead. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/kernel/head.S | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 1e985f2cd70..1aca1775b28 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -251,12 +251,11 @@ __turn_mmu_on: * r10 = procinfo * * Returns: - * r0, r3, r5, r6, r7 corrupted + * r0, r3, r6, r7 corrupted * r4 = physical page table address */ .type __create_page_tables, %function __create_page_tables: - ldr r5, [r8, #MACHINFO_PHYSRAM] @ physram pgtbl r4 @ page table address /* @@ -303,7 +302,7 @@ __create_page_tables: * Then map first 1MB of ram in case it contains our boot params. */ add r0, r4, #PAGE_OFFSET >> 18 - orr r6, r5, r7 + orr r6, r7, #PHYS_OFFSET str r6, [r0] #ifdef CONFIG_XIP_KERNEL @@ -311,7 +310,7 @@ __create_page_tables: * Map some ram to cover our .data and .bss areas. * Mapping 3MB should be plenty. */ - sub r3, r4, r5 + sub r3, r4, #PHYS_OFFSET mov r3, r3, lsr #20 add r0, r0, r3, lsl #2 add r6, r6, r3, lsl #20 -- GitLab From 946d4935fc61e1479f8c057d58c64110bb43d3b0 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 13 Jan 2006 20:51:52 +0000 Subject: [PATCH 122/465] [ARM] 3260/1: remove phys_ram from struct machine_desc (part 2) Patch from Nicolas Pitre This field is redundent since it must be equal to PHYS_OFFSET anyway. Now that no code uses it anymore, mark it deprecated and remove all initializations from the tree. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/mach-aaec2000/aaed2000.c | 1 - arch/arm/mach-at91rm9200/board-csb337.c | 1 - arch/arm/mach-at91rm9200/board-csb637.c | 1 - arch/arm/mach-at91rm9200/board-dk.c | 1 - arch/arm/mach-at91rm9200/board-ek.c | 1 - arch/arm/mach-clps711x/autcpu12.c | 1 - arch/arm/mach-clps711x/cdb89712.c | 1 - arch/arm/mach-clps711x/ceiva.c | 1 - arch/arm/mach-clps711x/clep7312.c | 1 - arch/arm/mach-clps711x/edb7211-arch.c | 1 - arch/arm/mach-clps711x/fortunet.c | 1 - arch/arm/mach-clps711x/p720t.c | 1 - arch/arm/mach-clps7500/core.c | 1 - arch/arm/mach-ebsa110/core.c | 1 - arch/arm/mach-footbridge/cats-hw.c | 1 - arch/arm/mach-footbridge/co285.c | 1 - arch/arm/mach-footbridge/ebsa285.c | 1 - arch/arm/mach-footbridge/netwinder-hw.c | 1 - arch/arm/mach-footbridge/personal.c | 1 - arch/arm/mach-h720x/h7201-eval.c | 1 - arch/arm/mach-h720x/h7202-eval.c | 1 - arch/arm/mach-imx/mx1ads.c | 1 - arch/arm/mach-integrator/integrator_ap.c | 1 - arch/arm/mach-integrator/integrator_cp.c | 1 - arch/arm/mach-iop3xx/iop321-setup.c | 2 -- arch/arm/mach-iop3xx/iop331-setup.c | 2 -- arch/arm/mach-ixp2000/enp2611.c | 1 - arch/arm/mach-ixp2000/ixdp2400.c | 1 - arch/arm/mach-ixp2000/ixdp2800.c | 1 - arch/arm/mach-ixp2000/ixdp2x01.c | 2 -- arch/arm/mach-ixp4xx/coyote-setup.c | 2 -- arch/arm/mach-ixp4xx/gtwx5715-setup.c | 1 - arch/arm/mach-ixp4xx/ixdp425-setup.c | 4 ---- arch/arm/mach-ixp4xx/nas100d-setup.c | 1 - arch/arm/mach-ixp4xx/nslu2-setup.c | 1 - arch/arm/mach-l7200/core.c | 1 - arch/arm/mach-lh7a40x/arch-kev7a400.c | 1 - arch/arm/mach-lh7a40x/arch-lpd7a40x.c | 2 -- arch/arm/mach-omap1/board-generic.c | 1 - arch/arm/mach-omap1/board-h2.c | 1 - arch/arm/mach-omap1/board-h3.c | 1 - arch/arm/mach-omap1/board-innovator.c | 1 - arch/arm/mach-omap1/board-netstar.c | 1 - arch/arm/mach-omap1/board-osk.c | 1 - arch/arm/mach-omap1/board-palmte.c | 1 - arch/arm/mach-omap1/board-perseus2.c | 1 - arch/arm/mach-omap1/board-voiceblue.c | 1 - arch/arm/mach-omap2/board-generic.c | 1 - arch/arm/mach-omap2/board-h4.c | 1 - arch/arm/mach-pxa/corgi.c | 3 --- arch/arm/mach-pxa/idp.c | 1 - arch/arm/mach-pxa/lubbock.c | 1 - arch/arm/mach-pxa/mainstone.c | 1 - arch/arm/mach-pxa/poodle.c | 1 - arch/arm/mach-pxa/spitz.c | 3 --- arch/arm/mach-pxa/tosa.c | 1 - arch/arm/mach-realview/realview_eb.c | 1 - arch/arm/mach-rpc/riscpc.c | 1 - arch/arm/mach-s3c2410/mach-anubis.c | 1 - arch/arm/mach-s3c2410/mach-bast.c | 1 - arch/arm/mach-s3c2410/mach-h1940.c | 1 - arch/arm/mach-s3c2410/mach-n30.c | 1 - arch/arm/mach-s3c2410/mach-nexcoder.c | 1 - arch/arm/mach-s3c2410/mach-otom.c | 1 - arch/arm/mach-s3c2410/mach-rx3715.c | 1 - arch/arm/mach-s3c2410/mach-smdk2410.c | 1 - arch/arm/mach-s3c2410/mach-smdk2440.c | 1 - arch/arm/mach-s3c2410/mach-vr1000.c | 1 - arch/arm/mach-sa1100/assabet.c | 1 - arch/arm/mach-sa1100/badge4.c | 1 - arch/arm/mach-sa1100/cerf.c | 1 - arch/arm/mach-sa1100/collie.c | 1 - arch/arm/mach-sa1100/h3600.c | 3 --- arch/arm/mach-sa1100/hackkit.c | 1 - arch/arm/mach-sa1100/jornada720.c | 1 - arch/arm/mach-sa1100/lart.c | 1 - arch/arm/mach-sa1100/pleb.c | 1 - arch/arm/mach-sa1100/shannon.c | 1 - arch/arm/mach-sa1100/simpad.c | 1 - arch/arm/mach-shark/core.c | 1 - arch/arm/mach-versatile/versatile_ab.c | 1 - arch/arm/mach-versatile/versatile_pb.c | 1 - include/asm-arm/mach/arch.h | 2 +- 83 files changed, 1 insertion(+), 97 deletions(-) diff --git a/arch/arm/mach-aaec2000/aaed2000.c b/arch/arm/mach-aaec2000/aaed2000.c index f5ef6970229..dc5fa8e5ebe 100644 --- a/arch/arm/mach-aaec2000/aaed2000.c +++ b/arch/arm/mach-aaec2000/aaed2000.c @@ -90,7 +90,6 @@ static void __init aaed2000_map_io(void) MACHINE_START(AAED2000, "Agilent AAED-2000 Development Platform") /* Maintainer: Nicolas Bellido Y Ortega */ - .phys_ram = 0xf0000000, .phys_io = PIO_BASE, .io_pg_offst = ((VIO_BASE) >> 18) & 0xfffc, .map_io = aaed2000_map_io, diff --git a/arch/arm/mach-at91rm9200/board-csb337.c b/arch/arm/mach-at91rm9200/board-csb337.c index 4aec834ee47..54022e58d50 100644 --- a/arch/arm/mach-at91rm9200/board-csb337.c +++ b/arch/arm/mach-at91rm9200/board-csb337.c @@ -132,7 +132,6 @@ static void __init csb337_board_init(void) MACHINE_START(CSB337, "Cogent CSB337") /* Maintainer: Bill Gatliff */ - .phys_ram = AT91_SDRAM_BASE, .phys_io = AT91_BASE_SYS, .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, .boot_params = AT91_SDRAM_BASE + 0x100, diff --git a/arch/arm/mach-at91rm9200/board-csb637.c b/arch/arm/mach-at91rm9200/board-csb637.c index 23e4cc21481..8195f9d919e 100644 --- a/arch/arm/mach-at91rm9200/board-csb637.c +++ b/arch/arm/mach-at91rm9200/board-csb637.c @@ -105,7 +105,6 @@ static void __init csb637_board_init(void) MACHINE_START(CSB637, "Cogent CSB637") /* Maintainer: Bill Gatliff */ - .phys_ram = AT91_SDRAM_BASE, .phys_io = AT91_BASE_SYS, .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, .boot_params = AT91_SDRAM_BASE + 0x100, diff --git a/arch/arm/mach-at91rm9200/board-dk.c b/arch/arm/mach-at91rm9200/board-dk.c index 8c747a31b95..8a783368366 100644 --- a/arch/arm/mach-at91rm9200/board-dk.c +++ b/arch/arm/mach-at91rm9200/board-dk.c @@ -127,7 +127,6 @@ static void __init dk_board_init(void) MACHINE_START(AT91RM9200DK, "Atmel AT91RM9200-DK") /* Maintainer: SAN People/Atmel */ - .phys_ram = AT91_SDRAM_BASE, .phys_io = AT91_BASE_SYS, .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, .boot_params = AT91_SDRAM_BASE + 0x100, diff --git a/arch/arm/mach-at91rm9200/board-ek.c b/arch/arm/mach-at91rm9200/board-ek.c index d140645711b..fd0752eba89 100644 --- a/arch/arm/mach-at91rm9200/board-ek.c +++ b/arch/arm/mach-at91rm9200/board-ek.c @@ -120,7 +120,6 @@ static void __init ek_board_init(void) MACHINE_START(AT91RM9200EK, "Atmel AT91RM9200-EK") /* Maintainer: SAN People/Atmel */ - .phys_ram = AT91_SDRAM_BASE, .phys_io = AT91_BASE_SYS, .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, .boot_params = AT91_SDRAM_BASE + 0x100, diff --git a/arch/arm/mach-clps711x/autcpu12.c b/arch/arm/mach-clps711x/autcpu12.c index 43b9423d144..c13ca6c56ba 100644 --- a/arch/arm/mach-clps711x/autcpu12.c +++ b/arch/arm/mach-clps711x/autcpu12.c @@ -64,7 +64,6 @@ void __init autcpu12_map_io(void) MACHINE_START(AUTCPU12, "autronix autcpu12") /* Maintainer: Thomas Gleixner */ - .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xff000000) >> 18) & 0xfffc, .boot_params = 0xc0020000, diff --git a/arch/arm/mach-clps711x/cdb89712.c b/arch/arm/mach-clps711x/cdb89712.c index cba7be5a06c..831df007f6c 100644 --- a/arch/arm/mach-clps711x/cdb89712.c +++ b/arch/arm/mach-clps711x/cdb89712.c @@ -55,7 +55,6 @@ static void __init cdb89712_map_io(void) MACHINE_START(CDB89712, "Cirrus-CDB89712") /* Maintainer: Ray Lehtiniemi */ - .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xff000000) >> 18) & 0xfffc, .boot_params = 0xc0000100, diff --git a/arch/arm/mach-clps711x/ceiva.c b/arch/arm/mach-clps711x/ceiva.c index 35d51a759b5..e2b2c5ac8a8 100644 --- a/arch/arm/mach-clps711x/ceiva.c +++ b/arch/arm/mach-clps711x/ceiva.c @@ -56,7 +56,6 @@ static void __init ceiva_map_io(void) MACHINE_START(CEIVA, "CEIVA/Polaroid Photo MAX Digital Picture Frame") /* Maintainer: Rob Scott */ - .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xff000000) >> 18) & 0xfffc, .boot_params = 0xc0000100, diff --git a/arch/arm/mach-clps711x/clep7312.c b/arch/arm/mach-clps711x/clep7312.c index c83f3fd68fc..09fb57e4521 100644 --- a/arch/arm/mach-clps711x/clep7312.c +++ b/arch/arm/mach-clps711x/clep7312.c @@ -38,7 +38,6 @@ fixup_clep7312(struct machine_desc *desc, struct tag *tags, MACHINE_START(CLEP7212, "Cirrus Logic 7212/7312") /* Maintainer: Nobody */ - .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xff000000) >> 18) & 0xfffc, .boot_params = 0xc0000100, diff --git a/arch/arm/mach-clps711x/edb7211-arch.c b/arch/arm/mach-clps711x/edb7211-arch.c index 255c98b63e1..dc81cc68595 100644 --- a/arch/arm/mach-clps711x/edb7211-arch.c +++ b/arch/arm/mach-clps711x/edb7211-arch.c @@ -52,7 +52,6 @@ fixup_edb7211(struct machine_desc *desc, struct tag *tags, MACHINE_START(EDB7211, "CL-EDB7211 (EP7211 eval board)") /* Maintainer: Jon McClintock */ - .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xff000000) >> 18) & 0xfffc, .boot_params = 0xc0020100, /* 0xc0000000 - 0xc001ffff can be video RAM */ diff --git a/arch/arm/mach-clps711x/fortunet.c b/arch/arm/mach-clps711x/fortunet.c index 3d88da0c287..ff26a85aa4b 100644 --- a/arch/arm/mach-clps711x/fortunet.c +++ b/arch/arm/mach-clps711x/fortunet.c @@ -78,7 +78,6 @@ fortunet_fixup(struct machine_desc *desc, struct tag *tags, MACHINE_START(FORTUNET, "ARM-FortuNet") /* Maintainer: FortuNet Inc. */ - .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf0000000) >> 18) & 0xfffc, .boot_params = 0x00000000, diff --git a/arch/arm/mach-clps711x/p720t.c b/arch/arm/mach-clps711x/p720t.c index a1acb945fb5..9ba45f4d5a7 100644 --- a/arch/arm/mach-clps711x/p720t.c +++ b/arch/arm/mach-clps711x/p720t.c @@ -90,7 +90,6 @@ static void __init p720t_map_io(void) MACHINE_START(P720T, "ARM-Prospector720T") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ - .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xff000000) >> 18) & 0xfffc, .boot_params = 0xc0000100, diff --git a/arch/arm/mach-clps7500/core.c b/arch/arm/mach-clps7500/core.c index d869af0023f..5b12cab0e69 100644 --- a/arch/arm/mach-clps7500/core.c +++ b/arch/arm/mach-clps7500/core.c @@ -384,7 +384,6 @@ static void __init clps7500_init(void) MACHINE_START(CLPS7500, "CL-PS7500") /* Maintainer: Philip Blundell */ - .phys_ram = 0x10000000, .phys_io = 0x03000000, .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc, .map_io = clps7500_map_io, diff --git a/arch/arm/mach-ebsa110/core.c b/arch/arm/mach-ebsa110/core.c index ed4614983ad..6d620d8268c 100644 --- a/arch/arm/mach-ebsa110/core.c +++ b/arch/arm/mach-ebsa110/core.c @@ -284,7 +284,6 @@ arch_initcall(ebsa110_init); MACHINE_START(EBSA110, "EBSA110") /* Maintainer: Russell King */ - .phys_ram = 0x00000000, .phys_io = 0xe0000000, .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc, .boot_params = 0x00000400, diff --git a/arch/arm/mach-footbridge/cats-hw.c b/arch/arm/mach-footbridge/cats-hw.c index 49b898af003..5b64d5c5b96 100644 --- a/arch/arm/mach-footbridge/cats-hw.c +++ b/arch/arm/mach-footbridge/cats-hw.c @@ -85,7 +85,6 @@ fixup_cats(struct machine_desc *desc, struct tag *tags, MACHINE_START(CATS, "Chalice-CATS") /* Maintainer: Philip Blundell */ - .phys_ram = 0x00000000, .phys_io = DC21285_ARMCSR_BASE, .io_pg_offst = ((0xfe000000) >> 18) & 0xfffc, .boot_params = 0x00000100, diff --git a/arch/arm/mach-footbridge/co285.c b/arch/arm/mach-footbridge/co285.c index 548a7908168..4545576ad8d 100644 --- a/arch/arm/mach-footbridge/co285.c +++ b/arch/arm/mach-footbridge/co285.c @@ -29,7 +29,6 @@ fixup_coebsa285(struct machine_desc *desc, struct tag *tags, MACHINE_START(CO285, "co-EBSA285") /* Maintainer: Mark van Doesburg */ - .phys_ram = 0x00000000, .phys_io = DC21285_ARMCSR_BASE, .io_pg_offst = ((0x7cf00000) >> 18) & 0xfffc, .fixup = fixup_coebsa285, diff --git a/arch/arm/mach-footbridge/ebsa285.c b/arch/arm/mach-footbridge/ebsa285.c index 1c37605268d..b1d3bf20a41 100644 --- a/arch/arm/mach-footbridge/ebsa285.c +++ b/arch/arm/mach-footbridge/ebsa285.c @@ -14,7 +14,6 @@ MACHINE_START(EBSA285, "EBSA285") /* Maintainer: Russell King */ - .phys_ram = 0x00000000, .phys_io = DC21285_ARMCSR_BASE, .io_pg_offst = ((0xfe000000) >> 18) & 0xfffc, .boot_params = 0x00000100, diff --git a/arch/arm/mach-footbridge/netwinder-hw.c b/arch/arm/mach-footbridge/netwinder-hw.c index 9e563de465b..229bf0585e4 100644 --- a/arch/arm/mach-footbridge/netwinder-hw.c +++ b/arch/arm/mach-footbridge/netwinder-hw.c @@ -649,7 +649,6 @@ fixup_netwinder(struct machine_desc *desc, struct tag *tags, MACHINE_START(NETWINDER, "Rebel-NetWinder") /* Maintainer: Russell King/Rebel.com */ - .phys_ram = 0x00000000, .phys_io = DC21285_ARMCSR_BASE, .io_pg_offst = ((0xfe000000) >> 18) & 0xfffc, .boot_params = 0x00000100, diff --git a/arch/arm/mach-footbridge/personal.c b/arch/arm/mach-footbridge/personal.c index 0146b8bb59d..c4f843fc099 100644 --- a/arch/arm/mach-footbridge/personal.c +++ b/arch/arm/mach-footbridge/personal.c @@ -14,7 +14,6 @@ MACHINE_START(PERSONAL_SERVER, "Compaq-PersonalServer") /* Maintainer: Jamey Hicks / George France */ - .phys_ram = 0x00000000, .phys_io = DC21285_ARMCSR_BASE, .io_pg_offst = ((0xfe000000) >> 18) & 0xfffc, .boot_params = 0x00000100, diff --git a/arch/arm/mach-h720x/h7201-eval.c b/arch/arm/mach-h720x/h7201-eval.c index fa59e9e2a5c..193f968edac 100644 --- a/arch/arm/mach-h720x/h7201-eval.c +++ b/arch/arm/mach-h720x/h7201-eval.c @@ -31,7 +31,6 @@ MACHINE_START(H7201, "Hynix GMS30C7201") /* Maintainer: Robert Schwebel, Pengutronix */ - .phys_ram = 0x40000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf0000000) >> 18) & 0xfffc, .boot_params = 0xc0001000, diff --git a/arch/arm/mach-h720x/h7202-eval.c b/arch/arm/mach-h720x/h7202-eval.c index d75c8221d2a..36266896979 100644 --- a/arch/arm/mach-h720x/h7202-eval.c +++ b/arch/arm/mach-h720x/h7202-eval.c @@ -72,7 +72,6 @@ static void __init init_eval_h7202(void) MACHINE_START(H7202, "Hynix HMS30C7202") /* Maintainer: Robert Schwebel, Pengutronix */ - .phys_ram = 0x40000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf0000000) >> 18) & 0xfffc, .boot_params = 0x40000100, diff --git a/arch/arm/mach-imx/mx1ads.c b/arch/arm/mach-imx/mx1ads.c index c9e0cd8ed01..dc31e3fd6c5 100644 --- a/arch/arm/mach-imx/mx1ads.c +++ b/arch/arm/mach-imx/mx1ads.c @@ -69,7 +69,6 @@ mx1ads_map_io(void) MACHINE_START(MX1ADS, "Motorola MX1ADS") /* Maintainer: Sascha Hauer, Pengutronix */ - .phys_ram = 0x08000000, .phys_io = 0x00200000, .io_pg_offst = ((0xe0200000) >> 18) & 0xfffc, .boot_params = 0x08000100, diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index 3afedeb56a6..d8d3c2a5a97 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c @@ -347,7 +347,6 @@ static struct sys_timer ap_timer = { MACHINE_START(INTEGRATOR, "ARM-Integrator") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ - .phys_ram = 0x00000000, .phys_io = 0x16000000, .io_pg_offst = ((0xf1600000) >> 18) & 0xfffc, .boot_params = 0x00000100, diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 16cf2482a3e..31820170f30 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -578,7 +578,6 @@ static struct sys_timer cp_timer = { MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ - .phys_ram = 0x00000000, .phys_io = 0x16000000, .io_pg_offst = ((0xf1600000) >> 18) & 0xfffc, .boot_params = 0x00000100, diff --git a/arch/arm/mach-iop3xx/iop321-setup.c b/arch/arm/mach-iop3xx/iop321-setup.c index 80770233b8d..e4f4c52d93d 100644 --- a/arch/arm/mach-iop3xx/iop321-setup.c +++ b/arch/arm/mach-iop3xx/iop321-setup.c @@ -151,7 +151,6 @@ extern void iop321_init_time(void); #if defined(CONFIG_ARCH_IQ80321) MACHINE_START(IQ80321, "Intel IQ80321") /* Maintainer: Intel Corporation */ - .phys_ram = PHYS_OFFSET, .phys_io = IQ80321_UART, .io_pg_offst = ((IQ80321_UART) >> 18) & 0xfffc, .map_io = iq80321_map_io, @@ -163,7 +162,6 @@ MACHINE_END #elif defined(CONFIG_ARCH_IQ31244) MACHINE_START(IQ31244, "Intel IQ31244") /* Maintainer: Intel Corp. */ - .phys_ram = PHYS_OFFSET, .phys_io = IQ31244_UART, .io_pg_offst = ((IQ31244_UART) >> 18) & 0xfffc, .map_io = iq31244_map_io, diff --git a/arch/arm/mach-iop3xx/iop331-setup.c b/arch/arm/mach-iop3xx/iop331-setup.c index e6ea1cba6a1..63585485123 100644 --- a/arch/arm/mach-iop3xx/iop331-setup.c +++ b/arch/arm/mach-iop3xx/iop331-setup.c @@ -195,7 +195,6 @@ extern void iq80332_map_io(void); #if defined(CONFIG_ARCH_IQ80331) MACHINE_START(IQ80331, "Intel IQ80331") /* Maintainer: Intel Corp. */ - .phys_ram = PHYS_OFFSET, .phys_io = 0xfefff000, .io_pg_offst = ((0xfffff000) >> 18) & 0xfffc, // virtual, physical .map_io = iq80331_map_io, @@ -208,7 +207,6 @@ MACHINE_END #elif defined(CONFIG_MACH_IQ80332) MACHINE_START(IQ80332, "Intel IQ80332") /* Maintainer: Intel Corp. */ - .phys_ram = PHYS_OFFSET, .phys_io = 0xfefff000, .io_pg_offst = ((0xfffff000) >> 18) & 0xfffc, // virtual, physical .map_io = iq80332_map_io, diff --git a/arch/arm/mach-ixp2000/enp2611.c b/arch/arm/mach-ixp2000/enp2611.c index 61f6006241b..9e5a13bb39d 100644 --- a/arch/arm/mach-ixp2000/enp2611.c +++ b/arch/arm/mach-ixp2000/enp2611.c @@ -254,7 +254,6 @@ static void __init enp2611_init_machine(void) MACHINE_START(ENP2611, "Radisys ENP-2611 PCI network processor board") /* Maintainer: Lennert Buytenhek */ - .phys_ram = 0x00000000, .phys_io = IXP2000_UART_PHYS_BASE, .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc, .boot_params = 0x00000100, diff --git a/arch/arm/mach-ixp2000/ixdp2400.c b/arch/arm/mach-ixp2000/ixdp2400.c index fd280a93637..7c782403042 100644 --- a/arch/arm/mach-ixp2000/ixdp2400.c +++ b/arch/arm/mach-ixp2000/ixdp2400.c @@ -169,7 +169,6 @@ void ixdp2400_init_irq(void) MACHINE_START(IXDP2400, "Intel IXDP2400 Development Platform") /* Maintainer: MontaVista Software, Inc. */ - .phys_ram = 0x00000000, .phys_io = IXP2000_UART_PHYS_BASE, .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc, .boot_params = 0x00000100, diff --git a/arch/arm/mach-ixp2000/ixdp2800.c b/arch/arm/mach-ixp2000/ixdp2800.c index f9073aa2861..076e3f8acc9 100644 --- a/arch/arm/mach-ixp2000/ixdp2800.c +++ b/arch/arm/mach-ixp2000/ixdp2800.c @@ -285,7 +285,6 @@ void ixdp2800_init_irq(void) MACHINE_START(IXDP2800, "Intel IXDP2800 Development Platform") /* Maintainer: MontaVista Software, Inc. */ - .phys_ram = 0x00000000, .phys_io = IXP2000_UART_PHYS_BASE, .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc, .boot_params = 0x00000100, diff --git a/arch/arm/mach-ixp2000/ixdp2x01.c b/arch/arm/mach-ixp2000/ixdp2x01.c index e6a882f35da..10f06606d46 100644 --- a/arch/arm/mach-ixp2000/ixdp2x01.c +++ b/arch/arm/mach-ixp2000/ixdp2x01.c @@ -376,7 +376,6 @@ static void __init ixdp2x01_init_machine(void) #ifdef CONFIG_ARCH_IXDP2401 MACHINE_START(IXDP2401, "Intel IXDP2401 Development Platform") /* Maintainer: MontaVista Software, Inc. */ - .phys_ram = 0x00000000, .phys_io = IXP2000_UART_PHYS_BASE, .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc, .boot_params = 0x00000100, @@ -390,7 +389,6 @@ MACHINE_END #ifdef CONFIG_ARCH_IXDP2801 MACHINE_START(IXDP2801, "Intel IXDP2801 Development Platform") /* Maintainer: MontaVista Software, Inc. */ - .phys_ram = 0x00000000, .phys_io = IXP2000_UART_PHYS_BASE, .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc, .boot_params = 0x00000100, diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c index 679594a7398..13f8a7ac3ba 100644 --- a/arch/arm/mach-ixp4xx/coyote-setup.c +++ b/arch/arm/mach-ixp4xx/coyote-setup.c @@ -101,7 +101,6 @@ static void __init coyote_init(void) #ifdef CONFIG_ARCH_ADI_COYOTE MACHINE_START(ADI_COYOTE, "ADI Engineering Coyote") /* Maintainer: MontaVista Software, Inc. */ - .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, .map_io = ixp4xx_map_io, @@ -119,7 +118,6 @@ MACHINE_END #ifdef CONFIG_MACH_IXDPG425 MACHINE_START(IXDPG425, "Intel IXDPG425") /* Maintainer: MontaVista Software, Inc. */ - .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, .map_io = ixp4xx_map_io, diff --git a/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/arch/arm/mach-ixp4xx/gtwx5715-setup.c index 03867048997..654e2eed81f 100644 --- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c +++ b/arch/arm/mach-ixp4xx/gtwx5715-setup.c @@ -142,7 +142,6 @@ static void __init gtwx5715_init(void) MACHINE_START(GTWX5715, "Gemtek GTWX5715 (Linksys WRV54G)") /* Maintainer: George Joseph */ - .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_UART2_BASE_PHYS, .io_pg_offst = ((IXP4XX_UART2_BASE_VIRT) >> 18) & 0xfffc, .map_io = ixp4xx_map_io, diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c index c2e105c89c9..da72383ee30 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c @@ -121,7 +121,6 @@ static void __init ixdp425_init(void) #ifdef CONFIG_ARCH_IXDP425 MACHINE_START(IXDP425, "Intel IXDP425 Development Platform") /* Maintainer: MontaVista Software, Inc. */ - .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, .map_io = ixp4xx_map_io, @@ -135,7 +134,6 @@ MACHINE_END #ifdef CONFIG_MACH_IXDP465 MACHINE_START(IXDP465, "Intel IXDP465 Development Platform") /* Maintainer: MontaVista Software, Inc. */ - .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, .map_io = ixp4xx_map_io, @@ -149,7 +147,6 @@ MACHINE_END #ifdef CONFIG_ARCH_PRPMC1100 MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform") /* Maintainer: MontaVista Software, Inc. */ - .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, .map_io = ixp4xx_map_io, @@ -169,7 +166,6 @@ MACHINE_END #ifdef CONFIG_ARCH_AVILA MACHINE_START(AVILA, "Gateworks Avila Network Platform") /* Maintainer: Deepak Saxena */ - .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, .map_io = ixp4xx_map_io, diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c index 49998a8bd4e..856d56f3b2a 100644 --- a/arch/arm/mach-ixp4xx/nas100d-setup.c +++ b/arch/arm/mach-ixp4xx/nas100d-setup.c @@ -124,7 +124,6 @@ static void __init nas100d_init(void) MACHINE_START(NAS100D, "Iomega NAS 100d") /* Maintainer: www.nslu2-linux.org */ - .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC, .boot_params = 0x00000100, diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c index 289e94cb65c..da9340a5343 100644 --- a/arch/arm/mach-ixp4xx/nslu2-setup.c +++ b/arch/arm/mach-ixp4xx/nslu2-setup.c @@ -123,7 +123,6 @@ static void __init nslu2_init(void) MACHINE_START(NSLU2, "Linksys NSLU2") /* Maintainer: www.nslu2-linux.org */ - .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC, .boot_params = 0x00000100, diff --git a/arch/arm/mach-l7200/core.c b/arch/arm/mach-l7200/core.c index 03ed742ae2b..ac626436e96 100644 --- a/arch/arm/mach-l7200/core.c +++ b/arch/arm/mach-l7200/core.c @@ -91,7 +91,6 @@ static void __init l7200_map_io(void) MACHINE_START(L7200, "LinkUp Systems L7200") /* Maintainer: Steve Hill / Scott McConnell */ - .phys_ram = 0xf0000000, .phys_io = 0x80040000, .io_pg_offst = ((0xd0000000) >> 18) & 0xfffc, .map_io = l7200_map_io, diff --git a/arch/arm/mach-lh7a40x/arch-kev7a400.c b/arch/arm/mach-lh7a40x/arch-kev7a400.c index 19f2fa2244c..2cccc27c62e 100644 --- a/arch/arm/mach-lh7a40x/arch-kev7a400.c +++ b/arch/arm/mach-lh7a40x/arch-kev7a400.c @@ -112,7 +112,6 @@ void __init lh7a40x_init_board_irq (void) MACHINE_START (KEV7A400, "Sharp KEV7a400") /* Maintainer: Marc Singer */ - .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((io_p2v (0x80000000))>>18) & 0xfffc, .boot_params = 0xc0000100, diff --git a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c index 4eb962fdb3a..12e23277c5e 100644 --- a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c +++ b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c @@ -317,7 +317,6 @@ lpd7a400_map_io(void) MACHINE_START (LPD7A400, "Logic Product Development LPD7A400-10") /* Maintainer: Marc Singer */ - .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((io_p2v (0x80000000))>>18) & 0xfffc, .boot_params = 0xc0000100, @@ -333,7 +332,6 @@ MACHINE_END MACHINE_START (LPD7A404, "Logic Product Development LPD7A404-10") /* Maintainer: Marc Singer */ - .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((io_p2v (0x80000000))>>18) & 0xfffc, .boot_params = 0xc0000100, diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c index 4b292e93fbe..bdc20b51b07 100644 --- a/arch/arm/mach-omap1/board-generic.c +++ b/arch/arm/mach-omap1/board-generic.c @@ -109,7 +109,6 @@ static void __init omap_generic_map_io(void) MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710") /* Maintainer: Tony Lindgren */ - .phys_ram = 0x10000000, .phys_io = 0xfff00000, .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, .boot_params = 0x10000100, diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c index a07e2c9307f..9533c36a92d 100644 --- a/arch/arm/mach-omap1/board-h2.c +++ b/arch/arm/mach-omap1/board-h2.c @@ -199,7 +199,6 @@ static void __init h2_map_io(void) MACHINE_START(OMAP_H2, "TI-H2") /* Maintainer: Imre Deak */ - .phys_ram = 0x10000000, .phys_io = 0xfff00000, .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, .boot_params = 0x10000100, diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c index 668e278433c..d665efc1c34 100644 --- a/arch/arm/mach-omap1/board-h3.c +++ b/arch/arm/mach-omap1/board-h3.c @@ -215,7 +215,6 @@ static void __init h3_map_io(void) MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board") /* Maintainer: Texas Instruments, Inc. */ - .phys_ram = 0x10000000, .phys_io = 0xfff00000, .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, .boot_params = 0x10000100, diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c index 95f1ff36cdc..652f37c7f90 100644 --- a/arch/arm/mach-omap1/board-innovator.c +++ b/arch/arm/mach-omap1/board-innovator.c @@ -303,7 +303,6 @@ static void __init innovator_map_io(void) MACHINE_START(OMAP_INNOVATOR, "TI-Innovator") /* Maintainer: MontaVista Software, Inc. */ - .phys_ram = 0x10000000, .phys_io = 0xfff00000, .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, .boot_params = 0x10000100, diff --git a/arch/arm/mach-omap1/board-netstar.c b/arch/arm/mach-omap1/board-netstar.c index 0448fa7de8a..58f783930d4 100644 --- a/arch/arm/mach-omap1/board-netstar.c +++ b/arch/arm/mach-omap1/board-netstar.c @@ -149,7 +149,6 @@ postcore_initcall(netstar_late_init); MACHINE_START(NETSTAR, "NetStar OMAP5910") /* Maintainer: Ladislav Michl */ - .phys_ram = 0x10000000, .phys_io = 0xfff00000, .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, .boot_params = 0x10000100, diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c index e990e1bc166..e5d126e8f27 100644 --- a/arch/arm/mach-omap1/board-osk.c +++ b/arch/arm/mach-omap1/board-osk.c @@ -274,7 +274,6 @@ static void __init osk_map_io(void) MACHINE_START(OMAP_OSK, "TI-OSK") /* Maintainer: Dirk Behme */ - .phys_ram = 0x10000000, .phys_io = 0xfff00000, .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, .boot_params = 0x10000100, diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c index 5c975eb5c34..67fada20762 100644 --- a/arch/arm/mach-omap1/board-palmte.c +++ b/arch/arm/mach-omap1/board-palmte.c @@ -76,7 +76,6 @@ static void __init omap_generic_map_io(void) } MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E") - .phys_ram = 0x10000000, .phys_io = 0xfff00000, .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, .boot_params = 0x10000100, diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c index 92ff5dc0735..88708a0c52a 100644 --- a/arch/arm/mach-omap1/board-perseus2.c +++ b/arch/arm/mach-omap1/board-perseus2.c @@ -199,7 +199,6 @@ static void __init omap_perseus2_map_io(void) MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2") /* Maintainer: Kevin Hilman */ - .phys_ram = 0x10000000, .phys_io = 0xfff00000, .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, .boot_params = 0x10000100, diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c index 6f9a6220e78..959b4b847c8 100644 --- a/arch/arm/mach-omap1/board-voiceblue.c +++ b/arch/arm/mach-omap1/board-voiceblue.c @@ -281,7 +281,6 @@ EXPORT_SYMBOL(voiceblue_wdt_ping); MACHINE_START(VOICEBLUE, "VoiceBlue OMAP5910") /* Maintainer: Ladislav Michl */ - .phys_ram = 0x10000000, .phys_io = 0xfff00000, .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, .boot_params = 0x10000100, diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c index c602e7a3d93..b937123e5c6 100644 --- a/arch/arm/mach-omap2/board-generic.c +++ b/arch/arm/mach-omap2/board-generic.c @@ -69,7 +69,6 @@ static void __init omap_generic_map_io(void) MACHINE_START(OMAP_GENERIC, "Generic OMAP24xx") /* Maintainer: Paul Mundt */ - .phys_ram = 0x80000000, .phys_io = 0x48000000, .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, .boot_params = 0x80000100, diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c index f2554469a76..c3c35d40378 100644 --- a/arch/arm/mach-omap2/board-h4.c +++ b/arch/arm/mach-omap2/board-h4.c @@ -186,7 +186,6 @@ static void __init omap_h4_map_io(void) MACHINE_START(OMAP_H4, "OMAP2420 H4 board") /* Maintainer: Paul Mundt */ - .phys_ram = 0x80000000, .phys_io = 0x48000000, .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, .boot_params = 0x80000100, diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index 5a7b873f29b..7ffd2de8f2f 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -342,7 +342,6 @@ static void __init fixup_corgi(struct machine_desc *desc, #ifdef CONFIG_MACH_CORGI MACHINE_START(CORGI, "SHARP Corgi") - .phys_ram = 0xa0000000, .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_corgi, @@ -355,7 +354,6 @@ MACHINE_END #ifdef CONFIG_MACH_SHEPHERD MACHINE_START(SHEPHERD, "SHARP Shepherd") - .phys_ram = 0xa0000000, .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_corgi, @@ -368,7 +366,6 @@ MACHINE_END #ifdef CONFIG_MACH_HUSKY MACHINE_START(HUSKY, "SHARP Husky") - .phys_ram = 0xa0000000, .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_corgi, diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c index 7de159e2ab4..347b9dea24c 100644 --- a/arch/arm/mach-pxa/idp.c +++ b/arch/arm/mach-pxa/idp.c @@ -183,7 +183,6 @@ static void __init idp_map_io(void) MACHINE_START(PXA_IDP, "Vibren PXA255 IDP") /* Maintainer: Vibren Technologies */ - .phys_ram = 0xa0000000, .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .map_io = idp_map_io, diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c index b464bc88ff9..3e26d7ce5bb 100644 --- a/arch/arm/mach-pxa/lubbock.c +++ b/arch/arm/mach-pxa/lubbock.c @@ -437,7 +437,6 @@ static void __init lubbock_map_io(void) MACHINE_START(LUBBOCK, "Intel DBPXA250 Development Platform (aka Lubbock)") /* Maintainer: MontaVista Software Inc. */ - .phys_ram = 0xa0000000, .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .map_io = lubbock_map_io, diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c index 8da9d3efe9a..d5bda60209e 100644 --- a/arch/arm/mach-pxa/mainstone.c +++ b/arch/arm/mach-pxa/mainstone.c @@ -489,7 +489,6 @@ static void __init mainstone_map_io(void) MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)") /* Maintainer: MontaVista Software Inc. */ - .phys_ram = 0xa0000000, .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .map_io = mainstone_map_io, diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index 663c9500598..911e6ff5a9b 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -311,7 +311,6 @@ static void __init fixup_poodle(struct machine_desc *desc, } MACHINE_START(POODLE, "SHARP Poodle") - .phys_ram = 0xa0000000, .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_poodle, diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index a9eacc06555..c094d99ebf5 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -497,7 +497,6 @@ static void __init fixup_spitz(struct machine_desc *desc, #ifdef CONFIG_MACH_SPITZ MACHINE_START(SPITZ, "SHARP Spitz") - .phys_ram = 0xa0000000, .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_spitz, @@ -510,7 +509,6 @@ MACHINE_END #ifdef CONFIG_MACH_BORZOI MACHINE_START(BORZOI, "SHARP Borzoi") - .phys_ram = 0xa0000000, .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_spitz, @@ -523,7 +521,6 @@ MACHINE_END #ifdef CONFIG_MACH_AKITA MACHINE_START(AKITA, "SHARP Akita") - .phys_ram = 0xa0000000, .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_spitz, diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index e4f92efc616..d168286ed47 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -295,7 +295,6 @@ static void __init fixup_tosa(struct machine_desc *desc, } MACHINE_START(TOSA, "SHARP Tosa") - .phys_ram = 0xa0000000, .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_tosa, diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c index 112f7592aca..d4a586e38d5 100644 --- a/arch/arm/mach-realview/realview_eb.c +++ b/arch/arm/mach-realview/realview_eb.c @@ -166,7 +166,6 @@ static void __init realview_eb_init(void) MACHINE_START(REALVIEW_EB, "ARM-RealView EB") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ - .phys_ram = 0x00000000, .phys_io = REALVIEW_UART0_BASE, .io_pg_offst = (IO_ADDRESS(REALVIEW_UART0_BASE) >> 18) & 0xfffc, .boot_params = 0x00000100, diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c index 5c4ac1c008a..208a2b5dba1 100644 --- a/arch/arm/mach-rpc/riscpc.c +++ b/arch/arm/mach-rpc/riscpc.c @@ -177,7 +177,6 @@ extern struct sys_timer ioc_timer; MACHINE_START(RISCPC, "Acorn-RiscPC") /* Maintainer: Russell King */ - .phys_ram = 0x10000000, .phys_io = 0x03000000, .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc, .boot_params = 0x10000100, diff --git a/arch/arm/mach-s3c2410/mach-anubis.c b/arch/arm/mach-s3c2410/mach-anubis.c index 0f81fc0c2f7..3e327b8e46b 100644 --- a/arch/arm/mach-s3c2410/mach-anubis.c +++ b/arch/arm/mach-s3c2410/mach-anubis.c @@ -294,7 +294,6 @@ static void __init anubis_map_io(void) MACHINE_START(ANUBIS, "Simtec-Anubis") /* Maintainer: Ben Dooks */ - .phys_ram = S3C2410_SDRAM_PA, .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c index 4d962717fdf..995bb8add33 100644 --- a/arch/arm/mach-s3c2410/mach-bast.c +++ b/arch/arm/mach-s3c2410/mach-bast.c @@ -527,7 +527,6 @@ static void __init bast_init(void) MACHINE_START(BAST, "Simtec-BAST") /* Maintainer: Ben Dooks */ - .phys_ram = S3C2410_SDRAM_PA, .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c index 0aa8760598f..1c316f14ed9 100644 --- a/arch/arm/mach-s3c2410/mach-h1940.c +++ b/arch/arm/mach-s3c2410/mach-h1940.c @@ -171,7 +171,6 @@ static void __init h1940_init(void) MACHINE_START(H1940, "IPAQ-H1940") /* Maintainer: Ben Dooks */ - .phys_ram = S3C2410_SDRAM_PA, .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c index 378d640ab00..116ac316996 100644 --- a/arch/arm/mach-s3c2410/mach-n30.c +++ b/arch/arm/mach-s3c2410/mach-n30.c @@ -128,7 +128,6 @@ MACHINE_START(N30, "Acer-N30") /* Maintainer: Christer Weinigel , Ben Dooks */ - .phys_ram = S3C2410_SDRAM_PA, .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, diff --git a/arch/arm/mach-s3c2410/mach-nexcoder.c b/arch/arm/mach-s3c2410/mach-nexcoder.c index 42b0eeff2e0..07d09509a62 100644 --- a/arch/arm/mach-s3c2410/mach-nexcoder.c +++ b/arch/arm/mach-s3c2410/mach-nexcoder.c @@ -148,7 +148,6 @@ static void __init nexcoder_map_io(void) MACHINE_START(NEXCODER_2440, "NexVision - Nexcoder 2440") /* Maintainer: Guillaume GOURAT */ - .phys_ram = S3C2410_SDRAM_PA, .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, diff --git a/arch/arm/mach-s3c2410/mach-otom.c b/arch/arm/mach-s3c2410/mach-otom.c index a2eb9ed48fc..b39daedf93c 100644 --- a/arch/arm/mach-s3c2410/mach-otom.c +++ b/arch/arm/mach-s3c2410/mach-otom.c @@ -116,7 +116,6 @@ static void __init otom11_map_io(void) MACHINE_START(OTOM, "Nex Vision - Otom 1.1") /* Maintainer: Guillaume GOURAT */ - .phys_ram = S3C2410_SDRAM_PA, .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, diff --git a/arch/arm/mach-s3c2410/mach-rx3715.c b/arch/arm/mach-s3c2410/mach-rx3715.c index f8d86d1e16b..0260ed5ab94 100644 --- a/arch/arm/mach-s3c2410/mach-rx3715.c +++ b/arch/arm/mach-s3c2410/mach-rx3715.c @@ -205,7 +205,6 @@ static void __init rx3715_init_machine(void) MACHINE_START(RX3715, "IPAQ-RX3715") /* Maintainer: Ben Dooks */ - .phys_ram = S3C2410_SDRAM_PA, .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c index 2c91965ee1c..1e76e1fdfce 100644 --- a/arch/arm/mach-s3c2410/mach-smdk2410.c +++ b/arch/arm/mach-s3c2410/mach-smdk2410.c @@ -115,7 +115,6 @@ static void __init smdk2410_init_irq(void) MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch * to SMDK2410 */ /* Maintainer: Jonas Dietsche */ - .phys_ram = S3C2410_SDRAM_PA, .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, diff --git a/arch/arm/mach-s3c2410/mach-smdk2440.c b/arch/arm/mach-s3c2410/mach-smdk2440.c index 4e31118533e..f4315721c3b 100644 --- a/arch/arm/mach-s3c2410/mach-smdk2440.c +++ b/arch/arm/mach-s3c2410/mach-smdk2440.c @@ -216,7 +216,6 @@ static void __init smdk2440_machine_init(void) MACHINE_START(S3C2440, "SMDK2440") /* Maintainer: Ben Dooks */ - .phys_ram = S3C2410_SDRAM_PA, .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c index ae7e099bf6c..785fc9cdcf7 100644 --- a/arch/arm/mach-s3c2410/mach-vr1000.c +++ b/arch/arm/mach-s3c2410/mach-vr1000.c @@ -395,7 +395,6 @@ static void __init vr1000_map_io(void) MACHINE_START(VR1000, "Thorcom-VR1000") /* Maintainer: Ben Dooks */ - .phys_ram = S3C2410_SDRAM_PA, .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c index a66ac61233a..a599bb0d4ab 100644 --- a/arch/arm/mach-sa1100/assabet.c +++ b/arch/arm/mach-sa1100/assabet.c @@ -447,7 +447,6 @@ static void __init assabet_map_io(void) MACHINE_START(ASSABET, "Intel-Assabet") - .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, .boot_params = 0xc0000100, diff --git a/arch/arm/mach-sa1100/badge4.c b/arch/arm/mach-sa1100/badge4.c index edccd5eb06b..f60b7a66dfa 100644 --- a/arch/arm/mach-sa1100/badge4.c +++ b/arch/arm/mach-sa1100/badge4.c @@ -297,7 +297,6 @@ static void __init badge4_map_io(void) } MACHINE_START(BADGE4, "Hewlett-Packard Laboratories BadgePAD 4") - .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, .boot_params = 0xc0000100, diff --git a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c index 508593722bc..8269a9ef9af 100644 --- a/arch/arm/mach-sa1100/cerf.c +++ b/arch/arm/mach-sa1100/cerf.c @@ -135,7 +135,6 @@ static void __init cerf_init(void) MACHINE_START(CERF, "Intrinsyc CerfBoard/CerfCube") /* Maintainer: support@intrinsyc.com */ - .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, .map_io = cerf_map_io, diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c index 522abc036d3..6888816a193 100644 --- a/arch/arm/mach-sa1100/collie.c +++ b/arch/arm/mach-sa1100/collie.c @@ -191,7 +191,6 @@ static void __init collie_map_io(void) } MACHINE_START(COLLIE, "Sharp-Collie") - .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, .map_io = collie_map_io, diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c index e8352b7f74b..b04d9227102 100644 --- a/arch/arm/mach-sa1100/h3600.c +++ b/arch/arm/mach-sa1100/h3600.c @@ -392,7 +392,6 @@ static void __init h3100_map_io(void) } MACHINE_START(H3100, "Compaq iPAQ H3100") - .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, .boot_params = 0xc0000100, @@ -510,7 +509,6 @@ static void __init h3600_map_io(void) } MACHINE_START(H3600, "Compaq iPAQ H3600") - .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, .boot_params = 0xc0000100, @@ -897,7 +895,6 @@ static void __init h3800_map_io(void) } MACHINE_START(H3800, "Compaq iPAQ H3800") - .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, .boot_params = 0xc0000100, diff --git a/arch/arm/mach-sa1100/hackkit.c b/arch/arm/mach-sa1100/hackkit.c index c922e043c42..046b213efd5 100644 --- a/arch/arm/mach-sa1100/hackkit.c +++ b/arch/arm/mach-sa1100/hackkit.c @@ -195,7 +195,6 @@ static void __init hackkit_init(void) */ MACHINE_START(HACKKIT, "HackKit Cpu Board") - .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, .boot_params = 0xc0000100, diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c index 2f671cc3cb9..17f5a43acdb 100644 --- a/arch/arm/mach-sa1100/jornada720.c +++ b/arch/arm/mach-sa1100/jornada720.c @@ -173,7 +173,6 @@ static void __init jornada720_mach_init(void) MACHINE_START(JORNADA720, "HP Jornada 720") /* Maintainer: Michael Gernoth */ - .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, .boot_params = 0xc0000100, diff --git a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c index 8c9e3dd5294..07d3a696ae7 100644 --- a/arch/arm/mach-sa1100/lart.c +++ b/arch/arm/mach-sa1100/lart.c @@ -60,7 +60,6 @@ static void __init lart_map_io(void) } MACHINE_START(LART, "LART") - .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, .boot_params = 0xc0000100, diff --git a/arch/arm/mach-sa1100/pleb.c b/arch/arm/mach-sa1100/pleb.c index 58c18f9e9b7..0709ebab531 100644 --- a/arch/arm/mach-sa1100/pleb.c +++ b/arch/arm/mach-sa1100/pleb.c @@ -146,7 +146,6 @@ static void __init pleb_map_io(void) } MACHINE_START(PLEB, "PLEB") - .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, .map_io = pleb_map_io, diff --git a/arch/arm/mach-sa1100/shannon.c b/arch/arm/mach-sa1100/shannon.c index 7482288278d..5aafe0b5699 100644 --- a/arch/arm/mach-sa1100/shannon.c +++ b/arch/arm/mach-sa1100/shannon.c @@ -83,7 +83,6 @@ static void __init shannon_map_io(void) } MACHINE_START(SHANNON, "Shannon (AKA: Tuxscreen)") - .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, .boot_params = 0xc0000100, diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c index 439ddc9b06d..d2c23b2c34d 100644 --- a/arch/arm/mach-sa1100/simpad.c +++ b/arch/arm/mach-sa1100/simpad.c @@ -229,7 +229,6 @@ arch_initcall(simpad_init); MACHINE_START(SIMPAD, "Simpad") /* Maintainer: Holger Freyther */ - .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, .boot_params = 0xc0000100, diff --git a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c index 2d428b6dbb5..877600e212d 100644 --- a/arch/arm/mach-shark/core.c +++ b/arch/arm/mach-shark/core.c @@ -111,7 +111,6 @@ static struct sys_timer shark_timer = { MACHINE_START(SHARK, "Shark") /* Maintainer: Alexander Schulz */ - .phys_ram = 0x08000000, .phys_io = 0x40000000, .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc, .boot_params = 0x08003000, diff --git a/arch/arm/mach-versatile/versatile_ab.c b/arch/arm/mach-versatile/versatile_ab.c index e74c8a2fbb9..1eb59678207 100644 --- a/arch/arm/mach-versatile/versatile_ab.c +++ b/arch/arm/mach-versatile/versatile_ab.c @@ -36,7 +36,6 @@ MACHINE_START(VERSATILE_AB, "ARM-Versatile AB") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ - .phys_ram = 0x00000000, .phys_io = 0x101f1000, .io_pg_offst = ((0xf11f1000) >> 18) & 0xfffc, .boot_params = 0x00000100, diff --git a/arch/arm/mach-versatile/versatile_pb.c b/arch/arm/mach-versatile/versatile_pb.c index 22d5ca07f75..f17ab4fb548 100644 --- a/arch/arm/mach-versatile/versatile_pb.c +++ b/arch/arm/mach-versatile/versatile_pb.c @@ -100,7 +100,6 @@ arch_initcall(versatile_pb_init); MACHINE_START(VERSATILE_PB, "ARM-Versatile PB") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ - .phys_ram = 0x00000000, .phys_io = 0x101f1000, .io_pg_offst = ((0xf11f1000) >> 18) & 0xfffc, .boot_params = 0x00000100, diff --git a/include/asm-arm/mach/arch.h b/include/asm-arm/mach/arch.h index eb262e078c4..8222bf9fc36 100644 --- a/include/asm-arm/mach/arch.h +++ b/include/asm-arm/mach/arch.h @@ -20,7 +20,7 @@ struct machine_desc { * by assembler code in head-armv.S */ unsigned int nr; /* architecture number */ - unsigned int phys_ram; /* start of physical ram */ + unsigned int __deprecated phys_ram; /* start of physical ram */ unsigned int phys_io; /* start of physical io */ unsigned int io_pg_offst; /* byte offset for io * page tabe entry */ -- GitLab From e72b04756f16e40dfd6dab3da81e03fe6dfe16e6 Mon Sep 17 00:00:00 2001 From: "Hyok S. Choi" Date: Fri, 13 Jan 2006 21:04:17 +0000 Subject: [PATCH 123/465] [ARM] start_thread fixup for nommu mode This patch supports start_thread in nommu mode which requires the base index register. Signed-off-by: Hyok S. Choi Signed-off-by: Russell King --- include/asm-arm/processor.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/asm-arm/processor.h b/include/asm-arm/processor.h index 31290694648..04f4d34c631 100644 --- a/include/asm-arm/processor.h +++ b/include/asm-arm/processor.h @@ -49,6 +49,12 @@ struct thread_struct { #define INIT_THREAD { } +#ifdef CONFIG_MMU +#define nommu_start_thread(regs) do { } while (0) +#else +#define nommu_start_thread(regs) regs->ARM_r10 = current->mm->start_data +#endif + #define start_thread(regs,pc,sp) \ ({ \ unsigned long *stack = (unsigned long *)sp; \ @@ -65,6 +71,7 @@ struct thread_struct { regs->ARM_r2 = stack[2]; /* r2 (envp) */ \ regs->ARM_r1 = stack[1]; /* r1 (argv) */ \ regs->ARM_r0 = stack[0]; /* r0 (argc) */ \ + nommu_start_thread(regs); \ }) /* Forward declaration, a strange C thing */ -- GitLab From afeb90ca08000cbd75f22836e667f368e25fe3ac Mon Sep 17 00:00:00 2001 From: "Hyok S. Choi" Date: Fri, 13 Jan 2006 21:05:25 +0000 Subject: [PATCH 124/465] [ARM] Support register switch in nommu mode This patch adds register switch support in nommu mode. Signed-off-by: Hyok S. Choi Signed-off-by: Russell King --- arch/arm/kernel/entry-armv.S | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index a52baedf626..fb8e7f4c4b3 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -3,6 +3,7 @@ * * Copyright (C) 1996,1997,1998 Russell King. * ARM700 fix by Matthew Godbolt (linux-user@willothewisp.demon.co.uk) + * nommu support by Hyok S. Choi (hyok.choi@samsung.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -538,7 +539,11 @@ ENTRY(__switch_to) add ip, r1, #TI_CPU_SAVE ldr r3, [r2, #TI_TP_VALUE] stmia ip!, {r4 - sl, fp, sp, lr} @ Store most regs on stack +#ifndef CONFIG_MMU + add r2, r2, #TI_CPU_DOMAIN +#else ldr r6, [r2, #TI_CPU_DOMAIN]! +#endif #if __LINUX_ARM_ARCH__ >= 6 #ifdef CONFIG_CPU_MPCORE clrex @@ -556,7 +561,9 @@ ENTRY(__switch_to) mov r4, #0xffff0fff str r3, [r4, #-15] @ TLS val at 0xffff0ff0 #endif +#ifdef CONFIG_MMU mcr p15, 0, r6, c3, c0, 0 @ Set domain register +#endif #ifdef CONFIG_VFP @ Always disable VFP so we can lazily save/restore the old @ state. This occurs in the context of the previous thread. -- GitLab From 23b0ca5bf52cef0ab0f0fe247cb91cbef836e7eb Mon Sep 17 00:00:00 2001 From: Per Liden Date: Fri, 13 Jan 2006 13:06:40 -0800 Subject: [PATCH 125/465] [PATCH] genetlink: don't touch module ref count Increasing the module ref count at registration will block the module from ever being unloaded. In fact, genetlink should not care about the owner at all. This patch removes the owner field from the struct registered with genetlink. Signed-off-by: Per Liden Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- include/net/genetlink.h | 1 - net/netlink/genetlink.c | 7 ------- net/tipc/netlink.c | 1 - 3 files changed, 9 deletions(-) diff --git a/include/net/genetlink.h b/include/net/genetlink.h index c5b96b2b815..805de50df00 100644 --- a/include/net/genetlink.h +++ b/include/net/genetlink.h @@ -22,7 +22,6 @@ struct genl_family char name[GENL_NAMSIZ]; unsigned int version; unsigned int maxattr; - struct module * owner; struct nlattr ** attrbuf; /* private */ struct list_head ops_list; /* private */ struct list_head family_list; /* private */ diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 3b1378498d5..4ae1538c54a 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -222,11 +222,6 @@ int genl_register_family(struct genl_family *family) goto errout_locked; } - if (!try_module_get(family->owner)) { - err = -EBUSY; - goto errout_locked; - } - if (family->id == GENL_ID_GENERATE) { u16 newid = genl_generate_id(); @@ -283,7 +278,6 @@ int genl_unregister_family(struct genl_family *family) INIT_LIST_HEAD(&family->ops_list); genl_unlock(); - module_put(family->owner); kfree(family->attrbuf); genl_ctrl_event(CTRL_CMD_DELFAMILY, family); return 0; @@ -535,7 +529,6 @@ static struct genl_family genl_ctrl = { .name = "nlctrl", .version = 0x1, .maxattr = CTRL_ATTR_MAX, - .owner = THIS_MODULE, }; static int __init genl_init(void) diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index 6fe95acde4f..19b3f402253 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c @@ -72,7 +72,6 @@ static struct genl_family family = { .version = TIPC_GENL_VERSION, .hdrsize = TIPC_GENL_HDRLEN, .maxattr = 0, - .owner = THIS_MODULE, }; static struct genl_ops ops = { -- GitLab From 5ff3fd27161127cc464fc04548d58672a6a8272a Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 13 Jan 2006 21:09:17 +0000 Subject: [PATCH 126/465] [ARM] Remove useless 'default n' from Kconfig files The default is already 'n' so there's no need to explicitly state it. Signed-off-by: Russell King --- arch/arm/mach-realview/Kconfig | 1 - arch/arm/mach-versatile/Kconfig | 1 - arch/arm/plat-omap/Kconfig | 3 --- 3 files changed, 5 deletions(-) diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig index 129976866d4..17f5f4439fe 100644 --- a/arch/arm/mach-realview/Kconfig +++ b/arch/arm/mach-realview/Kconfig @@ -3,7 +3,6 @@ menu "RealView platform type" config MACH_REALVIEW_EB bool "Support RealView/EB platform" - default n select ARM_GIC help Include support for the ARM(R) RealView Emulation Baseboard platform. diff --git a/arch/arm/mach-versatile/Kconfig b/arch/arm/mach-versatile/Kconfig index 8d787f4c78e..95096afd527 100644 --- a/arch/arm/mach-versatile/Kconfig +++ b/arch/arm/mach-versatile/Kconfig @@ -9,7 +9,6 @@ config ARCH_VERSATILE_PB config MACH_VERSATILE_AB bool "Support Versatile/AB platform" - default n help Include support for the ARM(R) Versatile/AP platform. diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index 9693e9b4ffd..0887bb2a255 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -22,7 +22,6 @@ comment "OMAP Feature Selections" config OMAP_RESET_CLOCKS bool "Reset unused clocks during boot" depends on ARCH_OMAP - default n help Say Y if you want to reset unused clocks during boot. This option saves power, but assumes all drivers are @@ -44,7 +43,6 @@ config OMAP_MUX config OMAP_MUX_DEBUG bool "Multiplexing debug output" depends on OMAP_MUX - default n help Makes the multiplexing functions print out a lot of debug info. This is useful if you want to find out the correct values of the @@ -93,7 +91,6 @@ config OMAP_32K_TIMER_HZ config OMAP_DM_TIMER bool "Use dual-mode timer" - default n depends on ARCH_OMAP16XX help Select this option if you want to use OMAP Dual-Mode timers. -- GitLab From fa0fe48fcca9ea7f8c13e21d2646bbaa1747d183 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 13 Jan 2006 21:30:48 +0000 Subject: [PATCH 127/465] [ARM] Separate VIC (vectored interrupt controller) support from Versatile Other machines may wish to make use of the VIC support code, so move it to arch/arm/common. Signed-off-by: Russell King --- arch/arm/Kconfig | 1 + arch/arm/common/Kconfig | 7 +- arch/arm/common/Makefile | 1 + arch/arm/common/vic.c | 92 ++++++++++++++++++++ arch/arm/mach-versatile/core.c | 58 ++---------- include/asm-arm/arch-versatile/entry-macro.S | 1 + include/asm-arm/arch-versatile/platform.h | 23 +---- include/asm-arm/hardware/vic.h | 45 ++++++++++ 8 files changed, 151 insertions(+), 77 deletions(-) create mode 100644 arch/arm/common/vic.c create mode 100644 include/asm-arm/hardware/vic.h diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 50b9afa8ae6..c4d585e2de7 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -180,6 +180,7 @@ config ARCH_OMAP config ARCH_VERSATILE bool "Versatile" select ARM_AMBA + select ARM_VIC select ICST307 help This enables support for ARM Ltd Versatile board. diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig index d7509c7a3c5..5e34ca6d38b 100644 --- a/arch/arm/common/Kconfig +++ b/arch/arm/common/Kconfig @@ -1,7 +1,10 @@ -config ICST525 +config ARM_GIC bool -config ARM_GIC +config ARM_VIC + bool + +config ICST525 bool config ICST307 diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile index ec8d17c9690..c81a2ff6b5b 100644 --- a/arch/arm/common/Makefile +++ b/arch/arm/common/Makefile @@ -4,6 +4,7 @@ obj-y += rtctime.o obj-$(CONFIG_ARM_GIC) += gic.o +obj-$(CONFIG_ARM_VIC) += vic.o obj-$(CONFIG_ICST525) += icst525.o obj-$(CONFIG_ICST307) += icst307.o obj-$(CONFIG_SA1111) += sa1111.o diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c new file mode 100644 index 00000000000..a45ed1687a5 --- /dev/null +++ b/arch/arm/common/vic.c @@ -0,0 +1,92 @@ +/* + * linux/arch/arm/common/vic.c + * + * Copyright (C) 1999 - 2003 ARM Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include + +#include +#include +#include +#include + +static void __iomem *vic_base; + +static void vic_mask_irq(unsigned int irq) +{ + irq -= IRQ_VIC_START; + writel(1 << irq, vic_base + VIC_INT_ENABLE_CLEAR); +} + +static void vic_unmask_irq(unsigned int irq) +{ + irq -= IRQ_VIC_START; + writel(1 << irq, vic_base + VIC_INT_ENABLE); +} + +static struct irqchip vic_chip = { + .ack = vic_mask_irq, + .mask = vic_mask_irq, + .unmask = vic_unmask_irq, +}; + +void __init vic_init(void __iomem *base, u32 vic_sources) +{ + unsigned int i; + + vic_base = base; + + /* Disable all interrupts initially. */ + + writel(0, vic_base + VIC_INT_SELECT); + writel(0, vic_base + VIC_INT_ENABLE); + writel(~0, vic_base + VIC_INT_ENABLE_CLEAR); + writel(0, vic_base + VIC_IRQ_STATUS); + writel(0, vic_base + VIC_ITCR); + writel(~0, vic_base + VIC_INT_SOFT_CLEAR); + + /* + * Make sure we clear all existing interrupts + */ + writel(0, vic_base + VIC_VECT_ADDR); + for (i = 0; i < 19; i++) { + unsigned int value; + + value = readl(vic_base + VIC_VECT_ADDR); + writel(value, vic_base + VIC_VECT_ADDR); + } + + for (i = 0; i < 16; i++) { + void __iomem *reg = vic_base + VIC_VECT_CNTL0 + (i * 4); + writel(VIC_VECT_CNTL_ENABLE | i, reg); + } + + writel(32, vic_base + VIC_DEF_VECT_ADDR); + + for (i = 0; i < 32; i++) { + unsigned int irq = IRQ_VIC_START + i; + + set_irq_chip(irq, &vic_chip); + + if (vic_sources & (1 << i)) { + set_irq_handler(irq, do_level_IRQ); + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + } + } +} diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 90023745b23..9ebbe808b41 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -56,24 +57,6 @@ #define VA_VIC_BASE __io_address(VERSATILE_VIC_BASE) #define VA_SIC_BASE __io_address(VERSATILE_SIC_BASE) -static void vic_mask_irq(unsigned int irq) -{ - irq -= IRQ_VIC_START; - writel(1 << irq, VA_VIC_BASE + VIC_IRQ_ENABLE_CLEAR); -} - -static void vic_unmask_irq(unsigned int irq) -{ - irq -= IRQ_VIC_START; - writel(1 << irq, VA_VIC_BASE + VIC_IRQ_ENABLE); -} - -static struct irqchip vic_chip = { - .ack = vic_mask_irq, - .mask = vic_mask_irq, - .unmask = vic_unmask_irq, -}; - static void sic_mask_irq(unsigned int irq) { irq -= IRQ_SIC_START; @@ -127,43 +110,12 @@ sic_handle_irq(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) void __init versatile_init_irq(void) { - unsigned int i, value; - - /* Disable all interrupts initially. */ + unsigned int i; - writel(0, VA_VIC_BASE + VIC_INT_SELECT); - writel(0, VA_VIC_BASE + VIC_IRQ_ENABLE); - writel(~0, VA_VIC_BASE + VIC_IRQ_ENABLE_CLEAR); - writel(0, VA_VIC_BASE + VIC_IRQ_STATUS); - writel(0, VA_VIC_BASE + VIC_ITCR); - writel(~0, VA_VIC_BASE + VIC_IRQ_SOFT_CLEAR); - - /* - * Make sure we clear all existing interrupts - */ - writel(0, VA_VIC_BASE + VIC_VECT_ADDR); - for (i = 0; i < 19; i++) { - value = readl(VA_VIC_BASE + VIC_VECT_ADDR); - writel(value, VA_VIC_BASE + VIC_VECT_ADDR); - } - - for (i = 0; i < 16; i++) { - value = readl(VA_VIC_BASE + VIC_VECT_CNTL0 + (i * 4)); - writel(value | VICVectCntl_Enable | i, VA_VIC_BASE + VIC_VECT_CNTL0 + (i * 4)); - } - - writel(32, VA_VIC_BASE + VIC_DEF_VECT_ADDR); - - for (i = IRQ_VIC_START; i <= IRQ_VIC_END; i++) { - if (i != IRQ_VICSOURCE31) { - set_irq_chip(i, &vic_chip); - set_irq_handler(i, do_level_IRQ); - set_irq_flags(i, IRQF_VALID | IRQF_PROBE); - } - } + vic_init(VA_VIC_BASE, ~(1 << 31)); set_irq_handler(IRQ_VICSOURCE31, sic_handle_irq); - vic_unmask_irq(IRQ_VICSOURCE31); + enable_irq(IRQ_VICSOURCE31); /* Do second interrupt controller */ writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR); @@ -877,7 +829,7 @@ static unsigned long versatile_gettimeoffset(void) ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff; do { ticks1 = ticks2; - status = __raw_readl(VA_IC_BASE + VIC_IRQ_RAW_STATUS); + status = __raw_readl(VA_IC_BASE + VIC_RAW_STATUS); ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff; } while (ticks2 > ticks1); diff --git a/include/asm-arm/arch-versatile/entry-macro.S b/include/asm-arm/arch-versatile/entry-macro.S index 58f0d71759f..feff771c0a0 100644 --- a/include/asm-arm/arch-versatile/entry-macro.S +++ b/include/asm-arm/arch-versatile/entry-macro.S @@ -8,6 +8,7 @@ * warranty of any kind, whether express or implied. */ #include +#include .macro disable_fiq .endm diff --git a/include/asm-arm/arch-versatile/platform.h b/include/asm-arm/arch-versatile/platform.h index cbdd9fb9633..72ef874567d 100644 --- a/include/asm-arm/arch-versatile/platform.h +++ b/include/asm-arm/arch-versatile/platform.h @@ -293,26 +293,7 @@ * VERSATILE_SYS_IC * */ -#define VIC_IRQ_STATUS 0 -#define VIC_FIQ_STATUS 0x04 -#define VIC_IRQ_RAW_STATUS 0x08 -#define VIC_INT_SELECT 0x0C /* 1 = FIQ, 0 = IRQ */ -#define VIC_IRQ_ENABLE 0x10 /* 1 = enable, 0 = disable */ -#define VIC_IRQ_ENABLE_CLEAR 0x14 -#define VIC_IRQ_SOFT 0x18 -#define VIC_IRQ_SOFT_CLEAR 0x1C -#define VIC_PROTECT 0x20 -#define VIC_VECT_ADDR 0x30 -#define VIC_DEF_VECT_ADDR 0x34 -#define VIC_VECT_ADDR0 0x100 /* 0 to 15 */ -#define VIC_VECT_CNTL0 0x200 /* 0 to 15 */ -#define VIC_ITCR 0x300 /* VIC test control register */ - -#define VIC_FIQ_RAW_STATUS 0x08 -#define VIC_FIQ_ENABLE 0x10 /* 1 = enable, 0 = disable */ -#define VIC_FIQ_ENABLE_CLEAR 0x14 -#define VIC_FIQ_SOFT 0x18 -#define VIC_FIQ_SOFT_CLEAR 0x1C +/* VIC definitions in include/asm-arm/hardware/vic.h */ #define SIC_IRQ_STATUS 0 #define SIC_IRQ_RAW_STATUS 0x04 @@ -325,8 +306,6 @@ #define SIC_INT_PIC_ENABLES 0x20 /* set interrupt pass through bits */ #define SIC_INT_PIC_ENABLEC 0x24 /* Clear interrupt pass through bits */ -#define VICVectCntl_Enable (1 << 5) - /* ------------------------------------------------------------------------ * Interrupts - bit assignment (primary) * ------------------------------------------------------------------------ diff --git a/include/asm-arm/hardware/vic.h b/include/asm-arm/hardware/vic.h new file mode 100644 index 00000000000..81825eb54c9 --- /dev/null +++ b/include/asm-arm/hardware/vic.h @@ -0,0 +1,45 @@ +/* + * linux/include/asm-arm/hardware/vic.h + * + * Copyright (c) ARM Limited 2003. All rights reserved. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARM_HARDWARE_VIC_H +#define __ASM_ARM_HARDWARE_VIC_H + +#define VIC_IRQ_STATUS 0x00 +#define VIC_FIQ_STATUS 0x04 +#define VIC_RAW_STATUS 0x08 +#define VIC_INT_SELECT 0x0c /* 1 = FIQ, 0 = IRQ */ +#define VIC_INT_ENABLE 0x10 /* 1 = enable, 0 = disable */ +#define VIC_INT_ENABLE_CLEAR 0x14 +#define VIC_INT_SOFT 0x18 +#define VIC_INT_SOFT_CLEAR 0x1c +#define VIC_PROTECT 0x20 +#define VIC_VECT_ADDR 0x30 +#define VIC_DEF_VECT_ADDR 0x34 + +#define VIC_VECT_ADDR0 0x100 /* 0 to 15 */ +#define VIC_VECT_CNTL0 0x200 /* 0 to 15 */ +#define VIC_ITCR 0x300 /* VIC test control register */ + +#define VIC_VECT_CNTL_ENABLE (1 << 5) + +#ifndef __ASSEMBLY__ +void vic_init(void __iomem *base, u32 vic_sources); +#endif + +#endif -- GitLab From e2862f6a833ea26591c7feb755dc2e46909182a6 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 13 Jan 2006 21:37:07 +0000 Subject: [PATCH 128/465] [SERIAL] convert uart_state.sem to uart_state.mutex semaphore to mutex conversion. the conversion was generated via scripts, and the result was validated automatically via a script as well. build and boot tested. Signed-off-by: Ingo Molnar Signed-off-by: Russell King --- drivers/serial/pmac_zilog.c | 9 +++--- drivers/serial/serial_core.c | 60 ++++++++++++++++++------------------ include/linux/serial_core.h | 3 +- 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index 5f52883e64d..4e03a87f3fb 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c @@ -69,7 +69,6 @@ #include #include #include -#include #if defined (CONFIG_SERIAL_PMACZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) #define SUPPORT_SYSRQ @@ -1593,7 +1592,7 @@ static int pmz_suspend(struct macio_dev *mdev, pm_message_t pm_state) state = pmz_uart_reg.state + uap->port.line; mutex_lock(&pmz_irq_mutex); - down(&state->sem); + mutex_lock(&state->mutex); spin_lock_irqsave(&uap->port.lock, flags); @@ -1624,7 +1623,7 @@ static int pmz_suspend(struct macio_dev *mdev, pm_message_t pm_state) /* Shut the chip down */ pmz_set_scc_power(uap, 0); - up(&state->sem); + mutex_unlock(&state->mutex); mutex_unlock(&pmz_irq_mutex); pmz_debug("suspend, switching complete\n"); @@ -1653,7 +1652,7 @@ static int pmz_resume(struct macio_dev *mdev) state = pmz_uart_reg.state + uap->port.line; mutex_lock(&pmz_irq_mutex); - down(&state->sem); + mutex_lock(&state->mutex); spin_lock_irqsave(&uap->port.lock, flags); if (!ZS_IS_OPEN(uap) && !ZS_IS_CONS(uap)) { @@ -1685,7 +1684,7 @@ static int pmz_resume(struct macio_dev *mdev) } bail: - up(&state->sem); + mutex_unlock(&state->mutex); mutex_unlock(&pmz_irq_mutex); /* Right now, we deal with delay by blocking here, I'll be diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 2ca620900bc..943770470b9 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -638,7 +638,7 @@ static int uart_set_info(struct uart_state *state, * module insertion/removal doesn't change anything * under us. */ - down(&state->sem); + mutex_lock(&state->mutex); change_irq = new_serial.irq != port->irq; @@ -797,7 +797,7 @@ static int uart_set_info(struct uart_state *state, } else retval = uart_startup(state, 1); exit: - up(&state->sem); + mutex_unlock(&state->mutex); return retval; } @@ -834,7 +834,7 @@ static int uart_tiocmget(struct tty_struct *tty, struct file *file) struct uart_port *port = state->port; int result = -EIO; - down(&state->sem); + mutex_lock(&state->mutex); if ((!file || !tty_hung_up_p(file)) && !(tty->flags & (1 << TTY_IO_ERROR))) { result = port->mctrl; @@ -843,7 +843,7 @@ static int uart_tiocmget(struct tty_struct *tty, struct file *file) result |= port->ops->get_mctrl(port); spin_unlock_irq(&port->lock); } - up(&state->sem); + mutex_unlock(&state->mutex); return result; } @@ -856,13 +856,13 @@ uart_tiocmset(struct tty_struct *tty, struct file *file, struct uart_port *port = state->port; int ret = -EIO; - down(&state->sem); + mutex_lock(&state->mutex); if ((!file || !tty_hung_up_p(file)) && !(tty->flags & (1 << TTY_IO_ERROR))) { uart_update_mctrl(port, set, clear); ret = 0; } - up(&state->sem); + mutex_unlock(&state->mutex); return ret; } @@ -873,12 +873,12 @@ static void uart_break_ctl(struct tty_struct *tty, int break_state) BUG_ON(!kernel_locked()); - down(&state->sem); + mutex_lock(&state->mutex); if (port->type != PORT_UNKNOWN) port->ops->break_ctl(port, break_state); - up(&state->sem); + mutex_unlock(&state->mutex); } static int uart_do_autoconfig(struct uart_state *state) @@ -894,7 +894,7 @@ static int uart_do_autoconfig(struct uart_state *state) * changing, and hence any extra opens of the port while * we're auto-configuring. */ - if (down_interruptible(&state->sem)) + if (mutex_lock_interruptible(&state->mutex)) return -ERESTARTSYS; ret = -EBUSY; @@ -920,7 +920,7 @@ static int uart_do_autoconfig(struct uart_state *state) ret = uart_startup(state, 1); } - up(&state->sem); + mutex_unlock(&state->mutex); return ret; } @@ -1074,7 +1074,7 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, if (ret != -ENOIOCTLCMD) goto out; - down(&state->sem); + mutex_lock(&state->mutex); if (tty_hung_up_p(filp)) { ret = -EIO; @@ -1098,7 +1098,7 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, } } out_up: - up(&state->sem); + mutex_unlock(&state->mutex); out: return ret; } @@ -1186,7 +1186,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) DPRINTK("uart_close(%d) called\n", port->line); - down(&state->sem); + mutex_lock(&state->mutex); if (tty_hung_up_p(filp)) goto done; @@ -1260,7 +1260,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) wake_up_interruptible(&state->info->open_wait); done: - up(&state->sem); + mutex_unlock(&state->mutex); } static void uart_wait_until_sent(struct tty_struct *tty, int timeout) @@ -1334,7 +1334,7 @@ static void uart_hangup(struct tty_struct *tty) BUG_ON(!kernel_locked()); DPRINTK("uart_hangup(%d)\n", state->port->line); - down(&state->sem); + mutex_lock(&state->mutex); if (state->info && state->info->flags & UIF_NORMAL_ACTIVE) { uart_flush_buffer(tty); uart_shutdown(state); @@ -1344,7 +1344,7 @@ static void uart_hangup(struct tty_struct *tty) wake_up_interruptible(&state->info->open_wait); wake_up_interruptible(&state->info->delta_msr_wait); } - up(&state->sem); + mutex_unlock(&state->mutex); } /* @@ -1447,9 +1447,9 @@ uart_block_til_ready(struct file *filp, struct uart_state *state) if (mctrl & TIOCM_CAR) break; - up(&state->sem); + mutex_unlock(&state->mutex); schedule(); - down(&state->sem); + mutex_lock(&state->mutex); if (signal_pending(current)) break; @@ -1475,7 +1475,7 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line) mutex_lock(&port_mutex); state = drv->state + line; - if (down_interruptible(&state->sem)) { + if (mutex_lock_interruptible(&state->mutex)) { state = ERR_PTR(-ERESTARTSYS); goto out; } @@ -1483,7 +1483,7 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line) state->count++; if (!state->port) { state->count--; - up(&state->sem); + mutex_unlock(&state->mutex); state = ERR_PTR(-ENXIO); goto out; } @@ -1504,7 +1504,7 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line) (unsigned long)state); } else { state->count--; - up(&state->sem); + mutex_unlock(&state->mutex); state = ERR_PTR(-ENOMEM); } } @@ -1571,7 +1571,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp) if (tty_hung_up_p(filp)) { retval = -EAGAIN; state->count--; - up(&state->sem); + mutex_unlock(&state->mutex); goto fail; } @@ -1591,7 +1591,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp) */ if (retval == 0) retval = uart_block_til_ready(filp, state); - up(&state->sem); + mutex_unlock(&state->mutex); /* * If this is the first open to succeed, adjust things to suit. @@ -1867,7 +1867,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port) { struct uart_state *state = drv->state + port->line; - down(&state->sem); + mutex_lock(&state->mutex); if (state->info && state->info->flags & UIF_INITIALIZED) { struct uart_ops *ops = port->ops; @@ -1896,7 +1896,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port) uart_change_pm(state, 3); - up(&state->sem); + mutex_unlock(&state->mutex); return 0; } @@ -1905,7 +1905,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) { struct uart_state *state = drv->state + port->line; - down(&state->sem); + mutex_lock(&state->mutex); uart_change_pm(state, 0); @@ -1954,7 +1954,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) } } - up(&state->sem); + mutex_unlock(&state->mutex); return 0; } @@ -2049,7 +2049,7 @@ uart_unconfigure_port(struct uart_driver *drv, struct uart_state *state) if (info && info->tty) tty_vhangup(info->tty); - down(&state->sem); + mutex_lock(&state->mutex); state->info = NULL; @@ -2072,7 +2072,7 @@ uart_unconfigure_port(struct uart_driver *drv, struct uart_state *state) kfree(info); } - up(&state->sem); + mutex_unlock(&state->mutex); } static struct tty_operations uart_ops = { @@ -2161,7 +2161,7 @@ int uart_register_driver(struct uart_driver *drv) state->close_delay = 500; /* .5 seconds */ state->closing_wait = 30000; /* 30 seconds */ - init_MUTEX(&state->sem); + mutex_init(&state->mutex); } retval = tty_register_driver(normal); diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index a8187c3c8a7..ec351005bf9 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -136,6 +136,7 @@ #include #include #include +#include struct uart_port; struct uart_info; @@ -284,7 +285,7 @@ struct uart_state { struct uart_info *info; struct uart_port *port; - struct semaphore sem; + struct mutex mutex; }; #define UART_XMIT_SIZE PAGE_SIZE -- GitLab From 51828abc17a4ae0f7fb3879e00a30da7bdc7ca20 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 13 Jan 2006 21:44:18 +0000 Subject: [PATCH 129/465] [MMC] mmc_blk_probe() warning fix drivers/mmc/mmc_block.c: In function `mmc_blk_probe': drivers/mmc/mmc_block.c:467: warning: long unsigned int format, different type arg (arg 5) We don't know what size sector_t is - cast it. Signed-off-by: Andrew Morton Signed-off-by: Russell King --- drivers/mmc/mmc_block.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c index 9b7c37e0e57..5b014c370e8 100644 --- a/drivers/mmc/mmc_block.c +++ b/drivers/mmc/mmc_block.c @@ -462,9 +462,10 @@ static int mmc_blk_probe(struct mmc_card *card) if (err) goto out; - printk(KERN_INFO "%s: %s %s %luKiB %s\n", + printk(KERN_INFO "%s: %s %s %lluKiB %s\n", md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), - get_capacity(md->disk) >> 1, md->read_only ? "(ro)" : ""); + (unsigned long long)(get_capacity(md->disk) >> 1), + md->read_only ? "(ro)" : ""); mmc_set_drvdata(card, md); add_disk(md->disk); -- GitLab From d600b97cf6ef8c24c9b87a4b7ce390c0d13684e8 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 13 Jan 2006 21:57:22 +0000 Subject: [PATCH 130/465] [SERIAL] fix SERIAL_M32R_PLDSIO dependencies This patch fixes a typo in the dependencies reported by Jean-Luc Leger . Signed-off-by: Adrian Bunk Signed-off-by: Russell King --- drivers/serial/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 843717275d4..6627ddae650 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -848,7 +848,7 @@ config SERIAL_M32R_SIO_CONSOLE config SERIAL_M32R_PLDSIO bool "M32R SIO I/F on a PLD" - depends on SERIAL_M32R_SIO=y && (PLAT_OPSPUT || PALT_USRV || PLAT_M32700UT) + depends on SERIAL_M32R_SIO=y && (PLAT_OPSPUT || PLAT_USRV || PLAT_M32700UT) default n help Say Y here if you want to use the M32R serial controller -- GitLab From 8a4b7b6f187f2967bff222e8c3758ab47efdb14f Mon Sep 17 00:00:00 2001 From: Francois Wellenrieter Date: Fri, 13 Jan 2006 14:01:01 -0800 Subject: [PATCH 131/465] [IA64] Fix conversion of pal_min_state physical address On return from INIT handler we must convert the address of the minstate area from a kernel virtual uncached address (0xC...) to physical uncached (0x8...). A typo (or thinko?) in the code converted to physical cached. Signed-off-by: Tony Luck --- arch/ia64/kernel/mca_asm.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S index db32fc1d393..403a80a58c1 100644 --- a/arch/ia64/kernel/mca_asm.S +++ b/arch/ia64/kernel/mca_asm.S @@ -847,7 +847,7 @@ ia64_state_restore: ;; mov cr.iim=temp3 mov cr.iha=temp4 - dep r22=0,r22,62,2 // pal_min_state, physical, uncached + dep r22=0,r22,62,1 // pal_min_state, physical, uncached mov IA64_KR(CURRENT)=r21 ld8 r8=[temp1] // os_status ld8 r10=[temp2] // context -- GitLab From 7493a314cb83797ce612a577475aacaedc553fed Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 13 Jan 2006 22:06:43 +0000 Subject: [PATCH 132/465] [SERIAL] serial8250: convert to the new platform device interface Do not use platform_device_register_simple() as it is going away. Also set up driver's owner to create link driver->module in sysfs. Signed-off-by: Dmitry Torokhov Signed-off-by: Russell King --- drivers/serial/8250.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index fb610c3634a..d9ce8c54941 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -2454,6 +2454,7 @@ static struct platform_driver serial8250_isa_driver = { .resume = serial8250_resume, .driver = { .name = "serial8250", + .owner = THIS_MODULE, }, }; @@ -2594,21 +2595,30 @@ static int __init serial8250_init(void) if (ret) goto out; - serial8250_isa_devs = platform_device_register_simple("serial8250", - PLAT8250_DEV_LEGACY, NULL, 0); - if (IS_ERR(serial8250_isa_devs)) { - ret = PTR_ERR(serial8250_isa_devs); - goto unreg; + ret = platform_driver_register(&serial8250_isa_driver); + if (ret) + goto unreg_uart_drv; + + serial8250_isa_devs = platform_device_alloc("serial8250", + PLAT8250_DEV_LEGACY); + if (!serial8250_isa_devs) { + ret = -ENOMEM; + goto unreg_plat_drv; } + ret = platform_device_add(serial8250_isa_devs); + if (ret) + goto put_dev; + serial8250_register_ports(&serial8250_reg, &serial8250_isa_devs->dev); - ret = platform_driver_register(&serial8250_isa_driver); - if (ret == 0) - goto out; + goto out; - platform_device_unregister(serial8250_isa_devs); - unreg: + put_dev: + platform_device_put(serial8250_isa_devs); + unreg_plat_drv: + platform_driver_unregister(&serial8250_isa_driver); + unreg_uart_drv: uart_unregister_driver(&serial8250_reg); out: return ret; -- GitLab From 17e8ce0e9417eee1f57f9b3d4aad168425e043c3 Mon Sep 17 00:00:00 2001 From: Russ Anderson Date: Fri, 16 Dec 2005 17:19:01 -0600 Subject: [PATCH 133/465] [IA64-SGI] Altix BTE error handling fixes Altix (shub2) pushes the BTE clean-up into SAL. This patch correctly interfaces with the now implemented SAL call. It also fixes a bug when delaying clean-up to allow busy BTEs to complete (or error out). Signed-off-by: Russ Anderson Signed-off-by: Tony Luck --- arch/ia64/sn/kernel/bte_error.c | 58 +++++++++++++++++++++++++++------ arch/ia64/sn/kernel/huberror.c | 9 ++--- include/asm-ia64/sn/sn_sal.h | 2 +- 3 files changed, 54 insertions(+), 15 deletions(-) diff --git a/arch/ia64/sn/kernel/bte_error.c b/arch/ia64/sn/kernel/bte_error.c index fcbc748ae43..f1ec1370b3e 100644 --- a/arch/ia64/sn/kernel/bte_error.c +++ b/arch/ia64/sn/kernel/bte_error.c @@ -33,7 +33,7 @@ void bte_error_handler(unsigned long); * Wait until all BTE related CRBs are completed * and then reset the interfaces. */ -void shub1_bte_error_handler(unsigned long _nodepda) +int shub1_bte_error_handler(unsigned long _nodepda) { struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda; struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer; @@ -53,7 +53,7 @@ void shub1_bte_error_handler(unsigned long _nodepda) (err_nodepda->bte_if[1].bh_error == BTE_SUCCESS)) { BTE_PRINTK(("eh:%p:%d Nothing to do.\n", err_nodepda, smp_processor_id())); - return; + return 1; } /* Determine information about our hub */ @@ -81,7 +81,7 @@ void shub1_bte_error_handler(unsigned long _nodepda) mod_timer(recovery_timer, HZ * 5); BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda, smp_processor_id())); - return; + return 1; } if (icmr.ii_icmr_fld_s.i_crb_vld != 0) { @@ -99,7 +99,7 @@ void shub1_bte_error_handler(unsigned long _nodepda) BTE_PRINTK(("eh:%p:%d Valid %d, Giving up\n", err_nodepda, smp_processor_id(), i)); - return; + return 1; } } } @@ -124,6 +124,42 @@ void shub1_bte_error_handler(unsigned long _nodepda) REMOTE_HUB_S(nasid, IIO_IBCR, ibcr.ii_ibcr_regval); del_timer(recovery_timer); + return 0; +} + +/* + * Wait until all BTE related CRBs are completed + * and then reset the interfaces. + */ +int shub2_bte_error_handler(unsigned long _nodepda) +{ + struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda; + struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer; + struct bteinfo_s *bte; + nasid_t nasid; + u64 status; + int i; + + nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode); + + /* + * Verify that all the BTEs are complete + */ + for (i = 0; i < BTES_PER_NODE; i++) { + bte = &err_nodepda->bte_if[i]; + status = BTE_LNSTAT_LOAD(bte); + if ((status & IBLS_ERROR) || !(status & IBLS_BUSY)) + continue; + mod_timer(recovery_timer, HZ * 5); + BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda, + smp_processor_id())); + return 1; + } + if (ia64_sn_bte_recovery(nasid)) + panic("bte_error_handler(): Fatal BTE Error"); + + del_timer(recovery_timer); + return 0; } /* @@ -135,7 +171,6 @@ void bte_error_handler(unsigned long _nodepda) struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda; spinlock_t *recovery_lock = &err_nodepda->bte_recovery_lock; int i; - nasid_t nasid; unsigned long irq_flags; volatile u64 *notify; bte_result_t bh_error; @@ -160,12 +195,15 @@ void bte_error_handler(unsigned long _nodepda) } if (is_shub1()) { - shub1_bte_error_handler(_nodepda); + if (shub1_bte_error_handler(_nodepda)) { + spin_unlock_irqrestore(recovery_lock, irq_flags); + return; + } } else { - nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode); - - if (ia64_sn_bte_recovery(nasid)) - panic("bte_error_handler(): Fatal BTE Error"); + if (shub2_bte_error_handler(_nodepda)) { + spin_unlock_irqrestore(recovery_lock, irq_flags); + return; + } } for (i = 0; i < BTES_PER_NODE; i++) { diff --git a/arch/ia64/sn/kernel/huberror.c b/arch/ia64/sn/kernel/huberror.c index 5c5eb01c50f..56ab6bae00e 100644 --- a/arch/ia64/sn/kernel/huberror.c +++ b/arch/ia64/sn/kernel/huberror.c @@ -32,13 +32,14 @@ static irqreturn_t hub_eint_handler(int irq, void *arg, struct pt_regs *ep) ret_stuff.v0 = 0; hubdev_info = (struct hubdev_info *)arg; nasid = hubdev_info->hdi_nasid; - SAL_CALL_NOLOCK(ret_stuff, SN_SAL_HUB_ERROR_INTERRUPT, + + if (is_shub1()) { + SAL_CALL_NOLOCK(ret_stuff, SN_SAL_HUB_ERROR_INTERRUPT, (u64) nasid, 0, 0, 0, 0, 0, 0); - if ((int)ret_stuff.v0) - panic("hubii_eint_handler(): Fatal TIO Error"); + if ((int)ret_stuff.v0) + panic("hubii_eint_handler(): Fatal TIO Error"); - if (is_shub1()) { if (!(nasid & 1)) /* Not a TIO, handle CRB errors */ (void)hubiio_crb_error_handler(hubdev_info); } else diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h index 2a8b0d92a5d..4363ed3598a 100644 --- a/include/asm-ia64/sn/sn_sal.h +++ b/include/asm-ia64/sn/sn_sal.h @@ -1100,7 +1100,7 @@ ia64_sn_bte_recovery(nasid_t nasid) struct ia64_sal_retval rv; rv.status = 0; - SAL_CALL_NOLOCK(rv, SN_SAL_BTE_RECOVER, 0, 0, 0, 0, 0, 0, 0); + SAL_CALL_NOLOCK(rv, SN_SAL_BTE_RECOVER, (u64)nasid, 0, 0, 0, 0, 0, 0); if (rv.status == SALRET_NOT_IMPLEMENTED) return 0; return (int) rv.status; -- GitLab From cfbb1426bd76c4ba6ec4491c8df2a5dd3d984750 Mon Sep 17 00:00:00 2001 From: Jack Steiner Date: Thu, 22 Dec 2005 13:45:41 -0600 Subject: [PATCH 134/465] [IA64] Hole in IA64 TLB flushing from system threads I originally thought this was an bug only in the SN code, but I think I also see a hole in the generic IA64 tlb code. (Separate patch was sent for the SN problem). It looks like there is a bug in the TLB flushing code. During context switch, kernel threads (kswapd, for example) inherit the mm of the task that was previously running on the cpu. Normally, this is ok because the previous context is still loaded into the RR registers. However, if the owner of the mm migrates to another cpu, changes it's context number, and references a page before kswapd issues a tlb_purge for that same page, the purge will be done with a stale context number (& RR registers). Signed-off-by: Tony Luck --- arch/ia64/mm/tlb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c index 41105d45442..6a4eec9113e 100644 --- a/arch/ia64/mm/tlb.c +++ b/arch/ia64/mm/tlb.c @@ -90,7 +90,7 @@ ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start, { static DEFINE_SPINLOCK(ptcg_lock); - if (mm != current->active_mm) { + if (mm != current->active_mm || !current->mm) { flush_tlb_all(); return; } -- GitLab From 6d6e420005f3753392b608a614eee8475bdc16f7 Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Fri, 23 Dec 2005 13:33:25 -0500 Subject: [PATCH 135/465] [IA64-SGI] Fix sn_flush_device_kernel & spinlock initialization This patch separates the sn_flush_device_list struct into kernel and common (both kernel and PROM accessible) structures. As it was, if the size of a spinlock_t changed (due to additional CONFIG options, etc.) the sal call which populated the sn_flush_device_list structs would erroneously write data (and cause memory corruption and/or a panic). This patch does the following: 1. Removes sn_flush_device_list and adds sn_flush_device_common and sn_flush_device_kernel. 2. Adds a new SAL call to populate a sn_flush_device_common struct per device, not per widget as previously done. 3. Correctly initializes each device's sn_flush_device_kernel spinlock_t struct (before it was only doing each widget's first device). Signed-off-by: Prarit Bhargava Signed-off-by: Tony Luck --- arch/ia64/sn/include/xtalk/hubdev.h | 16 +++-- arch/ia64/sn/kernel/io_init.c | 94 ++++++++++++++----------- arch/ia64/sn/pci/pcibr/pcibr_dma.c | 34 ++++----- arch/ia64/sn/pci/pcibr/pcibr_provider.c | 20 +++--- include/asm-ia64/sn/sn_sal.h | 3 +- 5 files changed, 95 insertions(+), 72 deletions(-) diff --git a/arch/ia64/sn/include/xtalk/hubdev.h b/arch/ia64/sn/include/xtalk/hubdev.h index 71c2b271b4c..4d417c30120 100644 --- a/arch/ia64/sn/include/xtalk/hubdev.h +++ b/arch/ia64/sn/include/xtalk/hubdev.h @@ -26,11 +26,14 @@ #define IIO_NUM_ITTES 7 #define HUB_NUM_BIG_WINDOW (IIO_NUM_ITTES - 1) -struct sn_flush_device_list { +/* This struct is shared between the PROM and the kernel. + * Changes to this struct will require corresponding changes to the kernel. + */ +struct sn_flush_device_common { int sfdl_bus; int sfdl_slot; int sfdl_pin; - struct bar_list { + struct common_bar_list { unsigned long start; unsigned long end; } sfdl_bar_list[6]; @@ -40,14 +43,19 @@ struct sn_flush_device_list { uint32_t sfdl_persistent_busnum; uint32_t sfdl_persistent_segment; struct pcibus_info *sfdl_pcibus_info; +}; + +/* This struct is kernel only and is not used by the PROM */ +struct sn_flush_device_kernel { spinlock_t sfdl_flush_lock; + struct sn_flush_device_common *common; }; /* - * **widget_p - Used as an array[wid_num][device] of sn_flush_device_list. + * **widget_p - Used as an array[wid_num][device] of sn_flush_device_kernel. */ struct sn_flush_nasid_entry { - struct sn_flush_device_list **widget_p; /* Used as a array of wid_num */ + struct sn_flush_device_kernel **widget_p; // Used as an array of wid_num uint64_t iio_itte[8]; }; diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index 318087e35b6..258d9d7aff9 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c @@ -76,11 +76,12 @@ static struct sn_pcibus_provider sn_pci_default_provider = { }; /* - * Retrieve the DMA Flush List given nasid. This list is needed - * to implement the WAR - Flush DMA data on PIO Reads. + * Retrieve the DMA Flush List given nasid, widget, and device. + * This list is needed to implement the WAR - Flush DMA data on PIO Reads. */ -static inline uint64_t -sal_get_widget_dmaflush_list(u64 nasid, u64 widget_num, u64 address) +static inline u64 +sal_get_device_dmaflush_list(u64 nasid, u64 widget_num, u64 device_num, + u64 address) { struct ia64_sal_retval ret_stuff; @@ -88,17 +89,17 @@ sal_get_widget_dmaflush_list(u64 nasid, u64 widget_num, u64 address) ret_stuff.v0 = 0; SAL_CALL_NOLOCK(ret_stuff, - (u64) SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST, - (u64) nasid, (u64) widget_num, (u64) address, 0, 0, 0, - 0); - return ret_stuff.v0; + (u64) SN_SAL_IOIF_GET_DEVICE_DMAFLUSH_LIST, + (u64) nasid, (u64) widget_num, + (u64) device_num, (u64) address, 0, 0, 0); + return ret_stuff.status; } /* * Retrieve the hub device info structure for the given nasid. */ -static inline uint64_t sal_get_hubdev_info(u64 handle, u64 address) +static inline u64 sal_get_hubdev_info(u64 handle, u64 address) { struct ia64_sal_retval ret_stuff; @@ -114,7 +115,7 @@ static inline uint64_t sal_get_hubdev_info(u64 handle, u64 address) /* * Retrieve the pci bus information given the bus number. */ -static inline uint64_t sal_get_pcibus_info(u64 segment, u64 busnum, u64 address) +static inline u64 sal_get_pcibus_info(u64 segment, u64 busnum, u64 address) { struct ia64_sal_retval ret_stuff; @@ -130,7 +131,7 @@ static inline uint64_t sal_get_pcibus_info(u64 segment, u64 busnum, u64 address) /* * Retrieve the pci device information given the bus and device|function number. */ -static inline uint64_t +static inline u64 sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev, u64 sn_irq_info) { @@ -170,12 +171,12 @@ sn_pcidev_info_get(struct pci_dev *dev) */ static void sn_fixup_ionodes(void) { - - struct sn_flush_device_list *sn_flush_device_list; + struct sn_flush_device_kernel *sn_flush_device_kernel; + struct sn_flush_device_kernel *dev_entry; struct hubdev_info *hubdev; - uint64_t status; - uint64_t nasid; - int i, widget; + u64 status; + u64 nasid; + int i, widget, device; /* * Get SGI Specific HUB chipset information. @@ -186,7 +187,7 @@ static void sn_fixup_ionodes(void) nasid = cnodeid_to_nasid(i); hubdev->max_segment_number = 0xffffffff; hubdev->max_pcibus_number = 0xff; - status = sal_get_hubdev_info(nasid, (uint64_t) __pa(hubdev)); + status = sal_get_hubdev_info(nasid, (u64) __pa(hubdev)); if (status) continue; @@ -213,38 +214,49 @@ static void sn_fixup_ionodes(void) hubdev->hdi_flush_nasid_list.widget_p = kmalloc((HUB_WIDGET_ID_MAX + 1) * - sizeof(struct sn_flush_device_list *), GFP_KERNEL); - + sizeof(struct sn_flush_device_kernel *), + GFP_KERNEL); memset(hubdev->hdi_flush_nasid_list.widget_p, 0x0, (HUB_WIDGET_ID_MAX + 1) * - sizeof(struct sn_flush_device_list *)); + sizeof(struct sn_flush_device_kernel *)); for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++) { - sn_flush_device_list = kmalloc(DEV_PER_WIDGET * - sizeof(struct - sn_flush_device_list), - GFP_KERNEL); - memset(sn_flush_device_list, 0x0, + sn_flush_device_kernel = kmalloc(DEV_PER_WIDGET * + sizeof(struct + sn_flush_device_kernel), + GFP_KERNEL); + if (!sn_flush_device_kernel) + BUG(); + memset(sn_flush_device_kernel, 0x0, DEV_PER_WIDGET * - sizeof(struct sn_flush_device_list)); - - status = - sal_get_widget_dmaflush_list(nasid, widget, - (uint64_t) - __pa - (sn_flush_device_list)); - if (status) { - kfree(sn_flush_device_list); - continue; + sizeof(struct sn_flush_device_kernel)); + + dev_entry = sn_flush_device_kernel; + for (device = 0; device < DEV_PER_WIDGET; + device++,dev_entry++) { + dev_entry->common = kmalloc(sizeof(struct + sn_flush_device_common), + GFP_KERNEL); + if (!dev_entry->common) + BUG(); + memset(dev_entry->common, 0x0, sizeof(struct + sn_flush_device_common)); + + status = sal_get_device_dmaflush_list(nasid, + widget, + device, + (u64)(dev_entry->common)); + if (status) + BUG(); + + spin_lock_init(&dev_entry->sfdl_flush_lock); } - spin_lock_init(&sn_flush_device_list->sfdl_flush_lock); - hubdev->hdi_flush_nasid_list.widget_p[widget] = - sn_flush_device_list; - } - + if (sn_flush_device_kernel) + hubdev->hdi_flush_nasid_list.widget_p[widget] = + sn_flush_device_kernel; + } } - } /* diff --git a/arch/ia64/sn/pci/pcibr/pcibr_dma.c b/arch/ia64/sn/pci/pcibr/pcibr_dma.c index 34093476e96..e68332d9317 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_dma.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_dma.c @@ -218,7 +218,9 @@ void sn_dma_flush(uint64_t addr) uint64_t flags; uint64_t itte; struct hubdev_info *hubinfo; - volatile struct sn_flush_device_list *p; + volatile struct sn_flush_device_kernel *p; + volatile struct sn_flush_device_common *common; + struct sn_flush_nasid_entry *flush_nasid_list; if (!sn_ioif_inited) @@ -268,17 +270,17 @@ void sn_dma_flush(uint64_t addr) p = &flush_nasid_list->widget_p[wid_num][0]; /* find a matching BAR */ - for (i = 0; i < DEV_PER_WIDGET; i++) { + for (i = 0; i < DEV_PER_WIDGET; i++,p++) { + common = p->common; for (j = 0; j < PCI_ROM_RESOURCE; j++) { - if (p->sfdl_bar_list[j].start == 0) + if (common->sfdl_bar_list[j].start == 0) break; - if (addr >= p->sfdl_bar_list[j].start - && addr <= p->sfdl_bar_list[j].end) + if (addr >= common->sfdl_bar_list[j].start + && addr <= common->sfdl_bar_list[j].end) break; } - if (j < PCI_ROM_RESOURCE && p->sfdl_bar_list[j].start != 0) + if (j < PCI_ROM_RESOURCE && common->sfdl_bar_list[j].start != 0) break; - p++; } /* if no matching BAR, return without doing anything. */ @@ -304,24 +306,24 @@ void sn_dma_flush(uint64_t addr) if ((1 << XWIDGET_PART_REV_NUM_REV(revnum)) & PV907516) { return; } else { - pcireg_wrb_flush_get(p->sfdl_pcibus_info, - (p->sfdl_slot - 1)); + pcireg_wrb_flush_get(common->sfdl_pcibus_info, + (common->sfdl_slot - 1)); } } else { - spin_lock_irqsave(&((struct sn_flush_device_list *)p)-> - sfdl_flush_lock, flags); - - *p->sfdl_flush_addr = 0; + spin_lock_irqsave((spinlock_t *)&p->sfdl_flush_lock, + flags); + *common->sfdl_flush_addr = 0; /* force an interrupt. */ - *(volatile uint32_t *)(p->sfdl_force_int_addr) = 1; + *(volatile uint32_t *)(common->sfdl_force_int_addr) = 1; /* wait for the interrupt to come back. */ - while (*(p->sfdl_flush_addr) != 0x10f) + while (*(common->sfdl_flush_addr) != 0x10f) cpu_relax(); /* okay, everything is synched up. */ - spin_unlock_irqrestore((spinlock_t *)&p->sfdl_flush_lock, flags); + spin_unlock_irqrestore((spinlock_t *)&p->sfdl_flush_lock, + flags); } return; } diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c index 1f500c81002..e328e948175 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c @@ -92,7 +92,8 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont cnodeid_t near_cnode; struct hubdev_info *hubdev_info; struct pcibus_info *soft; - struct sn_flush_device_list *sn_flush_device_list; + struct sn_flush_device_kernel *sn_flush_device_kernel; + struct sn_flush_device_common *common; if (! IS_PCI_BRIDGE_ASIC(prom_bussoft->bs_asic_type)) { return NULL; @@ -137,20 +138,19 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont hubdev_info = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo); if (hubdev_info->hdi_flush_nasid_list.widget_p) { - sn_flush_device_list = hubdev_info->hdi_flush_nasid_list. + sn_flush_device_kernel = hubdev_info->hdi_flush_nasid_list. widget_p[(int)soft->pbi_buscommon.bs_xid]; - if (sn_flush_device_list) { + if (sn_flush_device_kernel) { for (j = 0; j < DEV_PER_WIDGET; - j++, sn_flush_device_list++) { - if (sn_flush_device_list->sfdl_slot == -1) + j++, sn_flush_device_kernel++) { + common = sn_flush_device_kernel->common; + if (common->sfdl_slot == -1) continue; - if ((sn_flush_device_list-> - sfdl_persistent_segment == + if ((common->sfdl_persistent_segment == soft->pbi_buscommon.bs_persist_segment) && - (sn_flush_device_list-> - sfdl_persistent_busnum == + (common->sfdl_persistent_busnum == soft->pbi_buscommon.bs_persist_busnum)) - sn_flush_device_list->sfdl_pcibus_info = + common->sfdl_pcibus_info = soft; } } diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h index 4363ed3598a..8b9e10e7cdb 100644 --- a/include/asm-ia64/sn/sn_sal.h +++ b/include/asm-ia64/sn/sn_sal.h @@ -75,7 +75,8 @@ #define SN_SAL_IOIF_GET_HUBDEV_INFO 0x02000055 #define SN_SAL_IOIF_GET_PCIBUS_INFO 0x02000056 #define SN_SAL_IOIF_GET_PCIDEV_INFO 0x02000057 -#define SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST 0x02000058 +#define SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST 0x02000058 // deprecated +#define SN_SAL_IOIF_GET_DEVICE_DMAFLUSH_LIST 0x0200005a #define SN_SAL_HUB_ERROR_INTERRUPT 0x02000060 #define SN_SAL_BTE_RECOVER 0x02000061 -- GitLab From 15029285dc977a392e74eacb7625984b71d4f605 Mon Sep 17 00:00:00 2001 From: Jason Uhlenkott Date: Fri, 30 Dec 2005 02:27:01 -0800 Subject: [PATCH 136/465] [IA64] Handle debug traps in fsys mode We need to handle debug traps in fsys mode non-fatally. They can happen now that we have fsyscalls which contain probe instructions. Signed-off-by: Jason Uhlenkott Signed-off-by: Tony Luck --- arch/ia64/kernel/traps.c | 26 +++++++++++++++++++------- include/asm-ia64/thread_info.h | 4 +++- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c index d3e0ecb56d6..55391901b01 100644 --- a/arch/ia64/kernel/traps.c +++ b/arch/ia64/kernel/traps.c @@ -530,12 +530,15 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, if (fsys_mode(current, ®s)) { extern char __kernel_syscall_via_break[]; /* - * Got a trap in fsys-mode: Taken Branch Trap and Single Step trap - * need special handling; Debug trap is not supposed to happen. + * Got a trap in fsys-mode: Taken Branch Trap + * and Single Step trap need special handling; + * Debug trap is ignored (we disable it here + * and re-enable it in the lower-privilege trap). */ if (unlikely(vector == 29)) { - die("Got debug trap in fsys-mode---not supposed to happen!", - ®s, 0); + set_thread_flag(TIF_DB_DISABLED); + ia64_psr(®s)->db = 0; + ia64_psr(®s)->lp = 1; return; } /* re-do the system call via break 0x100000: */ @@ -589,10 +592,19 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, case 34: if (isr & 0x2) { /* Lower-Privilege Transfer Trap */ + + /* If we disabled debug traps during an fsyscall, + * re-enable them here. + */ + if (test_thread_flag(TIF_DB_DISABLED)) { + clear_thread_flag(TIF_DB_DISABLED); + ia64_psr(®s)->db = 1; + } + /* - * Just clear PSR.lp and then return immediately: all the - * interesting work (e.g., signal delivery is done in the kernel - * exit path). + * Just clear PSR.lp and then return immediately: + * all the interesting work (e.g., signal delivery) + * is done in the kernel exit path. */ ia64_psr(®s)->lp = 0; return; diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h index 653bb7f9a75..1d6518fe1f0 100644 --- a/include/asm-ia64/thread_info.h +++ b/include/asm-ia64/thread_info.h @@ -93,6 +93,7 @@ struct thread_info { #define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ #define TIF_MEMDIE 17 #define TIF_MCA_INIT 18 /* this task is processing MCA or INIT */ +#define TIF_DB_DISABLED 19 /* debug trap disabled for fsyscall */ #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) @@ -100,9 +101,10 @@ struct thread_info { #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) -#define _TIF_SIGDELAYED (1 << TIF_SIGDELAYED) +#define _TIF_SIGDELAYED (1 << TIF_SIGDELAYED) #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) #define _TIF_MCA_INIT (1 << TIF_MCA_INIT) +#define _TIF_DB_DISABLED (1 << TIF_DB_DISABLED) /* "work to do on user-return" bits */ #define TIF_ALLWORK_MASK (_TIF_NOTIFY_RESUME|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SIGDELAYED) -- GitLab From e026cca0f2c09c4c28c902db6384fd8a412671d6 Mon Sep 17 00:00:00 2001 From: Keith Owens Date: Fri, 6 Jan 2006 10:36:06 +1100 Subject: [PATCH 137/465] [IA64] Add hotplug cpu to salinfo.c, replace semaphore with mutex Add hotplug cpu support to salinfo.c. The cpu_event field is a cpumask so use the cpu_* macros consistently, replacing the existing mixture of cpu_* and *_bit macros. Instead of counting the number of outstanding events in a semaphore and trying to track that count over user space context, interrupt context, non-maskable interrupt context and cpu hotplug, replace the semaphore with a test for "any bits set" combined with a mutex. Modify the locking to make the test for "work to do" an atomic operation. Signed-off-by: Keith Owens Signed-off-by: Tony Luck --- arch/ia64/kernel/salinfo.c | 170 ++++++++++++++++++++++++++----------- 1 file changed, 119 insertions(+), 51 deletions(-) diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c index a87a162a308..9d5a823479a 100644 --- a/arch/ia64/kernel/salinfo.c +++ b/arch/ia64/kernel/salinfo.c @@ -3,7 +3,7 @@ * * Creates entries in /proc/sal for various system features. * - * Copyright (c) 2003 Silicon Graphics, Inc. All rights reserved. + * Copyright (c) 2003, 2006 Silicon Graphics, Inc. All rights reserved. * Copyright (c) 2003 Hewlett-Packard Co * Bjorn Helgaas * @@ -27,9 +27,17 @@ * mca.c may not pass a buffer, a NULL buffer just indicates that a new * record is available in SAL. * Replace some NR_CPUS by cpus_online, for hotplug cpu. + * + * Jan 5 2006 kaos@sgi.com + * Handle hotplug cpus coming online. + * Handle hotplug cpus going offline while they still have outstanding records. + * Use the cpu_* macros consistently. + * Replace the counting semaphore with a mutex and a test if the cpumask is non-empty. + * Modify the locking to make the test for "work to do" an atomic operation. */ #include +#include #include #include #include @@ -132,8 +140,8 @@ enum salinfo_state { }; struct salinfo_data { - volatile cpumask_t cpu_event; /* which cpus have outstanding events */ - struct semaphore sem; /* count of cpus with outstanding events (bits set in cpu_event) */ + cpumask_t cpu_event; /* which cpus have outstanding events */ + struct semaphore mutex; u8 *log_buffer; u64 log_size; u8 *oemdata; /* decoded oem data */ @@ -174,6 +182,21 @@ struct salinfo_platform_oemdata_parms { int ret; }; +/* Kick the mutex that tells user space that there is work to do. Instead of + * trying to track the state of the mutex across multiple cpus, in user + * context, interrupt context, non-maskable interrupt context and hotplug cpu, + * it is far easier just to grab the mutex if it is free then release it. + * + * This routine must be called with data_saved_lock held, to make the down/up + * operation atomic. + */ +static void +salinfo_work_to_do(struct salinfo_data *data) +{ + down_trylock(&data->mutex); + up(&data->mutex); +} + static void salinfo_platform_oemdata_cpu(void *context) { @@ -212,9 +235,9 @@ salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe) BUG_ON(type >= ARRAY_SIZE(salinfo_log_name)); + if (irqsafe) + spin_lock_irqsave(&data_saved_lock, flags); if (buffer) { - if (irqsafe) - spin_lock_irqsave(&data_saved_lock, flags); for (i = 0, data_saved = data->data_saved; i < saved_size; ++i, ++data_saved) { if (!data_saved->buffer) break; @@ -232,13 +255,11 @@ salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe) data_saved->size = size; data_saved->buffer = buffer; } - if (irqsafe) - spin_unlock_irqrestore(&data_saved_lock, flags); } - - if (!test_and_set_bit(smp_processor_id(), &data->cpu_event)) { - if (irqsafe) - up(&data->sem); + cpu_set(smp_processor_id(), data->cpu_event); + if (irqsafe) { + salinfo_work_to_do(data); + spin_unlock_irqrestore(&data_saved_lock, flags); } } @@ -249,20 +270,17 @@ static struct timer_list salinfo_timer; static void salinfo_timeout_check(struct salinfo_data *data) { - int i; + unsigned long flags; if (!data->open) return; - for_each_online_cpu(i) { - if (test_bit(i, &data->cpu_event)) { - /* double up() is not a problem, user space will see no - * records for the additional "events". - */ - up(&data->sem); - } + if (!cpus_empty(data->cpu_event)) { + spin_lock_irqsave(&data_saved_lock, flags); + salinfo_work_to_do(data); + spin_unlock_irqrestore(&data_saved_lock, flags); } } -static void +static void salinfo_timeout (unsigned long arg) { salinfo_timeout_check(salinfo_data + SAL_INFO_TYPE_MCA); @@ -290,16 +308,20 @@ salinfo_event_read(struct file *file, char __user *buffer, size_t count, loff_t int i, n, cpu = -1; retry: - if (down_trylock(&data->sem)) { + if (cpus_empty(data->cpu_event) && down_trylock(&data->mutex)) { if (file->f_flags & O_NONBLOCK) return -EAGAIN; - if (down_interruptible(&data->sem)) + if (down_interruptible(&data->mutex)) return -EINTR; } n = data->cpu_check; for (i = 0; i < NR_CPUS; i++) { - if (test_bit(n, &data->cpu_event) && cpu_online(n)) { + if (cpu_isset(n, data->cpu_event)) { + if (!cpu_online(n)) { + cpu_clear(n, data->cpu_event); + continue; + } cpu = n; break; } @@ -310,9 +332,6 @@ retry: if (cpu == -1) goto retry; - /* events are sticky until the user says "clear" */ - up(&data->sem); - /* for next read, start checking at next CPU */ data->cpu_check = cpu; if (++data->cpu_check == NR_CPUS) @@ -381,10 +400,8 @@ salinfo_log_release(struct inode *inode, struct file *file) static void call_on_cpu(int cpu, void (*fn)(void *), void *arg) { - cpumask_t save_cpus_allowed, new_cpus_allowed; - memcpy(&save_cpus_allowed, ¤t->cpus_allowed, sizeof(save_cpus_allowed)); - memset(&new_cpus_allowed, 0, sizeof(new_cpus_allowed)); - set_bit(cpu, &new_cpus_allowed); + cpumask_t save_cpus_allowed = current->cpus_allowed; + cpumask_t new_cpus_allowed = cpumask_of_cpu(cpu); set_cpus_allowed(current, new_cpus_allowed); (*fn)(arg); set_cpus_allowed(current, save_cpus_allowed); @@ -433,10 +450,10 @@ retry: if (!data->saved_num) call_on_cpu(cpu, salinfo_log_read_cpu, data); if (!data->log_size) { - data->state = STATE_NO_DATA; - clear_bit(cpu, &data->cpu_event); + data->state = STATE_NO_DATA; + cpu_clear(cpu, data->cpu_event); } else { - data->state = STATE_LOG_RECORD; + data->state = STATE_LOG_RECORD; } } @@ -473,27 +490,31 @@ static int salinfo_log_clear(struct salinfo_data *data, int cpu) { sal_log_record_header_t *rh; + unsigned long flags; + spin_lock_irqsave(&data_saved_lock, flags); data->state = STATE_NO_DATA; - if (!test_bit(cpu, &data->cpu_event)) + if (!cpu_isset(cpu, data->cpu_event)) { + spin_unlock_irqrestore(&data_saved_lock, flags); return 0; - down(&data->sem); - clear_bit(cpu, &data->cpu_event); + } + cpu_clear(cpu, data->cpu_event); if (data->saved_num) { - unsigned long flags; - spin_lock_irqsave(&data_saved_lock, flags); - shift1_data_saved(data, data->saved_num - 1 ); + shift1_data_saved(data, data->saved_num - 1); data->saved_num = 0; - spin_unlock_irqrestore(&data_saved_lock, flags); } + spin_unlock_irqrestore(&data_saved_lock, flags); rh = (sal_log_record_header_t *)(data->log_buffer); /* Corrected errors have already been cleared from SAL */ if (rh->severity != sal_log_severity_corrected) call_on_cpu(cpu, salinfo_log_clear_cpu, data); /* clearing a record may make a new record visible */ salinfo_log_new_read(cpu, data); - if (data->state == STATE_LOG_RECORD && - !test_and_set_bit(cpu, &data->cpu_event)) - up(&data->sem); + if (data->state == STATE_LOG_RECORD) { + spin_lock_irqsave(&data_saved_lock, flags); + cpu_set(cpu, data->cpu_event); + salinfo_work_to_do(data); + spin_unlock_irqrestore(&data_saved_lock, flags); + } return 0; } @@ -550,6 +571,53 @@ static struct file_operations salinfo_data_fops = { .write = salinfo_log_write, }; +#ifdef CONFIG_HOTPLUG_CPU +static int __devinit +salinfo_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) +{ + unsigned int i, cpu = (unsigned long)hcpu; + unsigned long flags; + struct salinfo_data *data; + switch (action) { + case CPU_ONLINE: + spin_lock_irqsave(&data_saved_lock, flags); + for (i = 0, data = salinfo_data; + i < ARRAY_SIZE(salinfo_data); + ++i, ++data) { + cpu_set(cpu, data->cpu_event); + salinfo_work_to_do(data); + } + spin_unlock_irqrestore(&data_saved_lock, flags); + break; + case CPU_DEAD: + spin_lock_irqsave(&data_saved_lock, flags); + for (i = 0, data = salinfo_data; + i < ARRAY_SIZE(salinfo_data); + ++i, ++data) { + struct salinfo_data_saved *data_saved; + int j; + for (j = ARRAY_SIZE(data->data_saved) - 1, data_saved = data->data_saved + j; + j >= 0; + --j, --data_saved) { + if (data_saved->buffer && data_saved->cpu == cpu) { + shift1_data_saved(data, j); + } + } + cpu_clear(cpu, data->cpu_event); + } + spin_unlock_irqrestore(&data_saved_lock, flags); + break; + } + return NOTIFY_OK; +} + +static struct notifier_block salinfo_cpu_notifier = +{ + .notifier_call = salinfo_cpu_callback, + .priority = 0, +}; +#endif /* CONFIG_HOTPLUG_CPU */ + static int __init salinfo_init(void) { @@ -557,7 +625,7 @@ salinfo_init(void) struct proc_dir_entry **sdir = salinfo_proc_entries; /* keeps track of every entry */ struct proc_dir_entry *dir, *entry; struct salinfo_data *data; - int i, j, online; + int i, j; salinfo_dir = proc_mkdir("sal", NULL); if (!salinfo_dir) @@ -572,7 +640,7 @@ salinfo_init(void) for (i = 0; i < ARRAY_SIZE(salinfo_log_name); i++) { data = salinfo_data + i; data->type = i; - sema_init(&data->sem, 0); + init_MUTEX(&data->mutex); dir = proc_mkdir(salinfo_log_name[i], salinfo_dir); if (!dir) continue; @@ -592,12 +660,8 @@ salinfo_init(void) *sdir++ = entry; /* we missed any events before now */ - online = 0; - for_each_online_cpu(j) { - set_bit(j, &data->cpu_event); - ++online; - } - sema_init(&data->sem, online); + for_each_online_cpu(j) + cpu_set(j, data->cpu_event); *sdir++ = dir; } @@ -609,6 +673,10 @@ salinfo_init(void) salinfo_timer.function = &salinfo_timeout; add_timer(&salinfo_timer); +#ifdef CONFIG_HOTPLUG_CPU + register_cpu_notifier(&salinfo_cpu_notifier); +#endif + return 0; } -- GitLab From 46b86a2da0fd14bd49765330df63a62279833acb Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 13 Jan 2006 14:29:07 -0800 Subject: [PATCH 138/465] [NET]: Use NIP6_FMT in kernel.h There are errors and inconsistency in the display of NIP6 strings. ie: net/ipv6/ip6_flowlabel.c There are errors and inconsistency in the display of NIPQUAD strings too. ie: net/netfilter/nf_conntrack_ftp.c This patch: adds NIP6_FMT to kernel.h changes all code to use NIP6_FMT fixes net/ipv6/ip6_flowlabel.c adds NIPQUAD_FMT to kernel.h fixes net/netfilter/nf_conntrack_ftp.c changes a few uses of "%u.%u.%u.%u" to NIPQUAD_FMT for symmetry to NIP6_FMT Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/linux/kernel.h | 2 ++ include/net/netfilter/nf_conntrack_tuple.h | 2 +- include/net/sctp/sctp.h | 4 ++-- net/ipv6/addrconf.c | 2 +- net/ipv6/ah6.c | 3 +-- net/ipv6/anycast.c | 4 +--- net/ipv6/esp6.c | 3 +-- net/ipv6/icmp.c | 2 +- net/ipv6/ip6_flowlabel.c | 8 +++---- net/ipv6/ipcomp6.c | 3 +-- net/ipv6/mcast.c | 9 +++---- net/ipv6/ndisc.c | 2 +- net/ipv6/netfilter/ip6t_LOG.c | 5 ++-- .../netfilter/nf_conntrack_l3proto_ipv6.c | 2 +- net/ipv6/xfrm6_tunnel.c | 8 +++---- net/netfilter/nf_conntrack_ftp.c | 4 ++-- net/sctp/ipv6.c | 24 +++++++------------ net/sctp/sm_statefuns.c | 4 ++-- security/selinux/avc.c | 5 ++-- 19 files changed, 39 insertions(+), 57 deletions(-) diff --git a/include/linux/kernel.h b/include/linux/kernel.h index e6ee2d95da7..323924edb26 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -216,6 +216,7 @@ extern void dump_stack(void); ((unsigned char *)&addr)[1], \ ((unsigned char *)&addr)[2], \ ((unsigned char *)&addr)[3] +#define NIPQUAD_FMT "%u.%u.%u.%u" #define NIP6(addr) \ ntohs((addr).s6_addr16[0]), \ @@ -226,6 +227,7 @@ extern void dump_stack(void); ntohs((addr).s6_addr16[5]), \ ntohs((addr).s6_addr16[6]), \ ntohs((addr).s6_addr16[7]) +#define NIP6_FMT "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x" #if defined(__LITTLE_ENDIAN) #define HIPQUAD(addr) \ diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h index 14ce790e5c6..530ef1f7528 100644 --- a/include/net/netfilter/nf_conntrack_tuple.h +++ b/include/net/netfilter/nf_conntrack_tuple.h @@ -111,7 +111,7 @@ struct nf_conntrack_tuple #ifdef __KERNEL__ #define NF_CT_DUMP_TUPLE(tp) \ -DEBUGP("tuple %p: %u %u %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x %hu -> %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x %hu\n", \ +DEBUGP("tuple %p: %u %u " NIP6_FMT " %hu -> " NIP6_FMT " %hu\n", \ (tp), (tp)->src.l3num, (tp)->dst.protonum, \ NIP6(*(struct in6_addr *)(tp)->src.u3.all), ntohs((tp)->src.u.all), \ NIP6(*(struct in6_addr *)(tp)->dst.u3.all), ntohs((tp)->dst.u.all)) diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 8f241216f46..a553f39f6ae 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -225,13 +225,13 @@ extern int sctp_debug_flag; if (sctp_debug_flag) { \ if (saddr->sa.sa_family == AF_INET6) { \ printk(KERN_DEBUG \ - lead "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x" trail, \ + lead NIP6_FMT trail, \ leadparm, \ NIP6(saddr->v6.sin6_addr), \ otherparms); \ } else { \ printk(KERN_DEBUG \ - lead "%u.%u.%u.%u" trail, \ + lead NIPQUAD_FMT trail, \ leadparm, \ NIPQUAD(saddr->v4.sin_addr.s_addr), \ otherparms); \ diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 7129d423975..dfb4f145a13 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2644,7 +2644,7 @@ static int if6_seq_show(struct seq_file *seq, void *v) { struct inet6_ifaddr *ifp = (struct inet6_ifaddr *)v; seq_printf(seq, - "%04x%04x%04x%04x%04x%04x%04x%04x %02x %02x %02x %02x %8s\n", + NIP6_FMT " %02x %02x %02x %02x %8s\n", NIP6(ifp->addr), ifp->idev->dev->ifindex, ifp->prefix_len, diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 13cc7f89558..c7932cb420a 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -332,8 +332,7 @@ static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, if (!x) return; - NETDEBUG(KERN_DEBUG "pmtu discovery on SA AH/%08x/" - "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + NETDEBUG(KERN_DEBUG "pmtu discovery on SA AH/%08x/" NIP6_FMT "\n", ntohl(ah->spi), NIP6(iph->daddr)); xfrm_state_put(x); diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index 65e73ac0d6d..72bd08af2df 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c @@ -532,9 +532,7 @@ static int ac6_seq_show(struct seq_file *seq, void *v) struct ac6_iter_state *state = ac6_seq_private(seq); seq_printf(seq, - "%-4d %-15s " - "%04x%04x%04x%04x%04x%04x%04x%04x " - "%5d\n", + "%-4d %-15s " NIP6_FMT " %5d\n", state->dev->ifindex, state->dev->name, NIP6(im->aca_addr), im->aca_users); diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 6de8ee1a5ad..7b5b94f1390 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -266,8 +266,7 @@ static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET6); if (!x) return; - printk(KERN_DEBUG "pmtu discovery on SA ESP/%08x/" - "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + printk(KERN_DEBUG "pmtu discovery on SA ESP/%08x/" NIP6_FMT "\n", ntohl(esph->spi), NIP6(iph->daddr)); xfrm_state_put(x); } diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 53c81fcd20b..fcf883183ce 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -607,7 +607,7 @@ static int icmpv6_rcv(struct sk_buff **pskb) skb->csum = ~csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6, 0); if (__skb_checksum_complete(skb)) { - LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x > %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]\n", + LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [" NIP6_FMT " > " NIP6_FMT "]\n", NIP6(*saddr), NIP6(*daddr)); goto discard_it; } diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 964ad9d1276..4183c8dac7f 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c @@ -629,9 +629,7 @@ static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl) { while(fl) { seq_printf(seq, - "%05X %-1d %-6d %-6d %-6ld %-8ld " - "%02x%02x%02x%02x%02x%02x%02x%02x " - "%-4d\n", + "%05X %-1d %-6d %-6d %-6ld %-8ld " NIP6_FMT " %-4d\n", (unsigned)ntohl(fl->label), fl->share, (unsigned)fl->owner, @@ -647,8 +645,8 @@ static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl) static int ip6fl_seq_show(struct seq_file *seq, void *v) { if (v == SEQ_START_TOKEN) - seq_puts(seq, "Label S Owner Users Linger Expires " - "Dst Opt\n"); + seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-39s %s\n", + "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt"); else ip6fl_fl_seq_show(seq, v); return 0; diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 626dd39685f..d511a884dad 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -212,8 +212,7 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, if (!x) return; - printk(KERN_DEBUG "pmtu discovery on SA IPCOMP/%08x/" - "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + printk(KERN_DEBUG "pmtu discovery on SA IPCOMP/%08x/" NIP6_FMT "\n", spi, NIP6(iph->daddr)); xfrm_state_put(x); } diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index cc3e9f56086..0e03eabfb9d 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -2373,7 +2373,7 @@ static int igmp6_mc_seq_show(struct seq_file *seq, void *v) struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq); seq_printf(seq, - "%-4d %-15s %04x%04x%04x%04x%04x%04x%04x%04x %5d %08X %ld\n", + "%-4d %-15s " NIP6_FMT " %5d %08X %ld\n", state->dev->ifindex, state->dev->name, NIP6(im->mca_addr), im->mca_users, im->mca_flags, @@ -2542,15 +2542,12 @@ static int igmp6_mcf_seq_show(struct seq_file *seq, void *v) if (v == SEQ_START_TOKEN) { seq_printf(seq, "%3s %6s " - "%32s %32s %6s %6s\n", "Idx", + "%39s %39s %6s %6s\n", "Idx", "Device", "Multicast Address", "Source Address", "INC", "EXC"); } else { seq_printf(seq, - "%3d %6.6s " - "%04x%04x%04x%04x%04x%04x%04x%04x " - "%04x%04x%04x%04x%04x%04x%04x%04x " - "%6lu %6lu\n", + "%3d %6.6s " NIP6_FMT " " NIP6_FMT " %6lu %6lu\n", state->dev->ifindex, state->dev->name, NIP6(state->im->mca_addr), NIP6(psf->sf_addr), diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 305d9ee6d7d..cb8856b1d95 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -692,7 +692,7 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb) if (!(neigh->nud_state & NUD_VALID)) { ND_PRINTK1(KERN_DEBUG "%s(): trying to ucast probe in NUD_INVALID: " - "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + NIP6_FMT "\n", __FUNCTION__, NIP6(*target)); } diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index fc19d8a4ca6..77c725832de 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c @@ -63,9 +63,8 @@ static void dump_packet(const struct nf_loginfo *info, return; } - /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000" */ - printk("SRC=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ih->saddr)); - printk("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ih->daddr)); + /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */ + printk("SRC=" NIP6_FMT " DST=" NIP6_FMT " ", NIP6(ih->saddr), NIP6(ih->daddr)); /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */ printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ", diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 92ad53d8f8c..ac702a29dd1 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -74,7 +74,7 @@ static int ipv6_invert_tuple(struct nf_conntrack_tuple *tuple, static int ipv6_print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple) { - return seq_printf(s, "src=%x:%x:%x:%x:%x:%x:%x:%x dst=%x:%x:%x:%x:%x:%x:%x:%x ", + return seq_printf(s, "src=" NIP6_FMT " dst=" NIP6_FMT " ", NIP6(*((struct in6_addr *)tuple->src.u3.ip6)), NIP6(*((struct in6_addr *)tuple->dst.u3.ip6))); } diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index da09ff25864..8cfc58b96fc 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c @@ -259,8 +259,7 @@ try_next_2:; spi = 0; goto out; alloc_spi: - X6TPRINTK3(KERN_DEBUG "%s(): allocate new spi for " - "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + X6TPRINTK3(KERN_DEBUG "%s(): allocate new spi for " NIP6_FMT "\n", __FUNCTION__, NIP6(*(struct in6_addr *)saddr)); x6spi = kmem_cache_alloc(xfrm6_tunnel_spi_kmem, SLAB_ATOMIC); @@ -323,9 +322,8 @@ void xfrm6_tunnel_free_spi(xfrm_address_t *saddr) list_byaddr) { if (memcmp(&x6spi->addr, saddr, sizeof(x6spi->addr)) == 0) { - X6TPRINTK3(KERN_DEBUG "%s(): x6spi object " - "for %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x " - "found at %p\n", + X6TPRINTK3(KERN_DEBUG "%s(): x6spi object for " NIP6_FMT + " found at %p\n", __FUNCTION__, NIP6(*(struct in6_addr *)saddr), x6spi); diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index d5a6eaf4a1d..ab0c920f0d3 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c @@ -545,11 +545,11 @@ static int help(struct sk_buff **pskb, different IP address. Simply don't record it for NAT. */ if (cmd.l3num == PF_INET) { - DEBUGP("conntrack_ftp: NOT RECORDING: %u,%u,%u,%u != %u.%u.%u.%u\n", + DEBUGP("conntrack_ftp: NOT RECORDING: " NIPQUAD_FMT " != " NIPQUAD_FMT "\n", NIPQUAD(cmd.u3.ip), NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip)); } else { - DEBUGP("conntrack_ftp: NOT RECORDING: %x:%x:%x:%x:%x:%x:%x:%x != %x:%x:%x:%x:%x:%x:%x:%x\n", + DEBUGP("conntrack_ftp: NOT RECORDING: " NIP6_FMT " != " NIP6_FMT "\n", NIP6(*((struct in6_addr *)cmd.u3.ip6)), NIP6(*((struct in6_addr *)ct->tuplehash[dir] .tuple.src.u3.ip6))); diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 04c7fab4edc..2e266129a76 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -180,8 +180,7 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport, } SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, " - "src:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x " - "dst:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + "src:" NIP6_FMT " dst:" NIP6_FMT "\n", __FUNCTION__, skb, skb->len, NIP6(fl.fl6_src), NIP6(fl.fl6_dst)); @@ -206,13 +205,13 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc, fl.oif = daddr->v6.sin6_scope_id; - SCTP_DEBUG_PRINTK("%s: DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", + SCTP_DEBUG_PRINTK("%s: DST=" NIP6_FMT " ", __FUNCTION__, NIP6(fl.fl6_dst)); if (saddr) { ipv6_addr_copy(&fl.fl6_src, &saddr->v6.sin6_addr); SCTP_DEBUG_PRINTK( - "SRC=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x - ", + "SRC=" NIP6_FMT " - ", NIP6(fl.fl6_src)); } @@ -221,8 +220,7 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc, struct rt6_info *rt; rt = (struct rt6_info *)dst; SCTP_DEBUG_PRINTK( - "rt6_dst:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x " - "rt6_src:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + "rt6_dst:" NIP6_FMT " rt6_src:" NIP6_FMT "\n", NIP6(rt->rt6i_dst.addr), NIP6(rt->rt6i_src.addr)); } else { SCTP_DEBUG_PRINTK("NO ROUTE\n"); @@ -271,13 +269,12 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc, __u8 bmatchlen; SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p " - "daddr:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", + "daddr:" NIP6_FMT " ", __FUNCTION__, asoc, dst, NIP6(daddr->v6.sin6_addr)); if (!asoc) { ipv6_get_saddr(dst, &daddr->v6.sin6_addr,&saddr->v6.sin6_addr); - SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: " - "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: " NIP6_FMT "\n", NIP6(saddr->v6.sin6_addr)); return; } @@ -305,13 +302,11 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc, if (baddr) { memcpy(saddr, baddr, sizeof(union sctp_addr)); - SCTP_DEBUG_PRINTK("saddr: " - "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + SCTP_DEBUG_PRINTK("saddr: " NIP6_FMT "\n", NIP6(saddr->v6.sin6_addr)); } else { printk(KERN_ERR "%s: asoc:%p Could not find a valid source " - "address for the " - "dest:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + "address for the dest:" NIP6_FMT "\n", __FUNCTION__, asoc, NIP6(daddr->v6.sin6_addr)); } @@ -675,8 +670,7 @@ static int sctp_v6_is_ce(const struct sk_buff *skb) /* Dump the v6 addr to the seq file. */ static void sctp_v6_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr) { - seq_printf(seq, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", - NIP6(addr->v6.sin6_addr)); + seq_printf(seq, NIP6_FMT " ", NIP6(addr->v6.sin6_addr)); } /* Initialize a PF_INET6 socket msg_name. */ diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 557a7d90b92..477d7f80dba 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -1036,14 +1036,14 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep, if (from_addr.sa.sa_family == AF_INET6) { printk(KERN_WARNING "%s association %p could not find address " - "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + NIP6_FMT "\n", __FUNCTION__, asoc, NIP6(from_addr.v6.sin6_addr)); } else { printk(KERN_WARNING "%s association %p could not find address " - "%u.%u.%u.%u\n", + NIPQUAD_FMT "\n", __FUNCTION__, asoc, NIPQUAD(from_addr.v4.sin_addr.s_addr)); diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 12e4fb72bf0..53d6c7bbf56 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -494,8 +494,7 @@ static inline void avc_print_ipv6_addr(struct audit_buffer *ab, char *name1, char *name2) { if (!ipv6_addr_any(addr)) - audit_log_format(ab, " %s=%04x:%04x:%04x:%04x:%04x:" - "%04x:%04x:%04x", name1, NIP6(*addr)); + audit_log_format(ab, " %s=" NIP6_FMT, name1, NIP6(*addr)); if (port) audit_log_format(ab, " %s=%d", name2, ntohs(port)); } @@ -504,7 +503,7 @@ static inline void avc_print_ipv4_addr(struct audit_buffer *ab, u32 addr, __be16 port, char *name1, char *name2) { if (addr) - audit_log_format(ab, " %s=%d.%d.%d.%d", name1, NIPQUAD(addr)); + audit_log_format(ab, " %s=" NIPQUAD_FMT, name1, NIPQUAD(addr)); if (port) audit_log_format(ab, " %s=%d", name2, ntohs(port)); } -- GitLab From 7b11f69fb5c475f521db79f5fa22104e15842671 Mon Sep 17 00:00:00 2001 From: Kris Katterjohn Date: Fri, 13 Jan 2006 14:33:06 -0800 Subject: [PATCH 139/465] [NET]: Clean up comments for sk_chk_filter() This removes redundant comments, and moves one comment to a better location. Signed-off-by: Kris Katterjohn Signed-off-by: David S. Miller --- net/core/filter.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/net/core/filter.c b/net/core/filter.c index 9eb9d0017a0..a52665f7522 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -287,7 +287,9 @@ load_b: * no references or jumps that are out of range, no illegal * instructions, and must end with a RET instruction. * - * Returns 0 if the rule set is legal or a negative errno code if not. + * All jumps are forward as they are not signed. + * + * Returns 0 if the rule set is legal or -EINVAL if not. */ int sk_chk_filter(struct sock_filter *filter, int flen) { @@ -299,7 +301,6 @@ int sk_chk_filter(struct sock_filter *filter, int flen) /* check the filter code now */ for (pc = 0; pc < flen; pc++) { - /* all jumps are forward as they are not signed */ ftest = &filter[pc]; /* Only allow valid instructions */ @@ -383,11 +384,6 @@ int sk_chk_filter(struct sock_filter *filter, int flen) } } - /* - * The program must end with a return. We don't care where they - * jumped within the script (its always forwards) but in the end - * they _will_ hit this. - */ return (BPF_CLASS(filter[flen - 1].code) == BPF_RET) ? 0 : -EINVAL; } -- GitLab From ee51b1b6cece4dad408feeb0c3c9adb9cbd9f7d9 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Fri, 13 Jan 2006 14:34:36 -0800 Subject: [PATCH 140/465] [XFRM]: IPsec tunnel wildcard address support When the source address of a tunnel is given as 0.0.0.0 do a routing lookup to get the real source address for the destination and fill that into the acquire message. This allows to specify policies like this: spdadd 172.16.128.13/32 172.16.0.0/20 any -P out ipsec esp/tunnel/0.0.0.0-x.x.x.x/require; spdadd 172.16.0.0/20 172.16.128.13/32 any -P in ipsec esp/tunnel/x.x.x.x-0.0.0.0/require; Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/xfrm4_state.c | 15 +++++++++++++++ net/ipv6/xfrm6_state.c | 17 +++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c index d23e07fc81f..dbabf81a9b7 100644 --- a/net/ipv4/xfrm4_state.c +++ b/net/ipv4/xfrm4_state.c @@ -42,6 +42,21 @@ __xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl, x->props.saddr = tmpl->saddr; if (x->props.saddr.a4 == 0) x->props.saddr.a4 = saddr->a4; + if (tmpl->mode && x->props.saddr.a4 == 0) { + struct rtable *rt; + struct flowi fl_tunnel = { + .nl_u = { + .ip4_u = { + .daddr = x->id.daddr.a4, + } + } + }; + if (!xfrm_dst_lookup((struct xfrm_dst **)&rt, + &fl_tunnel, AF_INET)) { + x->props.saddr.a4 = rt->rt_src; + dst_release(&rt->u.dst); + } + } x->props.mode = tmpl->mode; x->props.reqid = tmpl->reqid; x->props.family = AF_INET; diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index bf0d0abc387..a5723024d3b 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c @@ -15,6 +15,7 @@ #include #include #include +#include static struct xfrm_state_afinfo xfrm6_state_afinfo; @@ -41,6 +42,22 @@ __xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl, memcpy(&x->props.saddr, &tmpl->saddr, sizeof(x->props.saddr)); if (ipv6_addr_any((struct in6_addr*)&x->props.saddr)) memcpy(&x->props.saddr, saddr, sizeof(x->props.saddr)); + if (tmpl->mode && ipv6_addr_any((struct in6_addr*)&x->props.saddr)) { + struct rt6_info *rt; + struct flowi fl_tunnel = { + .nl_u = { + .ip6_u = { + .daddr = *(struct in6_addr *)daddr, + } + } + }; + if (!xfrm_dst_lookup((struct xfrm_dst **)&rt, + &fl_tunnel, AF_INET6)) { + ipv6_get_saddr(&rt->u.dst, (struct in6_addr *)daddr, + (struct in6_addr *)&x->props.saddr); + dst_release(&rt->u.dst); + } + } x->props.mode = tmpl->mode; x->props.reqid = tmpl->reqid; x->props.family = AF_INET6; -- GitLab From dca80b962a811a0454d779ab6250b59446a8c86c Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Fri, 13 Jan 2006 14:36:55 -0800 Subject: [PATCH 141/465] [PKT_SCHED]: Change default clock source to gettimeofday The default of using jiffies is very bad and results in underutilization except with very low bandwidth. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/sched/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sched/Kconfig b/net/sched/Kconfig index 8a260d43cee..778b1e5a4b5 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig @@ -44,7 +44,7 @@ if NET_SCHED choice prompt "Packet scheduler clock source" - default NET_SCH_CLK_JIFFIES + default NET_SCH_CLK_GETTIMEOFDAY ---help--- Packet schedulers need a monotonic clock that increments at a static rate. The kernel provides several suitable interfaces, each with -- GitLab From d3ef1f5aafcf7a4129eb2078c70bc9e577bc3af1 Mon Sep 17 00:00:00 2001 From: Zhang Yanmin Date: Fri, 13 Jan 2006 14:45:21 -0800 Subject: [PATCH 142/465] [IA64] prevent accidental modification of args in jprobe handler When jprobe is hit, the function parameters of the original function should be saved before jprobe handler is executed, and restored it after jprobe handler is executed, because jprobe handler might change the register values due to tail call optimization by the gcc. Signed-off-by: Zhang Yanmin Signed-off-by: Anil S Keshavamurthy Signed-off-by: Tony Luck --- arch/ia64/kernel/jprobes.S | 27 ++++++++++++++++++ arch/ia64/kernel/kprobes.c | 57 ++++++++++++++++++++++++++++++++++++++ include/asm-ia64/kprobes.h | 6 ++++ 3 files changed, 90 insertions(+) diff --git a/arch/ia64/kernel/jprobes.S b/arch/ia64/kernel/jprobes.S index 2323377e369..5cd6226f44f 100644 --- a/arch/ia64/kernel/jprobes.S +++ b/arch/ia64/kernel/jprobes.S @@ -60,3 +60,30 @@ END(jprobe_break) GLOBAL_ENTRY(jprobe_inst_return) br.call.sptk.many b0=jprobe_break END(jprobe_inst_return) + +GLOBAL_ENTRY(invalidate_stacked_regs) + movl r16=invalidate_restore_cfm + ;; + mov b6=r16 + ;; + br.ret.sptk.many b6 + ;; +invalidate_restore_cfm: + mov r16=ar.rsc + ;; + mov ar.rsc=r0 + ;; + loadrs + ;; + mov ar.rsc=r16 + ;; + br.cond.sptk.many rp +END(invalidate_stacked_regs) + +GLOBAL_ENTRY(flush_register_stack) + // flush dirty regs to backing store (must be first in insn group) + flushrs + ;; + br.ret.sptk.many rp +END(flush_register_stack) + diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index 346fedf9ea4..50ae8c7d453 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c @@ -766,11 +766,56 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, return ret; } +struct param_bsp_cfm { + unsigned long ip; + unsigned long *bsp; + unsigned long cfm; +}; + +static void ia64_get_bsp_cfm(struct unw_frame_info *info, void *arg) +{ + unsigned long ip; + struct param_bsp_cfm *lp = arg; + + do { + unw_get_ip(info, &ip); + if (ip == 0) + break; + if (ip == lp->ip) { + unw_get_bsp(info, (unsigned long*)&lp->bsp); + unw_get_cfm(info, (unsigned long*)&lp->cfm); + return; + } + } while (unw_unwind(info) >= 0); + lp->bsp = 0; + lp->cfm = 0; + return; +} + int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) { struct jprobe *jp = container_of(p, struct jprobe, kp); unsigned long addr = ((struct fnptr *)(jp->entry))->ip; struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + struct param_bsp_cfm pa; + int bytes; + + /* + * Callee owns the argument space and could overwrite it, eg + * tail call optimization. So to be absolutely safe + * we save the argument space before transfering the control + * to instrumented jprobe function which runs in + * the process context + */ + pa.ip = regs->cr_iip; + unw_init_running(ia64_get_bsp_cfm, &pa); + bytes = (char *)ia64_rse_skip_regs(pa.bsp, pa.cfm & 0x3f) + - (char *)pa.bsp; + memcpy( kcb->jprobes_saved_stacked_regs, + pa.bsp, + bytes ); + kcb->bsp = pa.bsp; + kcb->cfm = pa.cfm; /* save architectural state */ kcb->jprobe_saved_regs = *regs; @@ -792,8 +837,20 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) { struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + int bytes; + /* restoring architectural state */ *regs = kcb->jprobe_saved_regs; + + /* restoring the original argument space */ + flush_register_stack(); + bytes = (char *)ia64_rse_skip_regs(kcb->bsp, kcb->cfm & 0x3f) + - (char *)kcb->bsp; + memcpy( kcb->bsp, + kcb->jprobes_saved_stacked_regs, + bytes ); + invalidate_stacked_regs(); + preempt_enable_no_resched(); return 1; } diff --git a/include/asm-ia64/kprobes.h b/include/asm-ia64/kprobes.h index a74b6810455..8c0fc227f0f 100644 --- a/include/asm-ia64/kprobes.h +++ b/include/asm-ia64/kprobes.h @@ -68,10 +68,14 @@ struct prev_kprobe { unsigned long status; }; +#define MAX_PARAM_RSE_SIZE (0x60+0x60/0x3f) /* per-cpu kprobe control block */ struct kprobe_ctlblk { unsigned long kprobe_status; struct pt_regs jprobe_saved_regs; + unsigned long jprobes_saved_stacked_regs[MAX_PARAM_RSE_SIZE]; + unsigned long *bsp; + unsigned long cfm; struct prev_kprobe prev_kprobe; }; @@ -118,5 +122,7 @@ extern int kprobe_exceptions_notify(struct notifier_block *self, static inline void jprobe_return(void) { } +extern void invalidate_stacked_regs(void); +extern void flush_register_stack(void); #endif /* _ASM_KPROBES_H */ -- GitLab From 95ed644fd12f53c6fc778f3f246974e5fe3a9468 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 13 Jan 2006 14:51:39 -0800 Subject: [PATCH 143/465] IB: convert from semaphores to mutexes semaphore to mutex conversion by Ingo and Arjan's script. Signed-off-by: Ingo Molnar [ Sanity-checked on real IB hardware ] Signed-off-by: Roland Dreier --- drivers/infiniband/core/device.c | 23 ++- drivers/infiniband/core/ucm.c | 23 +-- drivers/infiniband/core/uverbs.h | 5 +- drivers/infiniband/core/uverbs_cmd.c | 150 +++++++++--------- drivers/infiniband/core/uverbs_main.c | 8 +- drivers/infiniband/ulp/ipoib/ipoib.h | 6 +- drivers/infiniband/ulp/ipoib/ipoib_ib.c | 18 +-- drivers/infiniband/ulp/ipoib/ipoib_main.c | 12 +- .../infiniband/ulp/ipoib/ipoib_multicast.c | 26 +-- drivers/infiniband/ulp/ipoib/ipoib_verbs.c | 8 +- drivers/infiniband/ulp/ipoib/ipoib_vlan.c | 10 +- 11 files changed, 145 insertions(+), 144 deletions(-) diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index e169e798354..b2f3cb91d9b 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c @@ -38,8 +38,7 @@ #include #include #include - -#include +#include #include "core_priv.h" @@ -57,13 +56,13 @@ static LIST_HEAD(device_list); static LIST_HEAD(client_list); /* - * device_sem protects access to both device_list and client_list. + * device_mutex protects access to both device_list and client_list. * There's no real point to using multiple locks or something fancier * like an rwsem: we always access both lists, and we're always * modifying one list or the other list. In any case this is not a * hot path so there's no point in trying to optimize. */ -static DECLARE_MUTEX(device_sem); +static DEFINE_MUTEX(device_mutex); static int ib_device_check_mandatory(struct ib_device *device) { @@ -221,7 +220,7 @@ int ib_register_device(struct ib_device *device) { int ret; - down(&device_sem); + mutex_lock(&device_mutex); if (strchr(device->name, '%')) { ret = alloc_name(device->name); @@ -259,7 +258,7 @@ int ib_register_device(struct ib_device *device) } out: - up(&device_sem); + mutex_unlock(&device_mutex); return ret; } EXPORT_SYMBOL(ib_register_device); @@ -276,7 +275,7 @@ void ib_unregister_device(struct ib_device *device) struct ib_client_data *context, *tmp; unsigned long flags; - down(&device_sem); + mutex_lock(&device_mutex); list_for_each_entry_reverse(client, &client_list, list) if (client->remove) @@ -284,7 +283,7 @@ void ib_unregister_device(struct ib_device *device) list_del(&device->core_list); - up(&device_sem); + mutex_unlock(&device_mutex); spin_lock_irqsave(&device->client_data_lock, flags); list_for_each_entry_safe(context, tmp, &device->client_data_list, list) @@ -312,14 +311,14 @@ int ib_register_client(struct ib_client *client) { struct ib_device *device; - down(&device_sem); + mutex_lock(&device_mutex); list_add_tail(&client->list, &client_list); list_for_each_entry(device, &device_list, core_list) if (client->add && !add_client_context(device, client)) client->add(device); - up(&device_sem); + mutex_unlock(&device_mutex); return 0; } @@ -339,7 +338,7 @@ void ib_unregister_client(struct ib_client *client) struct ib_device *device; unsigned long flags; - down(&device_sem); + mutex_lock(&device_mutex); list_for_each_entry(device, &device_list, core_list) { if (client->remove) @@ -355,7 +354,7 @@ void ib_unregister_client(struct ib_client *client) } list_del(&client->list); - up(&device_sem); + mutex_unlock(&device_mutex); } EXPORT_SYMBOL(ib_unregister_client); diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c index 6e15787d1de..e95c4293a49 100644 --- a/drivers/infiniband/core/ucm.c +++ b/drivers/infiniband/core/ucm.c @@ -42,6 +42,7 @@ #include #include #include +#include #include @@ -113,7 +114,7 @@ static struct ib_client ucm_client = { .remove = ib_ucm_remove_one }; -static DECLARE_MUTEX(ctx_id_mutex); +static DEFINE_MUTEX(ctx_id_mutex); static DEFINE_IDR(ctx_id_table); static DECLARE_BITMAP(dev_map, IB_UCM_MAX_DEVICES); @@ -121,7 +122,7 @@ static struct ib_ucm_context *ib_ucm_ctx_get(struct ib_ucm_file *file, int id) { struct ib_ucm_context *ctx; - down(&ctx_id_mutex); + mutex_lock(&ctx_id_mutex); ctx = idr_find(&ctx_id_table, id); if (!ctx) ctx = ERR_PTR(-ENOENT); @@ -129,7 +130,7 @@ static struct ib_ucm_context *ib_ucm_ctx_get(struct ib_ucm_file *file, int id) ctx = ERR_PTR(-EINVAL); else atomic_inc(&ctx->ref); - up(&ctx_id_mutex); + mutex_unlock(&ctx_id_mutex); return ctx; } @@ -186,9 +187,9 @@ static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file) if (!result) goto error; - down(&ctx_id_mutex); + mutex_lock(&ctx_id_mutex); result = idr_get_new(&ctx_id_table, ctx, &ctx->id); - up(&ctx_id_mutex); + mutex_unlock(&ctx_id_mutex); } while (result == -EAGAIN); if (result) @@ -550,9 +551,9 @@ static ssize_t ib_ucm_create_id(struct ib_ucm_file *file, err2: ib_destroy_cm_id(ctx->cm_id); err1: - down(&ctx_id_mutex); + mutex_lock(&ctx_id_mutex); idr_remove(&ctx_id_table, ctx->id); - up(&ctx_id_mutex); + mutex_unlock(&ctx_id_mutex); kfree(ctx); return result; } @@ -572,7 +573,7 @@ static ssize_t ib_ucm_destroy_id(struct ib_ucm_file *file, if (copy_from_user(&cmd, inbuf, sizeof(cmd))) return -EFAULT; - down(&ctx_id_mutex); + mutex_lock(&ctx_id_mutex); ctx = idr_find(&ctx_id_table, cmd.id); if (!ctx) ctx = ERR_PTR(-ENOENT); @@ -580,7 +581,7 @@ static ssize_t ib_ucm_destroy_id(struct ib_ucm_file *file, ctx = ERR_PTR(-EINVAL); else idr_remove(&ctx_id_table, ctx->id); - up(&ctx_id_mutex); + mutex_unlock(&ctx_id_mutex); if (IS_ERR(ctx)) return PTR_ERR(ctx); @@ -1280,9 +1281,9 @@ static int ib_ucm_close(struct inode *inode, struct file *filp) struct ib_ucm_context, file_list); up(&file->mutex); - down(&ctx_id_mutex); + mutex_lock(&ctx_id_mutex); idr_remove(&ctx_id_table, ctx->id); - up(&ctx_id_mutex); + mutex_unlock(&ctx_id_mutex); ib_destroy_cm_id(ctx->cm_id); ib_ucm_cleanup_events(ctx); diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h index 7114e3fbab0..f7eecbc6af6 100644 --- a/drivers/infiniband/core/uverbs.h +++ b/drivers/infiniband/core/uverbs.h @@ -41,6 +41,7 @@ #include #include +#include #include #include @@ -88,7 +89,7 @@ struct ib_uverbs_event_file { struct ib_uverbs_file { struct kref ref; - struct semaphore mutex; + struct mutex mutex; struct ib_uverbs_device *device; struct ib_ucontext *ucontext; struct ib_event_handler event_handler; @@ -131,7 +132,7 @@ struct ib_ucq_object { u32 async_events_reported; }; -extern struct semaphore ib_uverbs_idr_mutex; +extern struct mutex ib_uverbs_idr_mutex; extern struct idr ib_uverbs_pd_idr; extern struct idr ib_uverbs_mr_idr; extern struct idr ib_uverbs_mw_idr; diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 554c2057b7c..407b6284d7d 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -67,7 +67,7 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - down(&file->mutex); + mutex_lock(&file->mutex); if (file->ucontext) { ret = -EINVAL; @@ -119,7 +119,7 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file, fd_install(resp.async_fd, filp); - up(&file->mutex); + mutex_unlock(&file->mutex); return in_len; @@ -131,7 +131,7 @@ err_free: ibdev->dealloc_ucontext(ucontext); err: - up(&file->mutex); + mutex_unlock(&file->mutex); return ret; } @@ -290,7 +290,7 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file, pd->uobject = uobj; atomic_set(&pd->usecnt, 0); - down(&ib_uverbs_idr_mutex); + mutex_lock(&ib_uverbs_idr_mutex); retry: if (!idr_pre_get(&ib_uverbs_pd_idr, GFP_KERNEL)) { @@ -314,11 +314,11 @@ retry: goto err_idr; } - down(&file->mutex); + mutex_lock(&file->mutex); list_add_tail(&uobj->list, &file->ucontext->pd_list); - up(&file->mutex); + mutex_unlock(&file->mutex); - up(&ib_uverbs_idr_mutex); + mutex_unlock(&ib_uverbs_idr_mutex); return in_len; @@ -326,7 +326,7 @@ err_idr: idr_remove(&ib_uverbs_pd_idr, uobj->id); err_up: - up(&ib_uverbs_idr_mutex); + mutex_unlock(&ib_uverbs_idr_mutex); ib_dealloc_pd(pd); err: @@ -346,7 +346,7 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - down(&ib_uverbs_idr_mutex); + mutex_lock(&ib_uverbs_idr_mutex); pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); if (!pd || pd->uobject->context != file->ucontext) @@ -360,14 +360,14 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file, idr_remove(&ib_uverbs_pd_idr, cmd.pd_handle); - down(&file->mutex); + mutex_lock(&file->mutex); list_del(&uobj->list); - up(&file->mutex); + mutex_unlock(&file->mutex); kfree(uobj); out: - up(&ib_uverbs_idr_mutex); + mutex_unlock(&ib_uverbs_idr_mutex); return ret ? ret : in_len; } @@ -426,7 +426,7 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file, obj->umem.virt_base = cmd.hca_va; - down(&ib_uverbs_idr_mutex); + mutex_lock(&ib_uverbs_idr_mutex); pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); if (!pd || pd->uobject->context != file->ucontext) { @@ -476,11 +476,11 @@ retry: goto err_idr; } - down(&file->mutex); + mutex_lock(&file->mutex); list_add_tail(&obj->uobject.list, &file->ucontext->mr_list); - up(&file->mutex); + mutex_unlock(&file->mutex); - up(&ib_uverbs_idr_mutex); + mutex_unlock(&ib_uverbs_idr_mutex); return in_len; @@ -492,7 +492,7 @@ err_unreg: atomic_dec(&pd->usecnt); err_up: - up(&ib_uverbs_idr_mutex); + mutex_unlock(&ib_uverbs_idr_mutex); ib_umem_release(file->device->ib_dev, &obj->umem); @@ -513,7 +513,7 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - down(&ib_uverbs_idr_mutex); + mutex_lock(&ib_uverbs_idr_mutex); mr = idr_find(&ib_uverbs_mr_idr, cmd.mr_handle); if (!mr || mr->uobject->context != file->ucontext) @@ -527,15 +527,15 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file, idr_remove(&ib_uverbs_mr_idr, cmd.mr_handle); - down(&file->mutex); + mutex_lock(&file->mutex); list_del(&memobj->uobject.list); - up(&file->mutex); + mutex_unlock(&file->mutex); ib_umem_release(file->device->ib_dev, &memobj->umem); kfree(memobj); out: - up(&ib_uverbs_idr_mutex); + mutex_unlock(&ib_uverbs_idr_mutex); return ret ? ret : in_len; } @@ -628,7 +628,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, cq->cq_context = ev_file; atomic_set(&cq->usecnt, 0); - down(&ib_uverbs_idr_mutex); + mutex_lock(&ib_uverbs_idr_mutex); retry: if (!idr_pre_get(&ib_uverbs_cq_idr, GFP_KERNEL)) { @@ -653,11 +653,11 @@ retry: goto err_idr; } - down(&file->mutex); + mutex_lock(&file->mutex); list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list); - up(&file->mutex); + mutex_unlock(&file->mutex); - up(&ib_uverbs_idr_mutex); + mutex_unlock(&ib_uverbs_idr_mutex); return in_len; @@ -665,7 +665,7 @@ err_idr: idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id); err_up: - up(&ib_uverbs_idr_mutex); + mutex_unlock(&ib_uverbs_idr_mutex); ib_destroy_cq(cq); err: @@ -701,7 +701,7 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file, goto out_wc; } - down(&ib_uverbs_idr_mutex); + mutex_lock(&ib_uverbs_idr_mutex); cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); if (!cq || cq->uobject->context != file->ucontext) { ret = -EINVAL; @@ -731,7 +731,7 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file, ret = -EFAULT; out: - up(&ib_uverbs_idr_mutex); + mutex_unlock(&ib_uverbs_idr_mutex); kfree(resp); out_wc: @@ -750,14 +750,14 @@ ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - down(&ib_uverbs_idr_mutex); + mutex_lock(&ib_uverbs_idr_mutex); cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); if (cq && cq->uobject->context == file->ucontext) { ib_req_notify_cq(cq, cmd.solicited_only ? IB_CQ_SOLICITED : IB_CQ_NEXT_COMP); ret = in_len; } - up(&ib_uverbs_idr_mutex); + mutex_unlock(&ib_uverbs_idr_mutex); return ret; } @@ -779,7 +779,7 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file, memset(&resp, 0, sizeof resp); - down(&ib_uverbs_idr_mutex); + mutex_lock(&ib_uverbs_idr_mutex); cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); if (!cq || cq->uobject->context != file->ucontext) @@ -795,9 +795,9 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file, idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle); - down(&file->mutex); + mutex_lock(&file->mutex); list_del(&uobj->uobject.list); - up(&file->mutex); + mutex_unlock(&file->mutex); ib_uverbs_release_ucq(file, ev_file, uobj); @@ -811,7 +811,7 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file, ret = -EFAULT; out: - up(&ib_uverbs_idr_mutex); + mutex_unlock(&ib_uverbs_idr_mutex); return ret ? ret : in_len; } @@ -845,7 +845,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, if (!uobj) return -ENOMEM; - down(&ib_uverbs_idr_mutex); + mutex_lock(&ib_uverbs_idr_mutex); pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); scq = idr_find(&ib_uverbs_cq_idr, cmd.send_cq_handle); @@ -930,11 +930,11 @@ retry: goto err_idr; } - down(&file->mutex); + mutex_lock(&file->mutex); list_add_tail(&uobj->uevent.uobject.list, &file->ucontext->qp_list); - up(&file->mutex); + mutex_unlock(&file->mutex); - up(&ib_uverbs_idr_mutex); + mutex_unlock(&ib_uverbs_idr_mutex); return in_len; @@ -950,7 +950,7 @@ err_destroy: atomic_dec(&attr.srq->usecnt); err_up: - up(&ib_uverbs_idr_mutex); + mutex_unlock(&ib_uverbs_idr_mutex); kfree(uobj); return ret; @@ -972,7 +972,7 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, if (!attr) return -ENOMEM; - down(&ib_uverbs_idr_mutex); + mutex_lock(&ib_uverbs_idr_mutex); qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); if (!qp || qp->uobject->context != file->ucontext) { @@ -1033,7 +1033,7 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, ret = in_len; out: - up(&ib_uverbs_idr_mutex); + mutex_unlock(&ib_uverbs_idr_mutex); kfree(attr); return ret; @@ -1054,7 +1054,7 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file, memset(&resp, 0, sizeof resp); - down(&ib_uverbs_idr_mutex); + mutex_lock(&ib_uverbs_idr_mutex); qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); if (!qp || qp->uobject->context != file->ucontext) @@ -1073,9 +1073,9 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file, idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle); - down(&file->mutex); + mutex_lock(&file->mutex); list_del(&uobj->uevent.uobject.list); - up(&file->mutex); + mutex_unlock(&file->mutex); ib_uverbs_release_uevent(file, &uobj->uevent); @@ -1088,7 +1088,7 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file, ret = -EFAULT; out: - up(&ib_uverbs_idr_mutex); + mutex_unlock(&ib_uverbs_idr_mutex); return ret ? ret : in_len; } @@ -1119,7 +1119,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file, if (!user_wr) return -ENOMEM; - down(&ib_uverbs_idr_mutex); + mutex_lock(&ib_uverbs_idr_mutex); qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); if (!qp || qp->uobject->context != file->ucontext) @@ -1224,7 +1224,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file, ret = -EFAULT; out: - up(&ib_uverbs_idr_mutex); + mutex_unlock(&ib_uverbs_idr_mutex); while (wr) { next = wr->next; @@ -1341,7 +1341,7 @@ ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file, if (IS_ERR(wr)) return PTR_ERR(wr); - down(&ib_uverbs_idr_mutex); + mutex_lock(&ib_uverbs_idr_mutex); qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); if (!qp || qp->uobject->context != file->ucontext) @@ -1362,7 +1362,7 @@ ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file, ret = -EFAULT; out: - up(&ib_uverbs_idr_mutex); + mutex_unlock(&ib_uverbs_idr_mutex); while (wr) { next = wr->next; @@ -1392,7 +1392,7 @@ ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file, if (IS_ERR(wr)) return PTR_ERR(wr); - down(&ib_uverbs_idr_mutex); + mutex_lock(&ib_uverbs_idr_mutex); srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); if (!srq || srq->uobject->context != file->ucontext) @@ -1413,7 +1413,7 @@ ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file, ret = -EFAULT; out: - up(&ib_uverbs_idr_mutex); + mutex_unlock(&ib_uverbs_idr_mutex); while (wr) { next = wr->next; @@ -1446,7 +1446,7 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file, if (!uobj) return -ENOMEM; - down(&ib_uverbs_idr_mutex); + mutex_lock(&ib_uverbs_idr_mutex); pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); if (!pd || pd->uobject->context != file->ucontext) { @@ -1498,11 +1498,11 @@ retry: goto err_idr; } - down(&file->mutex); + mutex_lock(&file->mutex); list_add_tail(&uobj->list, &file->ucontext->ah_list); - up(&file->mutex); + mutex_unlock(&file->mutex); - up(&ib_uverbs_idr_mutex); + mutex_unlock(&ib_uverbs_idr_mutex); return in_len; @@ -1513,7 +1513,7 @@ err_destroy: ib_destroy_ah(ah); err_up: - up(&ib_uverbs_idr_mutex); + mutex_unlock(&ib_uverbs_idr_mutex); kfree(uobj); return ret; @@ -1530,7 +1530,7 @@ ssize_t ib_uverbs_destroy_ah(struct ib_uverbs_file *file, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - down(&ib_uverbs_idr_mutex); + mutex_lock(&ib_uverbs_idr_mutex); ah = idr_find(&ib_uverbs_ah_idr, cmd.ah_handle); if (!ah || ah->uobject->context != file->ucontext) @@ -1544,14 +1544,14 @@ ssize_t ib_uverbs_destroy_ah(struct ib_uverbs_file *file, idr_remove(&ib_uverbs_ah_idr, cmd.ah_handle); - down(&file->mutex); + mutex_lock(&file->mutex); list_del(&uobj->list); - up(&file->mutex); + mutex_unlock(&file->mutex); kfree(uobj); out: - up(&ib_uverbs_idr_mutex); + mutex_unlock(&ib_uverbs_idr_mutex); return ret ? ret : in_len; } @@ -1569,7 +1569,7 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - down(&ib_uverbs_idr_mutex); + mutex_lock(&ib_uverbs_idr_mutex); qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); if (!qp || qp->uobject->context != file->ucontext) @@ -1602,7 +1602,7 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file, kfree(mcast); out: - up(&ib_uverbs_idr_mutex); + mutex_unlock(&ib_uverbs_idr_mutex); return ret ? ret : in_len; } @@ -1620,7 +1620,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - down(&ib_uverbs_idr_mutex); + mutex_lock(&ib_uverbs_idr_mutex); qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); if (!qp || qp->uobject->context != file->ucontext) @@ -1641,7 +1641,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file, } out: - up(&ib_uverbs_idr_mutex); + mutex_unlock(&ib_uverbs_idr_mutex); return ret ? ret : in_len; } @@ -1673,7 +1673,7 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file, if (!uobj) return -ENOMEM; - down(&ib_uverbs_idr_mutex); + mutex_lock(&ib_uverbs_idr_mutex); pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); @@ -1730,11 +1730,11 @@ retry: goto err_idr; } - down(&file->mutex); + mutex_lock(&file->mutex); list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list); - up(&file->mutex); + mutex_unlock(&file->mutex); - up(&ib_uverbs_idr_mutex); + mutex_unlock(&ib_uverbs_idr_mutex); return in_len; @@ -1746,7 +1746,7 @@ err_destroy: atomic_dec(&pd->usecnt); err_up: - up(&ib_uverbs_idr_mutex); + mutex_unlock(&ib_uverbs_idr_mutex); kfree(uobj); return ret; @@ -1764,7 +1764,7 @@ ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - down(&ib_uverbs_idr_mutex); + mutex_lock(&ib_uverbs_idr_mutex); srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); if (!srq || srq->uobject->context != file->ucontext) { @@ -1778,7 +1778,7 @@ ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file, ret = ib_modify_srq(srq, &attr, cmd.attr_mask); out: - up(&ib_uverbs_idr_mutex); + mutex_unlock(&ib_uverbs_idr_mutex); return ret ? ret : in_len; } @@ -1796,7 +1796,7 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - down(&ib_uverbs_idr_mutex); + mutex_lock(&ib_uverbs_idr_mutex); memset(&resp, 0, sizeof resp); @@ -1812,9 +1812,9 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file, idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle); - down(&file->mutex); + mutex_lock(&file->mutex); list_del(&uobj->uobject.list); - up(&file->mutex); + mutex_unlock(&file->mutex); ib_uverbs_release_uevent(file, uobj); @@ -1827,7 +1827,7 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file, ret = -EFAULT; out: - up(&ib_uverbs_idr_mutex); + mutex_unlock(&ib_uverbs_idr_mutex); return ret ? ret : in_len; } diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 81737bd6fae..96ea79b63df 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -66,7 +66,7 @@ enum { static struct class *uverbs_class; -DECLARE_MUTEX(ib_uverbs_idr_mutex); +DEFINE_MUTEX(ib_uverbs_idr_mutex); DEFINE_IDR(ib_uverbs_pd_idr); DEFINE_IDR(ib_uverbs_mr_idr); DEFINE_IDR(ib_uverbs_mw_idr); @@ -180,7 +180,7 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file, if (!context) return 0; - down(&ib_uverbs_idr_mutex); + mutex_lock(&ib_uverbs_idr_mutex); list_for_each_entry_safe(uobj, tmp, &context->ah_list, list) { struct ib_ah *ah = idr_find(&ib_uverbs_ah_idr, uobj->id); @@ -250,7 +250,7 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file, kfree(uobj); } - up(&ib_uverbs_idr_mutex); + mutex_unlock(&ib_uverbs_idr_mutex); return context->device->dealloc_ucontext(context); } @@ -653,7 +653,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp) file->ucontext = NULL; file->async_file = NULL; kref_init(&file->ref); - init_MUTEX(&file->mutex); + mutex_init(&file->mutex); filp->private_data = file; diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index 9923a15a999..e0a5412b7e6 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h @@ -45,11 +45,11 @@ #include #include #include +#include #include #include -#include #include #include @@ -123,8 +123,8 @@ struct ipoib_dev_priv { unsigned long flags; - struct semaphore mcast_mutex; - struct semaphore vlan_mutex; + struct mutex mcast_mutex; + struct mutex vlan_mutex; struct rb_root path_tree; struct list_head path_list; diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index f7e84897079..86bcdd72a10 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -52,7 +52,7 @@ MODULE_PARM_DESC(data_debug_level, #define IPOIB_OP_RECV (1ul << 31) -static DECLARE_MUTEX(pkey_sem); +static DEFINE_MUTEX(pkey_mutex); struct ipoib_ah *ipoib_create_ah(struct net_device *dev, struct ib_pd *pd, struct ib_ah_attr *attr) @@ -445,10 +445,10 @@ int ipoib_ib_dev_down(struct net_device *dev) /* Shutdown the P_Key thread if still active */ if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) { - down(&pkey_sem); + mutex_lock(&pkey_mutex); set_bit(IPOIB_PKEY_STOP, &priv->flags); cancel_delayed_work(&priv->pkey_task); - up(&pkey_sem); + mutex_unlock(&pkey_mutex); flush_workqueue(ipoib_workqueue); } @@ -599,13 +599,13 @@ void ipoib_ib_dev_flush(void *_dev) if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) ipoib_ib_dev_up(dev); - down(&priv->vlan_mutex); + mutex_lock(&priv->vlan_mutex); /* Flush any child interfaces too */ list_for_each_entry(cpriv, &priv->child_intfs, list) ipoib_ib_dev_flush(&cpriv->dev); - up(&priv->vlan_mutex); + mutex_unlock(&priv->vlan_mutex); } void ipoib_ib_dev_cleanup(struct net_device *dev) @@ -651,12 +651,12 @@ void ipoib_pkey_poll(void *dev_ptr) if (test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) ipoib_open(dev); else { - down(&pkey_sem); + mutex_lock(&pkey_mutex); if (!test_bit(IPOIB_PKEY_STOP, &priv->flags)) queue_delayed_work(ipoib_workqueue, &priv->pkey_task, HZ); - up(&pkey_sem); + mutex_unlock(&pkey_mutex); } } @@ -670,12 +670,12 @@ int ipoib_pkey_dev_delay_open(struct net_device *dev) /* P_Key value not assigned yet - start polling */ if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) { - down(&pkey_sem); + mutex_lock(&pkey_mutex); clear_bit(IPOIB_PKEY_STOP, &priv->flags); queue_delayed_work(ipoib_workqueue, &priv->pkey_task, HZ); - up(&pkey_sem); + mutex_unlock(&pkey_mutex); return 1; } diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 780009c7eaa..fd3f5c862a5 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -105,7 +105,7 @@ int ipoib_open(struct net_device *dev) struct ipoib_dev_priv *cpriv; /* Bring up any child interfaces too */ - down(&priv->vlan_mutex); + mutex_lock(&priv->vlan_mutex); list_for_each_entry(cpriv, &priv->child_intfs, list) { int flags; @@ -115,7 +115,7 @@ int ipoib_open(struct net_device *dev) dev_change_flags(cpriv->dev, flags | IFF_UP); } - up(&priv->vlan_mutex); + mutex_unlock(&priv->vlan_mutex); } netif_start_queue(dev); @@ -140,7 +140,7 @@ static int ipoib_stop(struct net_device *dev) struct ipoib_dev_priv *cpriv; /* Bring down any child interfaces too */ - down(&priv->vlan_mutex); + mutex_lock(&priv->vlan_mutex); list_for_each_entry(cpriv, &priv->child_intfs, list) { int flags; @@ -150,7 +150,7 @@ static int ipoib_stop(struct net_device *dev) dev_change_flags(cpriv->dev, flags & ~IFF_UP); } - up(&priv->vlan_mutex); + mutex_unlock(&priv->vlan_mutex); } return 0; @@ -892,8 +892,8 @@ static void ipoib_setup(struct net_device *dev) spin_lock_init(&priv->lock); spin_lock_init(&priv->tx_lock); - init_MUTEX(&priv->mcast_mutex); - init_MUTEX(&priv->vlan_mutex); + mutex_init(&priv->mcast_mutex); + mutex_init(&priv->vlan_mutex); INIT_LIST_HEAD(&priv->path_list); INIT_LIST_HEAD(&priv->child_intfs); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 7403bac1977..98039da0caf 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -55,7 +55,7 @@ MODULE_PARM_DESC(mcast_debug_level, "Enable multicast debug tracing if > 0"); #endif -static DECLARE_MUTEX(mcast_mutex); +static DEFINE_MUTEX(mcast_mutex); /* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */ struct ipoib_mcast { @@ -385,10 +385,10 @@ static void ipoib_mcast_join_complete(int status, if (!status && !ipoib_mcast_join_finish(mcast, mcmember)) { mcast->backoff = 1; - down(&mcast_mutex); + mutex_lock(&mcast_mutex); if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) queue_work(ipoib_workqueue, &priv->mcast_task); - up(&mcast_mutex); + mutex_unlock(&mcast_mutex); complete(&mcast->done); return; } @@ -418,7 +418,7 @@ static void ipoib_mcast_join_complete(int status, mcast->query = NULL; - down(&mcast_mutex); + mutex_lock(&mcast_mutex); if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) { if (status == -ETIMEDOUT) queue_work(ipoib_workqueue, &priv->mcast_task); @@ -427,7 +427,7 @@ static void ipoib_mcast_join_complete(int status, mcast->backoff * HZ); } else complete(&mcast->done); - up(&mcast_mutex); + mutex_unlock(&mcast_mutex); return; } @@ -482,12 +482,12 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast, if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS) mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS; - down(&mcast_mutex); + mutex_lock(&mcast_mutex); if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) queue_delayed_work(ipoib_workqueue, &priv->mcast_task, mcast->backoff * HZ); - up(&mcast_mutex); + mutex_unlock(&mcast_mutex); } else mcast->query_id = ret; } @@ -520,11 +520,11 @@ void ipoib_mcast_join_task(void *dev_ptr) priv->broadcast = ipoib_mcast_alloc(dev, 1); if (!priv->broadcast) { ipoib_warn(priv, "failed to allocate broadcast group\n"); - down(&mcast_mutex); + mutex_lock(&mcast_mutex); if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) queue_delayed_work(ipoib_workqueue, &priv->mcast_task, HZ); - up(&mcast_mutex); + mutex_unlock(&mcast_mutex); return; } @@ -580,10 +580,10 @@ int ipoib_mcast_start_thread(struct net_device *dev) ipoib_dbg_mcast(priv, "starting multicast thread\n"); - down(&mcast_mutex); + mutex_lock(&mcast_mutex); if (!test_and_set_bit(IPOIB_MCAST_RUN, &priv->flags)) queue_work(ipoib_workqueue, &priv->mcast_task); - up(&mcast_mutex); + mutex_unlock(&mcast_mutex); return 0; } @@ -595,10 +595,10 @@ int ipoib_mcast_stop_thread(struct net_device *dev, int flush) ipoib_dbg_mcast(priv, "stopping multicast thread\n"); - down(&mcast_mutex); + mutex_lock(&mcast_mutex); clear_bit(IPOIB_MCAST_RUN, &priv->flags); cancel_delayed_work(&priv->mcast_task); - up(&mcast_mutex); + mutex_unlock(&mcast_mutex); if (flush) flush_workqueue(ipoib_workqueue); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c index e829e10400e..faaf10e5fc7 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c @@ -65,9 +65,9 @@ int ipoib_mcast_attach(struct net_device *dev, u16 mlid, union ib_gid *mgid) } /* attach QP to multicast group */ - down(&priv->mcast_mutex); + mutex_lock(&priv->mcast_mutex); ret = ib_attach_mcast(priv->qp, mgid, mlid); - up(&priv->mcast_mutex); + mutex_unlock(&priv->mcast_mutex); if (ret) ipoib_warn(priv, "failed to attach to multicast group, ret = %d\n", ret); @@ -81,9 +81,9 @@ int ipoib_mcast_detach(struct net_device *dev, u16 mlid, union ib_gid *mgid) struct ipoib_dev_priv *priv = netdev_priv(dev); int ret; - down(&priv->mcast_mutex); + mutex_lock(&priv->mcast_mutex); ret = ib_detach_mcast(priv->qp, mgid, mlid); - up(&priv->mcast_mutex); + mutex_unlock(&priv->mcast_mutex); if (ret) ipoib_warn(priv, "ib_detach_mcast failed (result = %d)\n", ret); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c index d280b341a37..4ca175553f9 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c @@ -63,7 +63,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) ppriv = netdev_priv(pdev); - down(&ppriv->vlan_mutex); + mutex_lock(&ppriv->vlan_mutex); /* * First ensure this isn't a duplicate. We check the parent device and @@ -124,7 +124,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) list_add_tail(&priv->list, &ppriv->child_intfs); - up(&ppriv->vlan_mutex); + mutex_unlock(&ppriv->vlan_mutex); return 0; @@ -139,7 +139,7 @@ device_init_failed: free_netdev(priv->dev); err: - up(&ppriv->vlan_mutex); + mutex_unlock(&ppriv->vlan_mutex); return result; } @@ -153,7 +153,7 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey) ppriv = netdev_priv(pdev); - down(&ppriv->vlan_mutex); + mutex_lock(&ppriv->vlan_mutex); list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) { if (priv->pkey == pkey) { unregister_netdev(priv->dev); @@ -167,7 +167,7 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey) break; } } - up(&ppriv->vlan_mutex); + mutex_unlock(&ppriv->vlan_mutex); return ret; } -- GitLab From d50f5c5ca0c3426669fbe11ad4d5708d333eb9fb Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Fri, 13 Jan 2006 23:46:38 +0100 Subject: [PATCH 144/465] [IA64] build broken for ia64 simserial.c TTY layer buffering revamp broke ia64 in commit 33f0f88f1c51ae5c2d593d26960c760ea154c2e2 CC arch/ia64/hp/sim/simserial.o arch/ia64/hp/sim/simserial.c: In function `receive_chars': arch/ia64/hp/sim/simserial.c:170: error: structure has no member named `flip' ... and so on ... make[1]: *** [arch/ia64/hp/sim/simserial.o] Error 1 Patch from Andreas Schwab. Signed-off-by: Tony Luck --- arch/ia64/hp/sim/simserial.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index a346e1833bf..27f23fa5ca1 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -167,15 +167,9 @@ static void receive_chars(struct tty_struct *tty, struct pt_regs *regs) } } seen_esc = 0; - if (tty->flip.count >= TTY_FLIPBUF_SIZE) break; - *tty->flip.char_buf_ptr = ch; - - *tty->flip.flag_buf_ptr = 0; - - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; + if (tty_insert_flip_char(tty, ch, TTY_NORMAL) == 0) + break; } tty_flip_buffer_push(tty); } -- GitLab From 80f15dc703b3677d0b025bafd215f1f3664c8978 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 14 Jan 2006 10:11:39 +1100 Subject: [PATCH 145/465] powerpc: Provide a suitable AT_PLATFORM value The glibc folks want to use AT_PLATFORM to select between possible alternative versions of shared libraries. This commit makes the kernel supply an AT_PLATFORM string that indicates what class of processor we are running on. Processors with the same set of user-level instructions and roughly the same instruction scheduling characteristics are given the same AT_PLATFORM value; for example, 821, 823 and 860 are all reported as "ppc823", and 7447, 7447A, 7448, 7450, 7451, 7455 are all called "ppc7450". The intention is that the AT_PLATFORM values match the values that gcc accepts for the -mcpu= option. For values which are numeric (e.g. -mcpu=750), "ppc" has been prepended. This also adds a PPC_FEATURE_BOOKE bit to the AT_HWCAP value and sets it for the 440 family and the Freescale 85xx family. Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/cputable.c | 172 ++++++++++++++++++++++++--------- include/asm-powerpc/cputable.h | 4 + include/asm-powerpc/elf.h | 16 ++- 3 files changed, 139 insertions(+), 53 deletions(-) diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 43c74a6b07b..cf1eea1a229 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -55,7 +55,8 @@ extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); #define COMMON_USER_POWER4 (COMMON_USER_PPC64 | PPC_FEATURE_POWER4) #define COMMON_USER_POWER5 (COMMON_USER_PPC64 | PPC_FEATURE_POWER5) #define COMMON_USER_POWER5_PLUS (COMMON_USER_PPC64 | PPC_FEATURE_POWER5_PLUS) - +#define COMMON_USER_BOOKE (PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \ + PPC_FEATURE_BOOKE) /* We only set the spe features if the kernel was compiled with * spe support @@ -80,6 +81,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/power3", .oprofile_type = RS64, + .platform = "power3", }, { /* Power3+ */ .pvr_mask = 0xffff0000, @@ -93,6 +95,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/power3", .oprofile_type = RS64, + .platform = "power3", }, { /* Northstar */ .pvr_mask = 0xffff0000, @@ -106,6 +109,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/rs64", .oprofile_type = RS64, + .platform = "rs64", }, { /* Pulsar */ .pvr_mask = 0xffff0000, @@ -119,6 +123,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/rs64", .oprofile_type = RS64, + .platform = "rs64", }, { /* I-star */ .pvr_mask = 0xffff0000, @@ -132,6 +137,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/rs64", .oprofile_type = RS64, + .platform = "rs64", }, { /* S-star */ .pvr_mask = 0xffff0000, @@ -145,6 +151,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/rs64", .oprofile_type = RS64, + .platform = "rs64", }, { /* Power4 */ .pvr_mask = 0xffff0000, @@ -158,6 +165,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power4", .oprofile_type = POWER4, + .platform = "power4", }, { /* Power4+ */ .pvr_mask = 0xffff0000, @@ -171,6 +179,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power4", .oprofile_type = POWER4, + .platform = "power4", }, { /* PPC970 */ .pvr_mask = 0xffff0000, @@ -185,6 +194,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_ppc970, .oprofile_cpu_type = "ppc64/970", .oprofile_type = POWER4, + .platform = "ppc970", }, #endif /* CONFIG_PPC64 */ #if defined(CONFIG_PPC64) || defined(CONFIG_POWER4) @@ -205,6 +215,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_ppc970, .oprofile_cpu_type = "ppc64/970", .oprofile_type = POWER4, + .platform = "ppc970", }, #endif /* defined(CONFIG_PPC64) || defined(CONFIG_POWER4) */ #ifdef CONFIG_PPC64 @@ -220,6 +231,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_ppc970, .oprofile_cpu_type = "ppc64/970", .oprofile_type = POWER4, + .platform = "ppc970", }, { /* Power5 GR */ .pvr_mask = 0xffff0000, @@ -233,6 +245,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power5", .oprofile_type = POWER4, + .platform = "power5", }, { /* Power5 GS */ .pvr_mask = 0xffff0000, @@ -246,6 +259,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power5+", .oprofile_type = POWER4, + .platform = "power5+", }, { /* Cell Broadband Engine */ .pvr_mask = 0xffff0000, @@ -257,6 +271,7 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 128, .dcache_bsize = 128, .cpu_setup = __setup_cpu_be, + .platform = "ppc-cell-be", }, { /* default match */ .pvr_mask = 0x00000000, @@ -268,6 +283,7 @@ struct cpu_spec cpu_specs[] = { .dcache_bsize = 128, .num_pmcs = 6, .cpu_setup = __setup_cpu_power4, + .platform = "power4", } #endif /* CONFIG_PPC64 */ #ifdef CONFIG_PPC32 @@ -281,6 +297,7 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_UNIFIED_CACHE | PPC_FEATURE_NO_TB, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc601", }, { /* 603 */ .pvr_mask = 0xffff0000, @@ -290,7 +307,8 @@ struct cpu_spec cpu_specs[] = { .cpu_user_features = COMMON_USER, .icache_bsize = 32, .dcache_bsize = 32, - .cpu_setup = __setup_cpu_603 + .cpu_setup = __setup_cpu_603, + .platform = "ppc603", }, { /* 603e */ .pvr_mask = 0xffff0000, @@ -300,7 +318,8 @@ struct cpu_spec cpu_specs[] = { .cpu_user_features = COMMON_USER, .icache_bsize = 32, .dcache_bsize = 32, - .cpu_setup = __setup_cpu_603 + .cpu_setup = __setup_cpu_603, + .platform = "ppc603", }, { /* 603ev */ .pvr_mask = 0xffff0000, @@ -310,7 +329,8 @@ struct cpu_spec cpu_specs[] = { .cpu_user_features = COMMON_USER, .icache_bsize = 32, .dcache_bsize = 32, - .cpu_setup = __setup_cpu_603 + .cpu_setup = __setup_cpu_603, + .platform = "ppc603", }, { /* 604 */ .pvr_mask = 0xffff0000, @@ -321,7 +341,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 2, - .cpu_setup = __setup_cpu_604 + .cpu_setup = __setup_cpu_604, + .platform = "ppc604", }, { /* 604e */ .pvr_mask = 0xfffff000, @@ -332,7 +353,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_604 + .cpu_setup = __setup_cpu_604, + .platform = "ppc604", }, { /* 604r */ .pvr_mask = 0xffff0000, @@ -343,7 +365,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_604 + .cpu_setup = __setup_cpu_604, + .platform = "ppc604", }, { /* 604ev */ .pvr_mask = 0xffff0000, @@ -354,7 +377,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_604 + .cpu_setup = __setup_cpu_604, + .platform = "ppc604", }, { /* 740/750 (0x4202, don't support TAU ?) */ .pvr_mask = 0xffffffff, @@ -365,7 +389,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_750 + .cpu_setup = __setup_cpu_750, + .platform = "ppc750", }, { /* 750CX (80100 and 8010x?) */ .pvr_mask = 0xfffffff0, @@ -376,7 +401,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_750cx + .cpu_setup = __setup_cpu_750cx, + .platform = "ppc750", }, { /* 750CX (82201 and 82202) */ .pvr_mask = 0xfffffff0, @@ -387,7 +413,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_750cx + .cpu_setup = __setup_cpu_750cx, + .platform = "ppc750", }, { /* 750CXe (82214) */ .pvr_mask = 0xfffffff0, @@ -398,7 +425,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_750cx + .cpu_setup = __setup_cpu_750cx, + .platform = "ppc750", }, { /* 750CXe "Gekko" (83214) */ .pvr_mask = 0xffffffff, @@ -409,7 +437,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_750cx + .cpu_setup = __setup_cpu_750cx, + .platform = "ppc750", }, { /* 745/755 */ .pvr_mask = 0xfffff000, @@ -420,7 +449,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_750 + .cpu_setup = __setup_cpu_750, + .platform = "ppc750", }, { /* 750FX rev 1.x */ .pvr_mask = 0xffffff00, @@ -431,7 +461,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_750 + .cpu_setup = __setup_cpu_750, + .platform = "ppc750", }, { /* 750FX rev 2.0 must disable HID0[DPM] */ .pvr_mask = 0xffffffff, @@ -442,7 +473,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_750 + .cpu_setup = __setup_cpu_750, + .platform = "ppc750", }, { /* 750FX (All revs except 2.0) */ .pvr_mask = 0xffff0000, @@ -453,7 +485,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_750fx + .cpu_setup = __setup_cpu_750fx, + .platform = "ppc750", }, { /* 750GX */ .pvr_mask = 0xffff0000, @@ -464,7 +497,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_750fx + .cpu_setup = __setup_cpu_750fx, + .platform = "ppc750", }, { /* 740/750 (L2CR bit need fixup for 740) */ .pvr_mask = 0xffff0000, @@ -475,7 +509,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_750 + .cpu_setup = __setup_cpu_750, + .platform = "ppc750", }, { /* 7400 rev 1.1 ? (no TAU) */ .pvr_mask = 0xffffffff, @@ -486,7 +521,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_7400 + .cpu_setup = __setup_cpu_7400, + .platform = "ppc7400", }, { /* 7400 */ .pvr_mask = 0xffff0000, @@ -497,7 +533,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_7400 + .cpu_setup = __setup_cpu_7400, + .platform = "ppc7400", }, { /* 7410 */ .pvr_mask = 0xffff0000, @@ -508,7 +545,8 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_7410 + .cpu_setup = __setup_cpu_7410, + .platform = "ppc7400", }, { /* 7450 2.0 - no doze/nap */ .pvr_mask = 0xffffffff, @@ -522,6 +560,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", .oprofile_type = G4, + .platform = "ppc7450", }, { /* 7450 2.1 */ .pvr_mask = 0xffffffff, @@ -535,6 +574,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", .oprofile_type = G4, + .platform = "ppc7450", }, { /* 7450 2.3 and newer */ .pvr_mask = 0xffff0000, @@ -548,6 +588,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", .oprofile_type = G4, + .platform = "ppc7450", }, { /* 7455 rev 1.x */ .pvr_mask = 0xffffff00, @@ -561,6 +602,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", .oprofile_type = G4, + .platform = "ppc7450", }, { /* 7455 rev 2.0 */ .pvr_mask = 0xffffffff, @@ -574,6 +616,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", .oprofile_type = G4, + .platform = "ppc7450", }, { /* 7455 others */ .pvr_mask = 0xffff0000, @@ -587,6 +630,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", .oprofile_type = G4, + .platform = "ppc7450", }, { /* 7447/7457 Rev 1.0 */ .pvr_mask = 0xffffffff, @@ -600,6 +644,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", .oprofile_type = G4, + .platform = "ppc7450", }, { /* 7447/7457 Rev 1.1 */ .pvr_mask = 0xffffffff, @@ -613,6 +658,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", .oprofile_type = G4, + .platform = "ppc7450", }, { /* 7447/7457 Rev 1.2 and later */ .pvr_mask = 0xffff0000, @@ -626,6 +672,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", .oprofile_type = G4, + .platform = "ppc7450", }, { /* 7447A */ .pvr_mask = 0xffff0000, @@ -639,6 +686,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", .oprofile_type = G4, + .platform = "ppc7450", }, { /* 7448 */ .pvr_mask = 0xffff0000, @@ -652,6 +700,7 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", .oprofile_type = G4, + .platform = "ppc7450", }, { /* 82xx (8240, 8245, 8260 are all 603e cores) */ .pvr_mask = 0x7fff0000, @@ -661,7 +710,8 @@ struct cpu_spec cpu_specs[] = { .cpu_user_features = COMMON_USER, .icache_bsize = 32, .dcache_bsize = 32, - .cpu_setup = __setup_cpu_603 + .cpu_setup = __setup_cpu_603, + .platform = "ppc603", }, { /* All G2_LE (603e core, plus some) have the same pvr */ .pvr_mask = 0x7fff0000, @@ -671,7 +721,8 @@ struct cpu_spec cpu_specs[] = { .cpu_user_features = COMMON_USER, .icache_bsize = 32, .dcache_bsize = 32, - .cpu_setup = __setup_cpu_603 + .cpu_setup = __setup_cpu_603, + .platform = "ppc603", }, { /* e300 (a 603e core, plus some) on 83xx */ .pvr_mask = 0x7fff0000, @@ -681,7 +732,8 @@ struct cpu_spec cpu_specs[] = { .cpu_user_features = COMMON_USER, .icache_bsize = 32, .dcache_bsize = 32, - .cpu_setup = __setup_cpu_603 + .cpu_setup = __setup_cpu_603, + .platform = "ppc603", }, { /* default match, we assume split I/D cache & TB (non-601)... */ .pvr_mask = 0x00000000, @@ -691,6 +743,7 @@ struct cpu_spec cpu_specs[] = { .cpu_user_features = COMMON_USER, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc603", }, #endif /* CLASSIC_PPC */ #ifdef CONFIG_8xx @@ -704,6 +757,7 @@ struct cpu_spec cpu_specs[] = { .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 16, .dcache_bsize = 16, + .platform = "ppc823", }, #endif /* CONFIG_8xx */ #ifdef CONFIG_40x @@ -715,6 +769,7 @@ struct cpu_spec cpu_specs[] = { .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 16, .dcache_bsize = 16, + .platform = "ppc403", }, { /* 403GCX */ .pvr_mask = 0xffffff00, @@ -725,6 +780,7 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_HAS_MMU | PPC_FEATURE_NO_TB, .icache_bsize = 16, .dcache_bsize = 16, + .platform = "ppc403", }, { /* 403G ?? */ .pvr_mask = 0xffff0000, @@ -734,6 +790,7 @@ struct cpu_spec cpu_specs[] = { .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 16, .dcache_bsize = 16, + .platform = "ppc403", }, { /* 405GP */ .pvr_mask = 0xffff0000, @@ -744,6 +801,7 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc405", }, { /* STB 03xxx */ .pvr_mask = 0xffff0000, @@ -754,6 +812,7 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc405", }, { /* STB 04xxx */ .pvr_mask = 0xffff0000, @@ -764,6 +823,7 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc405", }, { /* NP405L */ .pvr_mask = 0xffff0000, @@ -774,6 +834,7 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc405", }, { /* NP4GS3 */ .pvr_mask = 0xffff0000, @@ -784,6 +845,7 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc405", }, { /* NP405H */ .pvr_mask = 0xffff0000, @@ -794,6 +856,7 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc405", }, { /* 405GPr */ .pvr_mask = 0xffff0000, @@ -804,6 +867,7 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc405", }, { /* STBx25xx */ .pvr_mask = 0xffff0000, @@ -814,6 +878,7 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc405", }, { /* 405LP */ .pvr_mask = 0xffff0000, @@ -823,6 +888,7 @@ struct cpu_spec cpu_specs[] = { .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc405", }, { /* Xilinx Virtex-II Pro */ .pvr_mask = 0xffff0000, @@ -833,6 +899,7 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc405", }, { /* 405EP */ .pvr_mask = 0xffff0000, @@ -843,6 +910,7 @@ struct cpu_spec cpu_specs[] = { PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc405", }, #endif /* CONFIG_40x */ @@ -852,81 +920,90 @@ struct cpu_spec cpu_specs[] = { .pvr_value = 0x40000850, .cpu_name = "440EP Rev. A", .cpu_features = CPU_FTRS_44X, - .cpu_user_features = COMMON_USER, /* 440EP has an FPU */ + .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc440", }, { .pvr_mask = 0xf0000fff, .pvr_value = 0x400008d3, .cpu_name = "440EP Rev. B", .cpu_features = CPU_FTRS_44X, - .cpu_user_features = COMMON_USER, /* 440EP has an FPU */ + .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc440", }, { /* 440GP Rev. B */ .pvr_mask = 0xf0000fff, .pvr_value = 0x40000440, .cpu_name = "440GP Rev. B", .cpu_features = CPU_FTRS_44X, - .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .cpu_user_features = COMMON_USER_BOOKE, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc440gp", }, { /* 440GP Rev. C */ .pvr_mask = 0xf0000fff, .pvr_value = 0x40000481, .cpu_name = "440GP Rev. C", .cpu_features = CPU_FTRS_44X, - .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .cpu_user_features = COMMON_USER_BOOKE, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc440gp", }, { /* 440GX Rev. A */ .pvr_mask = 0xf0000fff, .pvr_value = 0x50000850, .cpu_name = "440GX Rev. A", .cpu_features = CPU_FTRS_44X, - .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .cpu_user_features = COMMON_USER_BOOKE, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc440", }, { /* 440GX Rev. B */ .pvr_mask = 0xf0000fff, .pvr_value = 0x50000851, .cpu_name = "440GX Rev. B", .cpu_features = CPU_FTRS_44X, - .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .cpu_user_features = COMMON_USER_BOOKE, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc440", }, { /* 440GX Rev. C */ .pvr_mask = 0xf0000fff, .pvr_value = 0x50000892, .cpu_name = "440GX Rev. C", .cpu_features = CPU_FTRS_44X, - .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .cpu_user_features = COMMON_USER_BOOKE, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc440", }, { /* 440GX Rev. F */ .pvr_mask = 0xf0000fff, .pvr_value = 0x50000894, .cpu_name = "440GX Rev. F", .cpu_features = CPU_FTRS_44X, - .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .cpu_user_features = COMMON_USER_BOOKE, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc440", }, { /* 440SP Rev. A */ .pvr_mask = 0xff000fff, .pvr_value = 0x53000891, .cpu_name = "440SP Rev. A", .cpu_features = CPU_FTRS_44X, - .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .cpu_user_features = COMMON_USER_BOOKE, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc440", }, { /* 440SPe Rev. A */ .pvr_mask = 0xff000fff, @@ -934,9 +1011,10 @@ struct cpu_spec cpu_specs[] = { .cpu_name = "440SPe Rev. A", .cpu_features = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, - .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .cpu_user_features = COMMON_USER_BOOKE, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "ppc440", }, #endif /* CONFIG_44x */ #ifdef CONFIG_FSL_BOOKE @@ -946,10 +1024,11 @@ struct cpu_spec cpu_specs[] = { .cpu_name = "e200z5", /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ .cpu_features = CPU_FTRS_E200, - .cpu_user_features = PPC_FEATURE_32 | - PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_EFP_SINGLE | + .cpu_user_features = COMMON_USER_BOOKE | + PPC_FEATURE_HAS_EFP_SINGLE | PPC_FEATURE_UNIFIED_CACHE, .dcache_bsize = 32, + .platform = "ppc5554", }, { /* e200z6 */ .pvr_mask = 0xfff00000, @@ -957,11 +1036,12 @@ struct cpu_spec cpu_specs[] = { .cpu_name = "e200z6", /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ .cpu_features = CPU_FTRS_E200, - .cpu_user_features = PPC_FEATURE_32 | - PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP | + .cpu_user_features = COMMON_USER_BOOKE | + PPC_FEATURE_SPE_COMP | PPC_FEATURE_HAS_EFP_SINGLE | PPC_FEATURE_UNIFIED_CACHE, .dcache_bsize = 32, + .platform = "ppc5554", }, { /* e500 */ .pvr_mask = 0xffff0000, @@ -969,14 +1049,15 @@ struct cpu_spec cpu_specs[] = { .cpu_name = "e500", /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ .cpu_features = CPU_FTRS_E500, - .cpu_user_features = PPC_FEATURE_32 | - PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP | + .cpu_user_features = COMMON_USER_BOOKE | + PPC_FEATURE_SPE_COMP | PPC_FEATURE_HAS_EFP_SINGLE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, .oprofile_cpu_type = "ppc/e500", .oprofile_type = BOOKE, + .platform = "ppc8540", }, { /* e500v2 */ .pvr_mask = 0xffff0000, @@ -984,14 +1065,16 @@ struct cpu_spec cpu_specs[] = { .cpu_name = "e500v2", /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ .cpu_features = CPU_FTRS_E500_2, - .cpu_user_features = PPC_FEATURE_32 | - PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP | - PPC_FEATURE_HAS_EFP_SINGLE | PPC_FEATURE_HAS_EFP_DOUBLE, + .cpu_user_features = COMMON_USER_BOOKE | + PPC_FEATURE_SPE_COMP | + PPC_FEATURE_HAS_EFP_SINGLE | + PPC_FEATURE_HAS_EFP_DOUBLE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, .oprofile_cpu_type = "ppc/e500", .oprofile_type = BOOKE, + .platform = "ppc8548", }, #endif #if !CLASSIC_PPC @@ -1003,6 +1086,7 @@ struct cpu_spec cpu_specs[] = { .cpu_user_features = PPC_FEATURE_32, .icache_bsize = 32, .dcache_bsize = 32, + .platform = "powerpc", } #endif /* !CLASSIC_PPC */ #endif /* CONFIG_PPC32 */ diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index ef6ead34a77..03017d90570 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -19,6 +19,7 @@ #define PPC_FEATURE_POWER5 0x00040000 #define PPC_FEATURE_POWER5_PLUS 0x00020000 #define PPC_FEATURE_CELL 0x00010000 +#define PPC_FEATURE_BOOKE 0x00008000 #ifdef __KERNEL__ #ifndef __ASSEMBLY__ @@ -64,6 +65,9 @@ struct cpu_spec { /* Processor specific oprofile operations */ enum powerpc_oprofile_type oprofile_type; + + /* Name of processor class, for the ELF AT_PLATFORM entry */ + char *platform; }; extern struct cpu_spec *cur_cpu_spec; diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h index 45f2af6f89c..94d228f9c6a 100644 --- a/include/asm-powerpc/elf.h +++ b/include/asm-powerpc/elf.h @@ -221,20 +221,18 @@ extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *); instruction set this cpu supports. This could be done in userspace, but it's not easy, and we've already done it here. */ # define ELF_HWCAP (cur_cpu_spec->cpu_user_features) -#ifdef __powerpc64__ -# define ELF_PLAT_INIT(_r, load_addr) do { \ - _r->gpr[2] = load_addr; \ -} while (0) -#endif /* __powerpc64__ */ /* This yields a string that ld.so will use to load implementation specific libraries for optimization. This is more specific in - intent than poking at uname or /proc/cpuinfo. + intent than poking at uname or /proc/cpuinfo. */ - For the moment, we have only optimizations for the Intel generations, - but that could change... */ +#define ELF_PLATFORM (cur_cpu_spec->platform) -#define ELF_PLATFORM (NULL) +#ifdef __powerpc64__ +# define ELF_PLAT_INIT(_r, load_addr) do { \ + _r->gpr[2] = load_addr; \ +} while (0) +#endif /* __powerpc64__ */ #ifdef __KERNEL__ -- GitLab From 7a45fb19cef93574230827e6e2c97ad5760ddecd Mon Sep 17 00:00:00 2001 From: Andy Whitcroft Date: Fri, 13 Jan 2006 12:35:49 +0000 Subject: [PATCH 146/465] [PATCH] powerpc: oprofile cpu type names clash with other code In 2.6.15-git6 a change was commited in the oprofile support in the powerpc architecture. It introduced the powerpc_oprofile_type which contains the define G4. This causes a name clash with the existing wacom usb tablet driver. CC [M] drivers/usb/input/wacom.o drivers/usb/input/wacom.c:98: error: conflicting types for `G4' include/asm/cputable.h:37: error: previous declaration of `G4' CC [M] drivers/usb/mon/mon_text.o make[3]: *** [drivers/usb/input/wacom.o] Error 1 make[2]: *** [drivers/usb/input] Error 2 The elements of an enum declared in global scope are effectivly global identifiers themselves. As such we need to ensure the names are unique. This patch updates the later oprofile support to use unique names. Signed-off-by: Andy Whitcroft Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/cputable.c | 52 +++++++++++++++++----------------- arch/powerpc/oprofile/common.c | 8 +++--- include/asm-powerpc/cputable.h | 10 +++---- 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index cf1eea1a229..10696456a4c 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -80,7 +80,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/power3", - .oprofile_type = RS64, + .oprofile_type = PPC_OPROFILE_RS64, .platform = "power3", }, { /* Power3+ */ @@ -94,7 +94,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/power3", - .oprofile_type = RS64, + .oprofile_type = PPC_OPROFILE_RS64, .platform = "power3", }, { /* Northstar */ @@ -108,7 +108,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/rs64", - .oprofile_type = RS64, + .oprofile_type = PPC_OPROFILE_RS64, .platform = "rs64", }, { /* Pulsar */ @@ -122,7 +122,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/rs64", - .oprofile_type = RS64, + .oprofile_type = PPC_OPROFILE_RS64, .platform = "rs64", }, { /* I-star */ @@ -136,7 +136,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/rs64", - .oprofile_type = RS64, + .oprofile_type = PPC_OPROFILE_RS64, .platform = "rs64", }, { /* S-star */ @@ -150,7 +150,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 8, .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/rs64", - .oprofile_type = RS64, + .oprofile_type = PPC_OPROFILE_RS64, .platform = "rs64", }, { /* Power4 */ @@ -164,7 +164,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 8, .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power4", - .oprofile_type = POWER4, + .oprofile_type = PPC_OPROFILE_POWER4, .platform = "power4", }, { /* Power4+ */ @@ -178,7 +178,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 8, .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power4", - .oprofile_type = POWER4, + .oprofile_type = PPC_OPROFILE_POWER4, .platform = "power4", }, { /* PPC970 */ @@ -193,7 +193,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 8, .cpu_setup = __setup_cpu_ppc970, .oprofile_cpu_type = "ppc64/970", - .oprofile_type = POWER4, + .oprofile_type = PPC_OPROFILE_POWER4, .platform = "ppc970", }, #endif /* CONFIG_PPC64 */ @@ -214,7 +214,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 8, .cpu_setup = __setup_cpu_ppc970, .oprofile_cpu_type = "ppc64/970", - .oprofile_type = POWER4, + .oprofile_type = PPC_OPROFILE_POWER4, .platform = "ppc970", }, #endif /* defined(CONFIG_PPC64) || defined(CONFIG_POWER4) */ @@ -230,7 +230,7 @@ struct cpu_spec cpu_specs[] = { .dcache_bsize = 128, .cpu_setup = __setup_cpu_ppc970, .oprofile_cpu_type = "ppc64/970", - .oprofile_type = POWER4, + .oprofile_type = PPC_OPROFILE_POWER4, .platform = "ppc970", }, { /* Power5 GR */ @@ -244,7 +244,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power5", - .oprofile_type = POWER4, + .oprofile_type = PPC_OPROFILE_POWER4, .platform = "power5", }, { /* Power5 GS */ @@ -258,7 +258,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power5+", - .oprofile_type = POWER4, + .oprofile_type = PPC_OPROFILE_POWER4, .platform = "power5+", }, { /* Cell Broadband Engine */ @@ -559,7 +559,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", - .oprofile_type = G4, + .oprofile_type = PPC_OPROFILE_G4, .platform = "ppc7450", }, { /* 7450 2.1 */ @@ -573,7 +573,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", - .oprofile_type = G4, + .oprofile_type = PPC_OPROFILE_G4, .platform = "ppc7450", }, { /* 7450 2.3 and newer */ @@ -587,7 +587,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", - .oprofile_type = G4, + .oprofile_type = PPC_OPROFILE_G4, .platform = "ppc7450", }, { /* 7455 rev 1.x */ @@ -601,7 +601,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", - .oprofile_type = G4, + .oprofile_type = PPC_OPROFILE_G4, .platform = "ppc7450", }, { /* 7455 rev 2.0 */ @@ -615,7 +615,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", - .oprofile_type = G4, + .oprofile_type = PPC_OPROFILE_G4, .platform = "ppc7450", }, { /* 7455 others */ @@ -629,7 +629,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", - .oprofile_type = G4, + .oprofile_type = PPC_OPROFILE_G4, .platform = "ppc7450", }, { /* 7447/7457 Rev 1.0 */ @@ -643,7 +643,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", - .oprofile_type = G4, + .oprofile_type = PPC_OPROFILE_G4, .platform = "ppc7450", }, { /* 7447/7457 Rev 1.1 */ @@ -657,7 +657,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", - .oprofile_type = G4, + .oprofile_type = PPC_OPROFILE_G4, .platform = "ppc7450", }, { /* 7447/7457 Rev 1.2 and later */ @@ -671,7 +671,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", - .oprofile_type = G4, + .oprofile_type = PPC_OPROFILE_G4, .platform = "ppc7450", }, { /* 7447A */ @@ -685,7 +685,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", - .oprofile_type = G4, + .oprofile_type = PPC_OPROFILE_G4, .platform = "ppc7450", }, { /* 7448 */ @@ -699,7 +699,7 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .cpu_setup = __setup_cpu_745x, .oprofile_cpu_type = "ppc/7450", - .oprofile_type = G4, + .oprofile_type = PPC_OPROFILE_G4, .platform = "ppc7450", }, { /* 82xx (8240, 8245, 8260 are all 603e cores) */ @@ -1056,7 +1056,7 @@ struct cpu_spec cpu_specs[] = { .dcache_bsize = 32, .num_pmcs = 4, .oprofile_cpu_type = "ppc/e500", - .oprofile_type = BOOKE, + .oprofile_type = PPC_OPROFILE_BOOKE, .platform = "ppc8540", }, { /* e500v2 */ @@ -1073,7 +1073,7 @@ struct cpu_spec cpu_specs[] = { .dcache_bsize = 32, .num_pmcs = 4, .oprofile_cpu_type = "ppc/e500", - .oprofile_type = BOOKE, + .oprofile_type = PPC_OPROFILE_BOOKE, .platform = "ppc8548", }, #endif diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c index 71615eb70b2..cc2535be3a7 100644 --- a/arch/powerpc/oprofile/common.c +++ b/arch/powerpc/oprofile/common.c @@ -140,19 +140,19 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) switch (cur_cpu_spec->oprofile_type) { #ifdef CONFIG_PPC64 - case RS64: + case PPC_OPROFILE_RS64: model = &op_model_rs64; break; - case POWER4: + case PPC_OPROFILE_POWER4: model = &op_model_power4; break; #else - case G4: + case PPC_OPROFILE_G4: model = &op_model_7450; break; #endif #ifdef CONFIG_FSL_BOOKE - case BOOKE: + case PPC_OPROFILE_BOOKE: model = &op_model_fsl_booke; break; #endif diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index 03017d90570..64210549f56 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -32,11 +32,11 @@ struct cpu_spec; typedef void (*cpu_setup_t)(unsigned long offset, struct cpu_spec* spec); enum powerpc_oprofile_type { - INVALID = 0, - RS64 = 1, - POWER4 = 2, - G4 = 3, - BOOKE = 4, + PPC_OPROFILE_INVALID = 0, + PPC_OPROFILE_RS64 = 1, + PPC_OPROFILE_POWER4 = 2, + PPC_OPROFILE_G4 = 3, + PPC_OPROFILE_BOOKE = 4, }; struct cpu_spec { -- GitLab From b8e383d592daaa35c944a9083ee92c995dce66ca Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Fri, 13 Jan 2006 10:15:17 -0600 Subject: [PATCH 147/465] [PATCH] powerpc: Allow for ppc_md restart, power_off, and halt to be NULL On a number of embedded reference boards there isn't always a way to reset, power_off, or halt the board. Rather than having each board implement a spin loop just let the generic code do it. Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/setup-common.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index d5c52fae023..be12041c0fc 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -100,7 +100,8 @@ void machine_shutdown(void) void machine_restart(char *cmd) { machine_shutdown(); - ppc_md.restart(cmd); + if (ppc_md.restart) + ppc_md.restart(cmd); #ifdef CONFIG_SMP smp_send_stop(); #endif @@ -112,7 +113,8 @@ void machine_restart(char *cmd) void machine_power_off(void) { machine_shutdown(); - ppc_md.power_off(); + if (ppc_md.power_off) + ppc_md.power_off(); #ifdef CONFIG_SMP smp_send_stop(); #endif @@ -129,7 +131,8 @@ EXPORT_SYMBOL_GPL(pm_power_off); void machine_halt(void) { machine_shutdown(); - ppc_md.halt(); + if (ppc_md.halt) + ppc_md.halt(); #ifdef CONFIG_SMP smp_send_stop(); #endif -- GitLab From eed320010872a11f5255b3d076e5b4f142af553d Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Fri, 13 Jan 2006 11:19:13 -0600 Subject: [PATCH 148/465] [PATCH] powerpc: Add FSL SOC library and setup code Parse the flat device tree for devices on Freescale SOC's that we know about (gianfar, gianfar_mdio, i2c, mpc83xx_wdt). We need to setup platform devices and platform data for these devices to match arch/ppc usage. Also add a helper function (get_immrbase) that reports the base address of the MMIO registers on the SOC. Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras --- arch/powerpc/sysdev/Makefile | 1 + arch/powerpc/sysdev/fsl_soc.c | 317 ++++++++++++++++++++++++++++++++++ arch/powerpc/sysdev/fsl_soc.h | 8 + 3 files changed, 326 insertions(+) create mode 100644 arch/powerpc/sysdev/fsl_soc.c create mode 100644 arch/powerpc/sysdev/fsl_soc.h diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 0ae841347a0..4c2b356774e 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_40x) += dcr.o obj-$(CONFIG_U3_DART) += dart_iommu.o obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o obj-$(CONFIG_PPC_83xx) += ipic.o +obj-$(CONFIG_FSL_SOC) += fsl_soc.o diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c new file mode 100644 index 00000000000..064c9de4773 --- /dev/null +++ b/arch/powerpc/sysdev/fsl_soc.c @@ -0,0 +1,317 @@ +/* + * FSL SoC setup code + * + * Maintained by Kumar Gala (see MAINTAINERS for contact information) + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +static phys_addr_t immrbase = -1; + +phys_addr_t get_immrbase(void) +{ + struct device_node *soc; + + if (immrbase != -1) + return immrbase; + + soc = of_find_node_by_type(NULL, "soc"); + if (soc != 0) { + unsigned int size; + void *prop = get_property(soc, "reg", &size); + immrbase = of_translate_address(soc, prop); + of_node_put(soc); + }; + + return immrbase; +} +EXPORT_SYMBOL(get_immrbase); + +static const char * gfar_tx_intr = "tx"; +static const char * gfar_rx_intr = "rx"; +static const char * gfar_err_intr = "error"; + +static int __init gfar_of_init(void) +{ + struct device_node *np; + unsigned int i; + struct platform_device *mdio_dev, *gfar_dev; + struct resource res; + int ret; + + for (np = NULL, i = 0; (np = of_find_compatible_node(np, "mdio", "gianfar")) != NULL; i++) { + int k; + struct device_node *child = NULL; + struct gianfar_mdio_data mdio_data; + + memset(&res, 0, sizeof(res)); + memset(&mdio_data, 0, sizeof(mdio_data)); + + ret = of_address_to_resource(np, 0, &res); + if (ret) + goto mdio_err; + + mdio_dev = platform_device_register_simple("fsl-gianfar_mdio", res.start, &res, 1); + if (IS_ERR(mdio_dev)) { + ret = PTR_ERR(mdio_dev); + goto mdio_err; + } + + for (k = 0; k < 32; k++) + mdio_data.irq[k] = -1; + + while ((child = of_get_next_child(np, child)) != NULL) { + if (child->n_intrs) { + u32 *id = (u32 *) get_property(child, "reg", NULL); + mdio_data.irq[*id] = child->intrs[0].line; + } + } + + ret = platform_device_add_data(mdio_dev, &mdio_data, sizeof(struct gianfar_mdio_data)); + if (ret) + goto mdio_unreg; + } + + for (np = NULL, i = 0; (np = of_find_compatible_node(np, "network", "gianfar")) != NULL; i++) { + struct resource r[4]; + struct device_node *phy, *mdio; + struct gianfar_platform_data gfar_data; + unsigned int *id; + char *model; + void *mac_addr; + phandle *ph; + + memset(r, 0, sizeof(r)); + memset(&gfar_data, 0, sizeof(gfar_data)); + + ret = of_address_to_resource(np, 0, &r[0]); + if (ret) + goto gfar_err; + + r[1].start = np->intrs[0].line; + r[1].end = np->intrs[0].line; + r[1].flags = IORESOURCE_IRQ; + + model = get_property(np, "model", NULL); + + /* If we aren't the FEC we have multiple interrupts */ + if (model && strcasecmp(model, "FEC")) { + r[1].name = gfar_tx_intr; + + r[2].name = gfar_rx_intr; + r[2].start = np->intrs[1].line; + r[2].end = np->intrs[1].line; + r[2].flags = IORESOURCE_IRQ; + + r[3].name = gfar_err_intr; + r[3].start = np->intrs[2].line; + r[3].end = np->intrs[2].line; + r[3].flags = IORESOURCE_IRQ; + } + + gfar_dev = platform_device_register_simple("fsl-gianfar", i, &r[0], np->n_intrs + 1); + + if (IS_ERR(gfar_dev)) { + ret = PTR_ERR(gfar_dev); + goto gfar_err; + } + + mac_addr = get_property(np, "address", NULL); + memcpy(gfar_data.mac_addr, mac_addr, 6); + + if (model && !strcasecmp(model, "TSEC")) + gfar_data.device_flags = + FSL_GIANFAR_DEV_HAS_GIGABIT | + FSL_GIANFAR_DEV_HAS_COALESCE | + FSL_GIANFAR_DEV_HAS_RMON | + FSL_GIANFAR_DEV_HAS_MULTI_INTR; + if (model && !strcasecmp(model, "eTSEC")) + gfar_data.device_flags = + FSL_GIANFAR_DEV_HAS_GIGABIT | + FSL_GIANFAR_DEV_HAS_COALESCE | + FSL_GIANFAR_DEV_HAS_RMON | + FSL_GIANFAR_DEV_HAS_MULTI_INTR | + FSL_GIANFAR_DEV_HAS_CSUM | + FSL_GIANFAR_DEV_HAS_VLAN | + FSL_GIANFAR_DEV_HAS_EXTENDED_HASH; + + ph = (phandle *) get_property(np, "phy-handle", NULL); + phy = of_find_node_by_phandle(*ph); + + if (phy == NULL) { + ret = -ENODEV; + goto gfar_unreg; + } + + mdio = of_get_parent(phy); + + id = (u32 *) get_property(phy, "reg", NULL); + ret = of_address_to_resource(mdio, 0, &res); + if (ret) { + of_node_put(phy); + of_node_put(mdio); + goto gfar_unreg; + } + + gfar_data.phy_id = *id; + gfar_data.bus_id = res.start; + + of_node_put(phy); + of_node_put(mdio); + + ret = platform_device_add_data(gfar_dev, &gfar_data, sizeof(struct gianfar_platform_data)); + if (ret) + goto gfar_unreg; + } + + return 0; + +mdio_unreg: + platform_device_unregister(mdio_dev); +mdio_err: + return ret; + +gfar_unreg: + platform_device_unregister(gfar_dev); +gfar_err: + return ret; +} +arch_initcall(gfar_of_init); + +static int __init fsl_i2c_of_init(void) +{ + struct device_node *np; + unsigned int i; + struct platform_device *i2c_dev; + int ret; + + for (np = NULL, i = 0; (np = of_find_compatible_node(np, "i2c", "fsl-i2c")) != NULL; i++) { + struct resource r[2]; + struct fsl_i2c_platform_data i2c_data; + unsigned char * flags = NULL; + + memset(&r, 0, sizeof(r)); + memset(&i2c_data, 0, sizeof(i2c_data)); + + ret = of_address_to_resource(np, 0, &r[0]); + if (ret) + goto i2c_err; + + r[1].start = np->intrs[0].line; + r[1].end = np->intrs[0].line; + r[1].flags = IORESOURCE_IRQ; + + i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2); + if (IS_ERR(i2c_dev)) { + ret = PTR_ERR(i2c_dev); + goto i2c_err; + } + + i2c_data.device_flags = 0; + flags = get_property(np, "dfsrr", NULL); + if (flags) + i2c_data.device_flags |= FSL_I2C_DEV_SEPARATE_DFSRR; + + flags = get_property(np, "fsl5200-clocking", NULL); + if (flags) + i2c_data.device_flags |= FSL_I2C_DEV_CLOCK_5200; + + ret = platform_device_add_data(i2c_dev, &i2c_data, sizeof(struct fsl_i2c_platform_data)); + if (ret) + goto i2c_unreg; + } + + return 0; + +i2c_unreg: + platform_device_unregister(i2c_dev); +i2c_err: + return ret; +} +arch_initcall(fsl_i2c_of_init); + +#ifdef CONFIG_PPC_83xx +static int __init mpc83xx_wdt_init(void) +{ + struct resource r; + struct device_node *soc, *np; + struct platform_device *dev; + unsigned int *freq; + int ret; + + np = of_find_compatible_node(NULL, "watchdog", "mpc83xx_wdt"); + + if (!np) { + ret = -ENODEV; + goto mpc83xx_wdt_nodev; + } + + soc = of_find_node_by_type(NULL, "soc"); + + if (!soc) { + ret = -ENODEV; + goto mpc83xx_wdt_nosoc; + } + + freq = (unsigned int *)get_property(soc, "bus-frequency", NULL); + if (!freq) { + ret = -ENODEV; + goto mpc83xx_wdt_err; + } + + memset(&r, 0, sizeof(r)); + + ret = of_address_to_resource(np, 0, &r); + if (ret) + goto mpc83xx_wdt_err; + + dev = platform_device_register_simple("mpc83xx_wdt", 0, &r, 1); + if (IS_ERR(dev)) { + ret = PTR_ERR(dev); + goto mpc83xx_wdt_err; + } + + ret = platform_device_add_data(dev, freq, sizeof(int)); + if (ret) + goto mpc83xx_wdt_unreg; + + of_node_put(soc); + of_node_put(np); + + return 0; + +mpc83xx_wdt_unreg: + platform_device_unregister(dev); +mpc83xx_wdt_err: + of_node_put(soc); +mpc83xx_wdt_nosoc: + of_node_put(np); +mpc83xx_wdt_nodev: + return ret; +} +arch_initcall(mpc83xx_wdt_init); +#endif diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h new file mode 100644 index 00000000000..c433d3f39ed --- /dev/null +++ b/arch/powerpc/sysdev/fsl_soc.h @@ -0,0 +1,8 @@ +#ifndef __PPC_FSL_SOC_H +#define __PPC_FSL_SOC_H +#ifdef __KERNEL__ + +extern phys_addr_t get_immrbase(void); + +#endif +#endif -- GitLab From 7d13d21ae85f64e35dcdae4d6a6286e62a38e0ab Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Fri, 13 Jan 2006 11:19:58 -0600 Subject: [PATCH 149/465] [PATCH] powerpc: Add MPC834x SYS board to arch/powerpc Add the first MPC83xx board that uses a flat device tree to arch/powerpc. Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras --- arch/powerpc/configs/mpc834x_sys_defconfig | 911 +++++++++++++++++++++ arch/powerpc/kernel/ppc_ksyms.c | 3 +- arch/powerpc/platforms/83xx/Kconfig | 1 + arch/powerpc/platforms/83xx/mpc834x_sys.c | 243 ++++++ arch/powerpc/platforms/83xx/mpc834x_sys.h | 23 + arch/powerpc/platforms/83xx/mpc83xx.h | 14 + arch/powerpc/platforms/83xx/pci.c | 99 +++ 7 files changed, 1292 insertions(+), 2 deletions(-) create mode 100644 arch/powerpc/configs/mpc834x_sys_defconfig create mode 100644 arch/powerpc/platforms/83xx/mpc834x_sys.c create mode 100644 arch/powerpc/platforms/83xx/mpc834x_sys.h create mode 100644 arch/powerpc/platforms/83xx/mpc83xx.h create mode 100644 arch/powerpc/platforms/83xx/pci.c diff --git a/arch/powerpc/configs/mpc834x_sys_defconfig b/arch/powerpc/configs/mpc834x_sys_defconfig new file mode 100644 index 00000000000..3bff761965c --- /dev/null +++ b/arch/powerpc/configs/mpc834x_sys_defconfig @@ -0,0 +1,911 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.15-g461d4edf-dirty +# Fri Jan 13 11:01:47 2006 +# +# CONFIG_PPC64 is not set +CONFIG_PPC32=y +CONFIG_PPC_MERGE=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_PPC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +CONFIG_PPC_UDBG_16550=y +# CONFIG_GENERIC_TBSYNC is not set +CONFIG_DEFAULT_UIMAGE=y + +# +# Processor support +# +# CONFIG_CLASSIC32 is not set +# CONFIG_PPC_52xx is not set +# CONFIG_PPC_82xx is not set +CONFIG_PPC_83xx=y +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_8xx is not set +# CONFIG_E200 is not set +# CONFIG_E500 is not set +CONFIG_6xx=y +CONFIG_83xx=y +CONFIG_PPC_FPU=y +CONFIG_PPC_STD_MMU=y +CONFIG_PPC_STD_MMU_32=y +# CONFIG_SMP is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_EMBEDDED=y +# CONFIG_KALLSYMS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +# CONFIG_EPOLL is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_SLAB=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_KMOD is not set + +# +# Block layer +# +# CONFIG_LBD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_PPC_GEN550=y +# CONFIG_WANT_EARLY_SERIAL is not set + +# +# Platform support +# +CONFIG_MPC834x_SYS=y +CONFIG_MPC834x=y + +# +# Kernel options +# +# CONFIG_HIGHMEM is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set +# CONFIG_PM is not set +# CONFIG_SOFTWARE_SUSPEND is not set +CONFIG_SECCOMP=y +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_GENERIC_ISA_DMA=y +# CONFIG_PPC_I8259 is not set +CONFIG_PPC_INDIRECT_PCI=y +CONFIG_FSL_SOC=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +# CONFIG_PCI_LEGACY_PROC is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Advanced setup +# +# CONFIG_ADVANCED_OPTIONS is not set + +# +# Default settings for advanced configuration options are used +# +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE=0x80000000 +CONFIG_BOOT_LOAD=0x00800000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=32768 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# +# CONFIG_WINDFARM is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=y +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=y +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +CONFIG_GIANFAR=y +# CONFIG_GFAR_NAPI is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_83xx_WDT=y + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set +# CONFIG_NVRAM is not set +CONFIG_GEN_RTC=y +# CONFIG_GEN_RTC_X is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +CONFIG_I2C_MPC=y +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_SCx200_ACB is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set +# CONFIG_SENSORS_M41T00 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_RTC_X1205_I2C is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia Capabilities Port drivers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# SN Devices +# + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_MSDOS_PARTITION is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set + +# +# Instrumentation Support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_BOOTX_TEXT is not set +# CONFIG_SERIAL_TEXT_DEBUG is not set +# CONFIG_PPC_EARLY_DEBUG_LPAR is not set +# CONFIG_PPC_EARLY_DEBUG_G5 is not set +# CONFIG_PPC_EARLY_DEBUG_RTAS is not set +# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set +# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# + +# +# SEC2.x Options +# +CONFIG_MPC8349E_SEC2x=y + +# +# SEC2.x Test Options +# +CONFIG_MPC8349E_SEC2xTEST=y diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index 16d9a904f3c..d9a459c144d 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c @@ -230,8 +230,7 @@ EXPORT_SYMBOL(__down_interruptible); EXPORT_SYMBOL(cpm_install_handler); EXPORT_SYMBOL(cpm_free_handler); #endif /* CONFIG_8xx */ -#if defined(CONFIG_8xx) || defined(CONFIG_40x) || defined(CONFIG_85xx) ||\ - defined(CONFIG_83xx) +#if defined(CONFIG_8xx) || defined(CONFIG_40x) EXPORT_SYMBOL(__res); #endif diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig index b20812d460e..7675e675dce 100644 --- a/arch/powerpc/platforms/83xx/Kconfig +++ b/arch/powerpc/platforms/83xx/Kconfig @@ -7,6 +7,7 @@ choice config MPC834x_SYS bool "Freescale MPC834x SYS" + select DEFAULT_UIMAGE help This option enables support for the MPC 834x SYS evaluation board. diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.c b/arch/powerpc/platforms/83xx/mpc834x_sys.c new file mode 100644 index 00000000000..2098dd05a77 --- /dev/null +++ b/arch/powerpc/platforms/83xx/mpc834x_sys.c @@ -0,0 +1,243 @@ +/* + * arch/powerpc/platforms/83xx/mpc834x_sys.c + * + * MPC834x SYS board specific routines + * + * Maintainer: Kumar Gala + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mpc83xx.h" + +#ifndef CONFIG_PCI +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +#endif + +#ifdef CONFIG_PCI +extern int mpc83xx_pci2_busno; + +static int +mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) +{ + static char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + { + {PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x11 */ + {PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x12 */ + {PIRQD, PIRQA, PIRQB, PIRQC}, /* idsel 0x13 */ + {0, 0, 0, 0}, + {PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x15 */ + {PIRQD, PIRQA, PIRQB, PIRQC}, /* idsel 0x16 */ + {PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x17 */ + {PIRQB, PIRQC, PIRQD, PIRQA}, /* idsel 0x18 */ + {0, 0, 0, 0}, /* idsel 0x19 */ + {0, 0, 0, 0}, /* idsel 0x20 */ + }; + + const long min_idsel = 0x11, max_idsel = 0x20, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP; +} + +static int +mpc83xx_exclude_device(u_char bus, u_char devfn) +{ + if (bus == 0 && PCI_SLOT(devfn) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + if (mpc83xx_pci2_busno) + if (bus == (mpc83xx_pci2_busno) && PCI_SLOT(devfn) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + return PCIBIOS_SUCCESSFUL; +} +#endif /* CONFIG_PCI */ + +/* ************************************************************************ + * + * Setup the architecture + * + */ +static void __init +mpc834x_sys_setup_arch(void) +{ + struct device_node *np; + + if (ppc_md.progress) + ppc_md.progress("mpc834x_sys_setup_arch()", 0); + + np = of_find_node_by_type(NULL, "cpu"); + if (np != 0) { + unsigned int *fp = (int *) get_property(np, "clock-frequency", NULL); + if (fp != 0) + loops_per_jiffy = *fp / HZ; + else + loops_per_jiffy = 50000000 / HZ; + of_node_put(np); + } + +#ifdef CONFIG_PCI + for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) + add_bridge(np); + + ppc_md.pci_swizzle = common_swizzle; + ppc_md.pci_map_irq = mpc83xx_map_irq; + ppc_md.pci_exclude_device = mpc83xx_exclude_device; +#endif + +#ifdef CONFIG_ROOT_NFS + ROOT_DEV = Root_NFS; +#else + ROOT_DEV = Root_HDA1; +#endif +} + +void __init +mpc834x_sys_init_IRQ(void) +{ + u8 senses[8] = { + 0, /* EXT 0 */ + IRQ_SENSE_LEVEL, /* EXT 1 */ + IRQ_SENSE_LEVEL, /* EXT 2 */ + 0, /* EXT 3 */ +#ifdef CONFIG_PCI + IRQ_SENSE_LEVEL, /* EXT 4 */ + IRQ_SENSE_LEVEL, /* EXT 5 */ + IRQ_SENSE_LEVEL, /* EXT 6 */ + IRQ_SENSE_LEVEL, /* EXT 7 */ +#else + 0, /* EXT 4 */ + 0, /* EXT 5 */ + 0, /* EXT 6 */ + 0, /* EXT 7 */ +#endif + }; + + ipic_init(get_immrbase() + 0x00700, 0, 0, senses, 8); + + /* Initialize the default interrupt mapping priorities, + * in case the boot rom changed something on us. + */ + ipic_set_default_priority(); +} + +#if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1374) +extern ulong ds1374_get_rtc_time(void); +extern int ds1374_set_rtc_time(ulong); + +static int __init +mpc834x_rtc_hookup(void) +{ + struct timespec tv; + + ppc_md.get_rtc_time = ds1374_get_rtc_time; + ppc_md.set_rtc_time = ds1374_set_rtc_time; + + tv.tv_nsec = 0; + tv.tv_sec = (ppc_md.get_rtc_time)(); + do_settimeofday(&tv); + + return 0; +} +late_initcall(mpc834x_rtc_hookup); +#endif + +static void +mpc83xx_restart(char *cmd) +{ +#define RST_OFFSET 0x00000900 +#define RST_PROT_REG 0x00000018 +#define RST_CTRL_REG 0x0000001c + __be32 __iomem *reg; + + // map reset register space + reg = ioremap(get_immrbase() + 0x900, 0xff); + + local_irq_disable(); + + /* enable software reset "RSTE" */ + out_be32(reg + (RST_PROT_REG >> 2), 0x52535445); + + /* set software hard reset */ + out_be32(reg + (RST_CTRL_REG >> 2), 0x52535445); + for(;;); +} + +static long __init +mpc83xx_time_init(void) +{ +#define SPCR_OFFSET 0x00000110 +#define SPCR_TBEN 0x00400000 + __be32 __iomem *spcr = ioremap(get_immrbase() + SPCR_OFFSET, 4); + __be32 tmp; + + tmp = in_be32(spcr); + out_be32(spcr, tmp|SPCR_TBEN); + + iounmap(spcr); + + return 0; +} +void __init +platform_init(void) +{ + /* setup the PowerPC module struct */ + ppc_md.setup_arch = mpc834x_sys_setup_arch; + + ppc_md.init_IRQ = mpc834x_sys_init_IRQ; + ppc_md.get_irq = ipic_get_irq; + + ppc_md.restart = mpc83xx_restart; + + ppc_md.time_init = mpc83xx_time_init; + ppc_md.set_rtc_time = NULL; + ppc_md.get_rtc_time = NULL; + ppc_md.calibrate_decr = generic_calibrate_decr; + + ppc_md.progress = udbg_progress; + + if (ppc_md.progress) + ppc_md.progress("mpc834x_sys_init(): exit", 0); + + return; +} + + diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.h b/arch/powerpc/platforms/83xx/mpc834x_sys.h new file mode 100644 index 00000000000..e4ca39f6a86 --- /dev/null +++ b/arch/powerpc/platforms/83xx/mpc834x_sys.h @@ -0,0 +1,23 @@ +/* + * arch/powerppc/platforms/83xx/mpc834x_sys.h + * + * MPC834X SYS common board definitions + * + * Maintainer: Kumar Gala + * + * 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. + * + */ + +#ifndef __MACH_MPC83XX_SYS_H__ +#define __MACH_MPC83XX_SYS_H__ + +#define PIRQA MPC83xx_IRQ_EXT4 +#define PIRQB MPC83xx_IRQ_EXT5 +#define PIRQC MPC83xx_IRQ_EXT6 +#define PIRQD MPC83xx_IRQ_EXT7 + +#endif /* __MACH_MPC83XX_SYS_H__ */ diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h new file mode 100644 index 00000000000..ce9e66abef2 --- /dev/null +++ b/arch/powerpc/platforms/83xx/mpc83xx.h @@ -0,0 +1,14 @@ +#ifndef __MPC83XX_H__ +#define __MPC83XX_H__ + +#include +#include + +/* + * Declaration for the various functions exported by the + * mpc83xx_* files. Mostly for use by mpc83xx_setup + */ + +extern int add_bridge(struct device_node *dev); + +#endif /* __MPC83XX_H__ */ diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c new file mode 100644 index 00000000000..469cdacc5bd --- /dev/null +++ b/arch/powerpc/platforms/83xx/pci.c @@ -0,0 +1,99 @@ +/* + * FSL SoC setup code + * + * Maintained by Kumar Gala (see MAINTAINERS for contact information) + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#undef DEBUG + +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +int mpc83xx_pci2_busno; + +#ifdef CONFIG_PCI +int __init add_bridge(struct device_node *dev) +{ + int len; + struct pci_controller *hose; + struct resource rsrc; + int *bus_range; + int primary = 1, has_address = 0; + phys_addr_t immr = get_immrbase(); + + DBG("Adding PCI host bridge %s\n", dev->full_name); + + /* Fetch host bridge registers address */ + has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); + + /* Get bus range if any */ + bus_range = (int *) get_property(dev, "bus-range", &len); + if (bus_range == NULL || len < 2 * sizeof(int)) { + printk(KERN_WARNING "Can't get bus-range for %s, assume" + " bus 0\n", dev->full_name); + } + + hose = pcibios_alloc_controller(); + if (!hose) + return -ENOMEM; + hose->arch_data = dev; + hose->set_cfg_type = 1; + + hose->first_busno = bus_range ? bus_range[0] : 0; + hose->last_busno = bus_range ? bus_range[1] : 0xff; + + /* MPC83xx supports up to two host controllers one at 0x8500 from immrbar + * the other at 0x8600, we consider the 0x8500 the primary controller + */ + /* PCI 1 */ + if ((rsrc.start & 0xfffff) == 0x8500) { + setup_indirect_pci(hose, immr + 0x8300, immr + 0x8304); + } + /* PCI 2*/ + if ((rsrc.start & 0xfffff) == 0x8600) { + setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384); + primary = 0; + hose->bus_offset = hose->first_busno; + mpc83xx_pci2_busno = hose->first_busno; + } + + printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%08lx. " + "Firmware bus number: %d->%d\n", + rsrc.start, hose->first_busno, hose->last_busno); + + DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", + hose, hose->cfg_addr, hose->cfg_data); + + /* Interpret the "ranges" property */ + /* This also maps the I/O region and sets isa_io/mem_base */ + pci_process_bridge_OF_ranges(hose, dev, primary); + + return 0; +} + +#endif -- GitLab From 8f069b1a90bd97bf6d59a02ecabf0173d9175609 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Fri, 13 Jan 2006 14:16:12 -0200 Subject: [PATCH 150/465] [PATCH] powerpc/8xx: Use 8MB D-TLB's for kernel static mapping faults The following implements support for instantiation of 8MB D-TLB entries for the kernel direct virtual mapping on 8xx, thus reducing TLB space consumed for the kernel. Test used: writing 40MB from /dev/zero to file in ext2fs over RAMDISK. $ time dd if=/dev/zero of=file bs=4k count=10000 VANILLA 8MB kernel data pages real 0m11.485s real 0m11.267s user 0m0.218s user 0m0.250s sys 0m8.939s sys 0m9.108s real 0m11.518s real 0m10.978s user 0m0.203s user 0m0.222s sys 0m9.585s sys 0m9.138s real 0m11.554s real 0m10.967s user 0m0.228s user 0m0.222s sys 0m9.497s sys 0m9.127s real 0m11.633s real 0m11.286s user 0m0.214s user 0m0.196s sys 0m9.529s sys 0m9.134s and averages for both: real 11.54750 real 11.12450 Which is a 3.6% improvement in execution time. More improvement is expected for loads with larger kernel data footprint (real workloads). Signed-off-by: Marcelo Tosatti Signed-off-by: Paul Mackerras --- arch/ppc/kernel/head_8xx.S | 77 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S index de097874222..3e6ca7f5843 100644 --- a/arch/ppc/kernel/head_8xx.S +++ b/arch/ppc/kernel/head_8xx.S @@ -375,6 +375,8 @@ DataStoreTLBMiss: lis r11, swapper_pg_dir@h ori r11, r11, swapper_pg_dir@l rlwimi r10, r11, 0, 2, 19 + stw r12, 16(r0) + b LoadLargeDTLB 3: lwz r11, 0(r10) /* Get the level 1 entry */ rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */ @@ -430,6 +432,81 @@ DataStoreTLBMiss: InstructionTLBError: b InstructionAccess +LoadLargeDTLB: + li r12, 0 + lwz r11, 0(r10) /* Get the level 1 entry */ + rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */ + beq 3f /* If zero, don't try to find a pte */ + + /* We have a pte table, so load fetch the pte from the table. + */ + ori r11, r11, 1 /* Set valid bit in physical L2 page */ + DO_8xx_CPU6(0x3b80, r3) + mtspr SPRN_MD_TWC, r11 /* Load pte table base address */ + mfspr r10, SPRN_MD_TWC /* ....and get the pte address */ + lwz r10, 0(r10) /* Get the pte */ + + /* Insert the Guarded flag into the TWC from the Linux PTE. + * It is bit 27 of both the Linux PTE and the TWC (at least + * I got that right :-). It will be better when we can put + * this into the Linux pgd/pmd and load it in the operation + * above. + */ + rlwimi r11, r10, 0, 27, 27 + + rlwimi r12, r10, 0, 0, 9 /* extract phys. addr */ + mfspr r3, SPRN_MD_EPN + rlwinm r3, r3, 0, 0, 9 /* extract virtual address */ + tophys(r3, r3) + cmpw r3, r12 /* only use 8M page if it is a direct + kernel mapping */ + bne 1f + ori r11, r11, MD_PS8MEG + li r12, 1 + b 2f +1: + li r12, 0 /* can't use 8MB TLB, so zero r12. */ +2: + DO_8xx_CPU6(0x3b80, r3) + mtspr SPRN_MD_TWC, r11 + + /* The Linux PTE won't go exactly into the MMU TLB. + * Software indicator bits 21, 22 and 28 must be clear. + * Software indicator bits 24, 25, 26, and 27 must be + * set. All other Linux PTE bits control the behavior + * of the MMU. + */ +3: li r11, 0x00f0 + rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */ + cmpwi r12, 1 + bne 4f + ori r10, r10, 0x8 + + mfspr r12, SPRN_MD_EPN + lis r3, 0xff80 /* 10-19 must be clear for 8MB TLB */ + ori r3, r3, 0x0fff + and r12, r3, r12 + DO_8xx_CPU6(0x3780, r3) + mtspr SPRN_MD_EPN, r12 + + lis r3, 0xff80 /* 10-19 must be clear for 8MB TLB */ + ori r3, r3, 0x0fff + and r10, r3, r10 +4: + DO_8xx_CPU6(0x3d80, r3) + mtspr SPRN_MD_RPN, r10 /* Update TLB entry */ + + mfspr r10, SPRN_M_TW /* Restore registers */ + lwz r11, 0(r0) + mtcr r11 + lwz r11, 4(r0) + + lwz r12, 16(r0) +#ifdef CONFIG_8xx_CPU6 + lwz r3, 8(r0) +#endif + rfi + /* This is the data TLB error on the MPC8xx. This could be due to * many reasons, including a dirty update to a pte. We can catch that * one here, but anything else is an error. First, we track down the -- GitLab From 37d8dc82e0cd93eec77c5bcebd725c4ba661351a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 13 Jan 2006 16:19:44 -0800 Subject: [PATCH 151/465] [NETFILTER] x-tables: Missing linux/ipv6.h includes. Signed-off-by: David S. Miller --- net/netfilter/xt_length.c | 1 + net/netfilter/xt_tcpudp.c | 1 + 2 files changed, 2 insertions(+) diff --git a/net/netfilter/xt_length.c b/net/netfilter/xt_length.c index ab6c710cf88..39c8faea63d 100644 --- a/net/netfilter/xt_length.c +++ b/net/netfilter/xt_length.c @@ -8,6 +8,7 @@ #include #include +#include #include #include diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c index 33f86fd6f3e..669c8113cc6 100644 --- a/net/netfilter/xt_tcpudp.c +++ b/net/netfilter/xt_tcpudp.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include -- GitLab From 8ae12a0d85987dc138f8c944cb78a92bf466cea0 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sun, 8 Jan 2006 13:34:19 -0800 Subject: [PATCH 152/465] [PATCH] spi: simple SPI framework This is the core of a small SPI framework, implementing the model of a queue of messages which complete asynchronously (with thin synchronous wrappers on top). - It's still less than 2KB of ".text" (ARM). If there's got to be a mid-layer for something so simple, that's the right size budget. :) - The guts use board-specific SPI device tables to build the driver model tree. (Hardware probing is rarely an option.) - This version of Kconfig includes no drivers. At this writing there are two known master controller drivers (PXA/SSP, OMAP MicroWire) and three protocol drivers (CS8415a, ADS7846, DataFlash) with LKML mentions of other drivers in development. - No userspace API. There are several implementations to compare. Implement them like any other driver, and bind them with sysfs. The changes from last version posted to LKML (on 11-Nov-2005) are minor, and include: - One bugfix (removes a FIXME), with the visible effect of making device names be "spiB.C" where B is the bus number and C is the chipselect. - The "caller provides DMA mappings" mechanism now has kerneldoc, for DMA drivers that want to be fancy. - Hey, the framework init can be subsys_init. Even though board init logic fires earlier, at arch_init ... since the framework init is for driver support, and the board init support uses static init. - Various additional spec/doc clarifications based on discussions with other folk. It adds a brief "thank you" at the end, for folk who've helped nudge this framework into existence. As I've said before, I think that "protocol tweaking" is the main support that this driver framework will need to evolve. From: Mark Underwood Update the SPI framework to remove a potential priority inversion case by reverting to kmalloc if the pre-allocated DMA-safe buffer isn't available. Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- Documentation/spi/spi-summary | 416 +++++++++++++++++++++++++ arch/arm/Kconfig | 2 + drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/spi/Kconfig | 76 +++++ drivers/spi/Makefile | 23 ++ drivers/spi/spi.c | 568 ++++++++++++++++++++++++++++++++++ include/linux/spi/spi.h | 542 ++++++++++++++++++++++++++++++++ 8 files changed, 1630 insertions(+) create mode 100644 Documentation/spi/spi-summary create mode 100644 drivers/spi/Kconfig create mode 100644 drivers/spi/Makefile create mode 100644 drivers/spi/spi.c create mode 100644 include/linux/spi/spi.h diff --git a/Documentation/spi/spi-summary b/Documentation/spi/spi-summary new file mode 100644 index 00000000000..00497f95ca4 --- /dev/null +++ b/Documentation/spi/spi-summary @@ -0,0 +1,416 @@ +Overview of Linux kernel SPI support +==================================== + +22-Nov-2005 + +What is SPI? +------------ +The "Serial Peripheral Interface" (SPI) is a four-wire point-to-point +serial link used to connect microcontrollers to sensors and memory. + +The three signal wires hold a clock (SCLK, often on the order of 10 MHz), +and parallel data lines with "Master Out, Slave In" (MOSI) or "Master In, +Slave Out" (MISO) signals. (Other names are also used.) There are four +clocking modes through which data is exchanged; mode-0 and mode-3 are most +commonly used. + +SPI masters may use a "chip select" line to activate a given SPI slave +device, so those three signal wires may be connected to several chips +in parallel. All SPI slaves support chipselects. Some devices have +other signals, often including an interrupt to the master. + +Unlike serial busses like USB or SMBUS, even low level protocols for +SPI slave functions are usually not interoperable between vendors +(except for cases like SPI memory chips). + + - SPI may be used for request/response style device protocols, as with + touchscreen sensors and memory chips. + + - It may also be used to stream data in either direction (half duplex), + or both of them at the same time (full duplex). + + - Some devices may use eight bit words. Others may different word + lengths, such as streams of 12-bit or 20-bit digital samples. + +In the same way, SPI slaves will only rarely support any kind of automatic +discovery/enumeration protocol. The tree of slave devices accessible from +a given SPI master will normally be set up manually, with configuration +tables. + +SPI is only one of the names used by such four-wire protocols, and +most controllers have no problem handling "MicroWire" (think of it as +half-duplex SPI, for request/response protocols), SSP ("Synchronous +Serial Protocol"), PSP ("Programmable Serial Protocol"), and other +related protocols. + +Microcontrollers often support both master and slave sides of the SPI +protocol. This document (and Linux) currently only supports the master +side of SPI interactions. + + +Who uses it? On what kinds of systems? +--------------------------------------- +Linux developers using SPI are probably writing device drivers for embedded +systems boards. SPI is used to control external chips, and it is also a +protocol supported by every MMC or SD memory card. (The older "DataFlash" +cards, predating MMC cards but using the same connectors and card shape, +support only SPI.) Some PC hardware uses SPI flash for BIOS code. + +SPI slave chips range from digital/analog converters used for analog +sensors and codecs, to memory, to peripherals like USB controllers +or Ethernet adapters; and more. + +Most systems using SPI will integrate a few devices on a mainboard. +Some provide SPI links on expansion connectors; in cases where no +dedicated SPI controller exists, GPIO pins can be used to create a +low speed "bitbanging" adapter. Very few systems will "hotplug" an SPI +controller; the reasons to use SPI focus on low cost and simple operation, +and if dynamic reconfiguration is important, USB will often be a more +appropriate low-pincount peripheral bus. + +Many microcontrollers that can run Linux integrate one or more I/O +interfaces with SPI modes. Given SPI support, they could use MMC or SD +cards without needing a special purpose MMC/SD/SDIO controller. + + +How do these driver programming interfaces work? +------------------------------------------------ +The header file includes kerneldoc, as does the +main source code, and you should certainly read that. This is just +an overview, so you get the big picture before the details. + +There are two types of SPI driver, here called: + + Controller drivers ... these are often built in to System-On-Chip + processors, and often support both Master and Slave roles. + These drivers touch hardware registers and may use DMA. + + Protocol drivers ... these pass messages through the controller + driver to communicate with a Slave or Master device on the + other side of an SPI link. + +So for example one protocol driver might talk to the MTD layer to export +data to filesystems stored on SPI flash like DataFlash; and others might +control audio interfaces, present touchscreen sensors as input interfaces, +or monitor temperature and voltage levels during industrial processing. +And those might all be sharing the same controller driver. + +A "struct spi_device" encapsulates the master-side interface between +those two types of driver. At this writing, Linux has no slave side +programming interface. + +There is a minimal core of SPI programming interfaces, focussing on +using driver model to connect controller and protocol drivers using +device tables provided by board specific initialization code. SPI +shows up in sysfs in several locations: + + /sys/devices/.../CTLR/spiB.C ... spi_device for on bus "B", + chipselect C, accessed through CTLR. + + /sys/bus/spi/devices/spiB.C ... symlink to the physical + spiB-C device + + /sys/bus/spi/drivers/D ... driver for one or more spi*.* devices + + /sys/class/spi_master/spiB ... class device for the controller + managing bus "B". All the spiB.* devices share the same + physical SPI bus segment, with SCLK, MOSI, and MISO. + +The basic I/O primitive submits an asynchronous message to an I/O queue +maintained by the controller driver. A completion callback is issued +asynchronously when the data transfer(s) in that message completes. +There are also some simple synchronous wrappers for those calls. + + +How does board-specific init code declare SPI devices? +------------------------------------------------------ +Linux needs several kinds of information to properly configure SPI devices. +That information is normally provided by board-specific code, even for +chips that do support some of automated discovery/enumeration. + +DECLARE CONTROLLERS + +The first kind of information is a list of what SPI controllers exist. +For System-on-Chip (SOC) based boards, these will usually be platform +devices, and the controller may need some platform_data in order to +operate properly. The "struct platform_device" will include resources +like the physical address of the controller's first register and its IRQ. + +Platforms will often abstract the "register SPI controller" operation, +maybe coupling it with code to initialize pin configurations, so that +the arch/.../mach-*/board-*.c files for several boards can all share the +same basic controller setup code. This is because most SOCs have several +SPI-capable controllers, and only the ones actually usable on a given +board should normally be set up and registered. + +So for example arch/.../mach-*/board-*.c files might have code like: + + #include /* for mysoc_spi_data */ + + /* if your mach-* infrastructure doesn't support kernels that can + * run on multiple boards, pdata wouldn't benefit from "__init". + */ + static struct mysoc_spi_data __init pdata = { ... }; + + static __init board_init(void) + { + ... + /* this board only uses SPI controller #2 */ + mysoc_register_spi(2, &pdata); + ... + } + +And SOC-specific utility code might look something like: + + #include + + static struct platform_device spi2 = { ... }; + + void mysoc_register_spi(unsigned n, struct mysoc_spi_data *pdata) + { + struct mysoc_spi_data *pdata2; + + pdata2 = kmalloc(sizeof *pdata2, GFP_KERNEL); + *pdata2 = pdata; + ... + if (n == 2) { + spi2->dev.platform_data = pdata2; + register_platform_device(&spi2); + + /* also: set up pin modes so the spi2 signals are + * visible on the relevant pins ... bootloaders on + * production boards may already have done this, but + * developer boards will often need Linux to do it. + */ + } + ... + } + +Notice how the platform_data for boards may be different, even if the +same SOC controller is used. For example, on one board SPI might use +an external clock, where another derives the SPI clock from current +settings of some master clock. + + +DECLARE SLAVE DEVICES + +The second kind of information is a list of what SPI slave devices exist +on the target board, often with some board-specific data needed for the +driver to work correctly. + +Normally your arch/.../mach-*/board-*.c files would provide a small table +listing the SPI devices on each board. (This would typically be only a +small handful.) That might look like: + + static struct ads7846_platform_data ads_info = { + .vref_delay_usecs = 100, + .x_plate_ohms = 580, + .y_plate_ohms = 410, + }; + + static struct spi_board_info spi_board_info[] __initdata = { + { + .modalias = "ads7846", + .platform_data = &ads_info, + .mode = SPI_MODE_0, + .irq = GPIO_IRQ(31), + .max_speed_hz = 120000 /* max sample rate at 3V */ * 16, + .bus_num = 1, + .chip_select = 0, + }, + }; + +Again, notice how board-specific information is provided; each chip may need +several types. This example shows generic constraints like the fastest SPI +clock to allow (a function of board voltage in this case) or how an IRQ pin +is wired, plus chip-specific constraints like an important delay that's +changed by the capacitance at one pin. + +(There's also "controller_data", information that may be useful to the +controller driver. An example would be peripheral-specific DMA tuning +data or chipselect callbacks. This is stored in spi_device later.) + +The board_info should provide enough information to let the system work +without the chip's driver being loaded. The most troublesome aspect of +that is likely the SPI_CS_HIGH bit in the spi_device.mode field, since +sharing a bus with a device that interprets chipselect "backwards" is +not possible. + +Then your board initialization code would register that table with the SPI +infrastructure, so that it's available later when the SPI master controller +driver is registered: + + spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); + +Like with other static board-specific setup, you won't unregister those. + + +NON-STATIC CONFIGURATIONS + +Developer boards often play by different rules than product boards, and one +example is the potential need to hotplug SPI devices and/or controllers. + +For those cases you might need to use use spi_busnum_to_master() to look +up the spi bus master, and will likely need spi_new_device() to provide the +board info based on the board that was hotplugged. Of course, you'd later +call at least spi_unregister_device() when that board is removed. + + +How do I write an "SPI Protocol Driver"? +---------------------------------------- +All SPI drivers are currently kernel drivers. A userspace driver API +would just be another kernel driver, probably offering some lowlevel +access through aio_read(), aio_write(), and ioctl() calls and using the +standard userspace sysfs mechanisms to bind to a given SPI device. + +SPI protocol drivers are normal device drivers, with no more wrapper +than needed by platform devices: + + static struct device_driver CHIP_driver = { + .name = "CHIP", + .bus = &spi_bus_type, + .probe = CHIP_probe, + .remove = __exit_p(CHIP_remove), + .suspend = CHIP_suspend, + .resume = CHIP_resume, + }; + +The SPI core will autmatically attempt to bind this driver to any SPI +device whose board_info gave a modalias of "CHIP". Your probe() code +might look like this unless you're creating a class_device: + + static int __init CHIP_probe(struct device *dev) + { + struct spi_device *spi = to_spi_device(dev); + struct CHIP *chip; + struct CHIP_platform_data *pdata = dev->platform_data; + + /* get memory for driver's per-chip state */ + chip = kzalloc(sizeof *chip, GFP_KERNEL); + if (!chip) + return -ENOMEM; + dev_set_drvdata(dev, chip); + + ... etc + return 0; + } + +As soon as it enters probe(), the driver may issue I/O requests to +the SPI device using "struct spi_message". When remove() returns, +the driver guarantees that it won't submit any more such messages. + + - An spi_message is a sequence of of protocol operations, executed + as one atomic sequence. SPI driver controls include: + + + when bidirectional reads and writes start ... by how its + sequence of spi_transfer requests is arranged; + + + optionally defining short delays after transfers ... using + the spi_transfer.delay_usecs setting; + + + whether the chipselect becomes inactive after a transfer and + any delay ... by using the spi_transfer.cs_change flag; + + + hinting whether the next message is likely to go to this same + device ... using the spi_transfer.cs_change flag on the last + transfer in that atomic group, and potentially saving costs + for chip deselect and select operations. + + - Follow standard kernel rules, and provide DMA-safe buffers in + your messages. That way controller drivers using DMA aren't forced + to make extra copies unless the hardware requires it (e.g. working + around hardware errata that force the use of bounce buffering). + + If standard dma_map_single() handling of these buffers is inappropriate, + you can use spi_message.is_dma_mapped to tell the controller driver + that you've already provided the relevant DMA addresses. + + - The basic I/O primitive is spi_async(). Async requests may be + issued in any context (irq handler, task, etc) and completion + is reported using a callback provided with the message. + + - There are also synchronous wrappers like spi_sync(), and wrappers + like spi_read(), spi_write(), and spi_write_then_read(). These + may be issued only in contexts that may sleep, and they're all + clean (and small, and "optional") layers over spi_async(). + + - The spi_write_then_read() call, and convenience wrappers around + it, should only be used with small amounts of data where the + cost of an extra copy may be ignored. It's designed to support + common RPC-style requests, such as writing an eight bit command + and reading a sixteen bit response -- spi_w8r16() being one its + wrappers, doing exactly that. + +Some drivers may need to modify spi_device characteristics like the +transfer mode, wordsize, or clock rate. This is done with spi_setup(), +which would normally be called from probe() before the first I/O is +done to the device. + +While "spi_device" would be the bottom boundary of the driver, the +upper boundaries might include sysfs (especially for sensor readings), +the input layer, ALSA, networking, MTD, the character device framework, +or other Linux subsystems. + + +How do I write an "SPI Master Controller Driver"? +------------------------------------------------- +An SPI controller will probably be registered on the platform_bus; write +a driver to bind to the device, whichever bus is involved. + +The main task of this type of driver is to provide an "spi_master". +Use spi_alloc_master() to allocate the master, and class_get_devdata() +to get the driver-private data allocated for that device. + + struct spi_master *master; + struct CONTROLLER *c; + + master = spi_alloc_master(dev, sizeof *c); + if (!master) + return -ENODEV; + + c = class_get_devdata(&master->cdev); + +The driver will initialize the fields of that spi_master, including the +bus number (maybe the same as the platform device ID) and three methods +used to interact with the SPI core and SPI protocol drivers. It will +also initialize its own internal state. + + master->setup(struct spi_device *spi) + This sets up the device clock rate, SPI mode, and word sizes. + Drivers may change the defaults provided by board_info, and then + call spi_setup(spi) to invoke this routine. It may sleep. + + master->transfer(struct spi_device *spi, struct spi_message *message) + This must not sleep. Its responsibility is arrange that the + transfer happens and its complete() callback is issued; the two + will normally happen later, after other transfers complete. + + master->cleanup(struct spi_device *spi) + Your controller driver may use spi_device.controller_state to hold + state it dynamically associates with that device. If you do that, + be sure to provide the cleanup() method to free that state. + +The bulk of the driver will be managing the I/O queue fed by transfer(). + +That queue could be purely conceptual. For example, a driver used only +for low-frequency sensor acess might be fine using synchronous PIO. + +But the queue will probably be very real, using message->queue, PIO, +often DMA (especially if the root filesystem is in SPI flash), and +execution contexts like IRQ handlers, tasklets, or workqueues (such +as keventd). Your driver can be as fancy, or as simple, as you need. + + +THANKS TO +--------- +Contributors to Linux-SPI discussions include (in alphabetical order, +by last name): + +David Brownell +Russell King +Dmitry Pervushin +Stephen Street +Mark Underwood +Andrew Victor +Vitaly Wool + diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 50b9afa8ae6..3cfd82a05b2 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -729,6 +729,8 @@ source "drivers/char/Kconfig" source "drivers/i2c/Kconfig" +source "drivers/spi/Kconfig" + source "drivers/hwmon/Kconfig" #source "drivers/l3/Kconfig" diff --git a/drivers/Kconfig b/drivers/Kconfig index 48f446d3c67..283c089537b 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -44,6 +44,8 @@ source "drivers/char/Kconfig" source "drivers/i2c/Kconfig" +source "drivers/spi/Kconfig" + source "drivers/w1/Kconfig" source "drivers/hwmon/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 7fc3f0f08b2..7c45050ecd0 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -41,6 +41,7 @@ obj-$(CONFIG_FUSION) += message/ obj-$(CONFIG_IEEE1394) += ieee1394/ obj-y += cdrom/ obj-$(CONFIG_MTD) += mtd/ +obj-$(CONFIG_SPI) += spi/ obj-$(CONFIG_PCCARD) += pcmcia/ obj-$(CONFIG_DIO) += dio/ obj-$(CONFIG_SBUS) += sbus/ diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig new file mode 100644 index 00000000000..d3105104a29 --- /dev/null +++ b/drivers/spi/Kconfig @@ -0,0 +1,76 @@ +# +# SPI driver configuration +# +# NOTE: the reason this doesn't show SPI slave support is mostly that +# nobody's needed a slave side API yet. The master-role API is not +# fully appropriate there, so it'd need some thought to do well. +# +menu "SPI support" + +config SPI + bool "SPI support" + help + The "Serial Peripheral Interface" is a low level synchronous + protocol. Chips that support SPI can have data transfer rates + up to several tens of Mbit/sec. Chips are addressed with a + controller and a chipselect. Most SPI slaves don't support + dynamic device discovery; some are even write-only or read-only. + + SPI is widely used by microcontollers to talk with sensors, + eeprom and flash memory, codecs and various other controller + chips, analog to digital (and d-to-a) converters, and more. + MMC and SD cards can be accessed using SPI protocol; and for + DataFlash cards used in MMC sockets, SPI must always be used. + + SPI is one of a family of similar protocols using a four wire + interface (select, clock, data in, data out) including Microwire + (half duplex), SSP, SSI, and PSP. This driver framework should + work with most such devices and controllers. + +config SPI_DEBUG + boolean "Debug support for SPI drivers" + depends on SPI && DEBUG_KERNEL + help + Say "yes" to enable debug messaging (like dev_dbg and pr_debug), + sysfs, and debugfs support in SPI controller and protocol drivers. + +# +# MASTER side ... talking to discrete SPI slave chips including microcontrollers +# + +config SPI_MASTER +# boolean "SPI Master Support" + boolean + default SPI + help + If your system has an master-capable SPI controller (which + provides the clock and chipselect), you can enable that + controller and the protocol drivers for the SPI slave chips + that are connected. + +comment "SPI Master Controller Drivers" + depends on SPI_MASTER + + +# +# Add new SPI master controllers in alphabetical order above this line +# + + +# +# There are lots of SPI device types, with sensors and memory +# being probably the most widely used ones. +# +comment "SPI Protocol Masters" + depends on SPI_MASTER + + +# +# Add new SPI protocol masters in alphabetical order above this line +# + + +# (slave support would go here) + +endmenu # "SPI support" + diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile new file mode 100644 index 00000000000..afd2321753b --- /dev/null +++ b/drivers/spi/Makefile @@ -0,0 +1,23 @@ +# +# Makefile for kernel SPI drivers. +# + +ifeq ($(CONFIG_SPI_DEBUG),y) +EXTRA_CFLAGS += -DDEBUG +endif + +# small core, mostly translating board-specific +# config declarations into driver model code +obj-$(CONFIG_SPI_MASTER) += spi.o + +# SPI master controller drivers (bus) +# ... add above this line ... + +# SPI protocol drivers (device/link on bus) +# ... add above this line ... + +# SPI slave controller drivers (upstream link) +# ... add above this line ... + +# SPI slave drivers (protocol for that link) +# ... add above this line ... diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c new file mode 100644 index 00000000000..7cd356b1764 --- /dev/null +++ b/drivers/spi/spi.c @@ -0,0 +1,568 @@ +/* + * spi.c - SPI init/core code + * + * Copyright (C) 2005 David Brownell + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + + +/* SPI bustype and spi_master class are registered during early boot, + * usually before board init code provides the SPI device tables, and + * are available later when driver init code needs them. + * + * Drivers for SPI devices started out like those for platform bus + * devices. But both have changed in 2.6.15; maybe this should get + * an "spi_driver" structure at some point (not currently needed) + */ +static void spidev_release(struct device *dev) +{ + const struct spi_device *spi = to_spi_device(dev); + + /* spi masters may cleanup for released devices */ + if (spi->master->cleanup) + spi->master->cleanup(spi); + + class_device_put(&spi->master->cdev); + kfree(dev); +} + +static ssize_t +modalias_show(struct device *dev, struct device_attribute *a, char *buf) +{ + const struct spi_device *spi = to_spi_device(dev); + + return snprintf(buf, BUS_ID_SIZE + 1, "%s\n", spi->modalias); +} + +static struct device_attribute spi_dev_attrs[] = { + __ATTR_RO(modalias), + __ATTR_NULL, +}; + +/* modalias support makes "modprobe $MODALIAS" new-style hotplug work, + * and the sysfs version makes coldplug work too. + */ + +static int spi_match_device(struct device *dev, struct device_driver *drv) +{ + const struct spi_device *spi = to_spi_device(dev); + + return strncmp(spi->modalias, drv->name, BUS_ID_SIZE) == 0; +} + +static int spi_uevent(struct device *dev, char **envp, int num_envp, + char *buffer, int buffer_size) +{ + const struct spi_device *spi = to_spi_device(dev); + + envp[0] = buffer; + snprintf(buffer, buffer_size, "MODALIAS=%s", spi->modalias); + envp[1] = NULL; + return 0; +} + +#ifdef CONFIG_PM + +/* Suspend/resume in "struct device_driver" don't really need that + * strange third parameter, so we just make it a constant and expect + * SPI drivers to ignore it just like most platform drivers do. + * + * NOTE: the suspend() method for an spi_master controller driver + * should verify that all its child devices are marked as suspended; + * suspend requests delivered through sysfs power/state files don't + * enforce such constraints. + */ +static int spi_suspend(struct device *dev, pm_message_t message) +{ + int value; + + if (!dev->driver || !dev->driver->suspend) + return 0; + + /* suspend will stop irqs and dma; no more i/o */ + value = dev->driver->suspend(dev, message); + if (value == 0) + dev->power.power_state = message; + return value; +} + +static int spi_resume(struct device *dev) +{ + int value; + + if (!dev->driver || !dev->driver->resume) + return 0; + + /* resume may restart the i/o queue */ + value = dev->driver->resume(dev); + if (value == 0) + dev->power.power_state = PMSG_ON; + return value; +} + +#else +#define spi_suspend NULL +#define spi_resume NULL +#endif + +struct bus_type spi_bus_type = { + .name = "spi", + .dev_attrs = spi_dev_attrs, + .match = spi_match_device, + .uevent = spi_uevent, + .suspend = spi_suspend, + .resume = spi_resume, +}; +EXPORT_SYMBOL_GPL(spi_bus_type); + +/*-------------------------------------------------------------------------*/ + +/* SPI devices should normally not be created by SPI device drivers; that + * would make them board-specific. Similarly with SPI master drivers. + * Device registration normally goes into like arch/.../mach.../board-YYY.c + * with other readonly (flashable) information about mainboard devices. + */ + +struct boardinfo { + struct list_head list; + unsigned n_board_info; + struct spi_board_info board_info[0]; +}; + +static LIST_HEAD(board_list); +static DECLARE_MUTEX(board_lock); + + +/* On typical mainboards, this is purely internal; and it's not needed + * after board init creates the hard-wired devices. Some development + * platforms may not be able to use spi_register_board_info though, and + * this is exported so that for example a USB or parport based adapter + * driver could add devices (which it would learn about out-of-band). + */ +struct spi_device *__init_or_module +spi_new_device(struct spi_master *master, struct spi_board_info *chip) +{ + struct spi_device *proxy; + struct device *dev = master->cdev.dev; + int status; + + /* NOTE: caller did any chip->bus_num checks necessary */ + + if (!class_device_get(&master->cdev)) + return NULL; + + proxy = kzalloc(sizeof *proxy, GFP_KERNEL); + if (!proxy) { + dev_err(dev, "can't alloc dev for cs%d\n", + chip->chip_select); + goto fail; + } + proxy->master = master; + proxy->chip_select = chip->chip_select; + proxy->max_speed_hz = chip->max_speed_hz; + proxy->irq = chip->irq; + proxy->modalias = chip->modalias; + + snprintf(proxy->dev.bus_id, sizeof proxy->dev.bus_id, + "%s.%u", master->cdev.class_id, + chip->chip_select); + proxy->dev.parent = dev; + proxy->dev.bus = &spi_bus_type; + proxy->dev.platform_data = (void *) chip->platform_data; + proxy->controller_data = chip->controller_data; + proxy->controller_state = NULL; + proxy->dev.release = spidev_release; + + /* drivers may modify this default i/o setup */ + status = master->setup(proxy); + if (status < 0) { + dev_dbg(dev, "can't %s %s, status %d\n", + "setup", proxy->dev.bus_id, status); + goto fail; + } + + /* driver core catches callers that misbehave by defining + * devices that already exist. + */ + status = device_register(&proxy->dev); + if (status < 0) { + dev_dbg(dev, "can't %s %s, status %d\n", + "add", proxy->dev.bus_id, status); +fail: + class_device_put(&master->cdev); + kfree(proxy); + return NULL; + } + dev_dbg(dev, "registered child %s\n", proxy->dev.bus_id); + return proxy; +} +EXPORT_SYMBOL_GPL(spi_new_device); + +/* + * Board-specific early init code calls this (probably during arch_initcall) + * with segments of the SPI device table. Any device nodes are created later, + * after the relevant parent SPI controller (bus_num) is defined. We keep + * this table of devices forever, so that reloading a controller driver will + * not make Linux forget about these hard-wired devices. + * + * Other code can also call this, e.g. a particular add-on board might provide + * SPI devices through its expansion connector, so code initializing that board + * would naturally declare its SPI devices. + * + * The board info passed can safely be __initdata ... but be careful of + * any embedded pointers (platform_data, etc), they're copied as-is. + */ +int __init +spi_register_board_info(struct spi_board_info const *info, unsigned n) +{ + struct boardinfo *bi; + + bi = kmalloc (sizeof (*bi) + n * sizeof (*info), GFP_KERNEL); + if (!bi) + return -ENOMEM; + bi->n_board_info = n; + memcpy(bi->board_info, info, n * sizeof (*info)); + + down(&board_lock); + list_add_tail(&bi->list, &board_list); + up(&board_lock); + return 0; +} +EXPORT_SYMBOL_GPL(spi_register_board_info); + +/* FIXME someone should add support for a __setup("spi", ...) that + * creates board info from kernel command lines + */ + +static void __init_or_module +scan_boardinfo(struct spi_master *master) +{ + struct boardinfo *bi; + struct device *dev = master->cdev.dev; + + down(&board_lock); + list_for_each_entry(bi, &board_list, list) { + struct spi_board_info *chip = bi->board_info; + unsigned n; + + for (n = bi->n_board_info; n > 0; n--, chip++) { + if (chip->bus_num != master->bus_num) + continue; + /* some controllers only have one chip, so they + * might not use chipselects. otherwise, the + * chipselects are numbered 0..max. + */ + if (chip->chip_select >= master->num_chipselect + && master->num_chipselect) { + dev_dbg(dev, "cs%d > max %d\n", + chip->chip_select, + master->num_chipselect); + continue; + } + (void) spi_new_device(master, chip); + } + } + up(&board_lock); +} + +/*-------------------------------------------------------------------------*/ + +static void spi_master_release(struct class_device *cdev) +{ + struct spi_master *master; + + master = container_of(cdev, struct spi_master, cdev); + put_device(master->cdev.dev); + master->cdev.dev = NULL; + kfree(master); +} + +static struct class spi_master_class = { + .name = "spi_master", + .owner = THIS_MODULE, + .release = spi_master_release, +}; + + +/** + * spi_alloc_master - allocate SPI master controller + * @dev: the controller, possibly using the platform_bus + * @size: how much driver-private data to preallocate; a pointer to this + * memory in the class_data field of the returned class_device + * + * This call is used only by SPI master controller drivers, which are the + * only ones directly touching chip registers. It's how they allocate + * an spi_master structure, prior to calling spi_add_master(). + * + * This must be called from context that can sleep. It returns the SPI + * master structure on success, else NULL. + * + * The caller is responsible for assigning the bus number and initializing + * the master's methods before calling spi_add_master(), or else (on error) + * calling class_device_put() to prevent a memory leak. + */ +struct spi_master * __init_or_module +spi_alloc_master(struct device *dev, unsigned size) +{ + struct spi_master *master; + + master = kzalloc(size + sizeof *master, SLAB_KERNEL); + if (!master) + return NULL; + + master->cdev.class = &spi_master_class; + master->cdev.dev = get_device(dev); + class_set_devdata(&master->cdev, &master[1]); + + return master; +} +EXPORT_SYMBOL_GPL(spi_alloc_master); + +/** + * spi_register_master - register SPI master controller + * @master: initialized master, originally from spi_alloc_master() + * + * SPI master controllers connect to their drivers using some non-SPI bus, + * such as the platform bus. The final stage of probe() in that code + * includes calling spi_register_master() to hook up to this SPI bus glue. + * + * SPI controllers use board specific (often SOC specific) bus numbers, + * and board-specific addressing for SPI devices combines those numbers + * with chip select numbers. Since SPI does not directly support dynamic + * device identification, boards need configuration tables telling which + * chip is at which address. + * + * This must be called from context that can sleep. It returns zero on + * success, else a negative error code (dropping the master's refcount). + */ +int __init_or_module +spi_register_master(struct spi_master *master) +{ + static atomic_t dyn_bus_id = ATOMIC_INIT(0); + struct device *dev = master->cdev.dev; + int status = -ENODEV; + int dynamic = 0; + + /* convention: dynamically assigned bus IDs count down from the max */ + if (master->bus_num == 0) { + master->bus_num = atomic_dec_return(&dyn_bus_id); + dynamic = 0; + } + + /* register the device, then userspace will see it. + * registration fails if the bus ID is in use. + */ + snprintf(master->cdev.class_id, sizeof master->cdev.class_id, + "spi%u", master->bus_num); + status = class_device_register(&master->cdev); + if (status < 0) { + class_device_put(&master->cdev); + goto done; + } + dev_dbg(dev, "registered master %s%s\n", master->cdev.class_id, + dynamic ? " (dynamic)" : ""); + + /* populate children from any spi device tables */ + scan_boardinfo(master); + status = 0; +done: + return status; +} +EXPORT_SYMBOL_GPL(spi_register_master); + + +static int __unregister(struct device *dev, void *unused) +{ + /* note: before about 2.6.14-rc1 this would corrupt memory: */ + device_unregister(dev); + return 0; +} + +/** + * spi_unregister_master - unregister SPI master controller + * @master: the master being unregistered + * + * This call is used only by SPI master controller drivers, which are the + * only ones directly touching chip registers. + * + * This must be called from context that can sleep. + */ +void spi_unregister_master(struct spi_master *master) +{ + class_device_unregister(&master->cdev); + (void) device_for_each_child(master->cdev.dev, NULL, __unregister); +} +EXPORT_SYMBOL_GPL(spi_unregister_master); + +/** + * spi_busnum_to_master - look up master associated with bus_num + * @bus_num: the master's bus number + * + * This call may be used with devices that are registered after + * arch init time. It returns a refcounted pointer to the relevant + * spi_master (which the caller must release), or NULL if there is + * no such master registered. + */ +struct spi_master *spi_busnum_to_master(u16 bus_num) +{ + if (bus_num) { + char name[8]; + struct kobject *bus; + + snprintf(name, sizeof name, "spi%u", bus_num); + bus = kset_find_obj(&spi_master_class.subsys.kset, name); + if (bus) + return container_of(bus, struct spi_master, cdev.kobj); + } + return NULL; +} +EXPORT_SYMBOL_GPL(spi_busnum_to_master); + + +/*-------------------------------------------------------------------------*/ + +/** + * spi_sync - blocking/synchronous SPI data transfers + * @spi: device with which data will be exchanged + * @message: describes the data transfers + * + * This call may only be used from a context that may sleep. The sleep + * is non-interruptible, and has no timeout. Low-overhead controller + * drivers may DMA directly into and out of the message buffers. + * + * Note that the SPI device's chip select is active during the message, + * and then is normally disabled between messages. Drivers for some + * frequently-used devices may want to minimize costs of selecting a chip, + * by leaving it selected in anticipation that the next message will go + * to the same chip. (That may increase power usage.) + * + * The return value is a negative error code if the message could not be + * submitted, else zero. When the value is zero, then message->status is + * also defined: it's the completion code for the transfer, either zero + * or a negative error code from the controller driver. + */ +int spi_sync(struct spi_device *spi, struct spi_message *message) +{ + DECLARE_COMPLETION(done); + int status; + + message->complete = (void (*)(void *)) complete; + message->context = &done; + status = spi_async(spi, message); + if (status == 0) + wait_for_completion(&done); + message->context = NULL; + return status; +} +EXPORT_SYMBOL_GPL(spi_sync); + +#define SPI_BUFSIZ (SMP_CACHE_BYTES) + +static u8 *buf; + +/** + * spi_write_then_read - SPI synchronous write followed by read + * @spi: device with which data will be exchanged + * @txbuf: data to be written (need not be dma-safe) + * @n_tx: size of txbuf, in bytes + * @rxbuf: buffer into which data will be read + * @n_rx: size of rxbuf, in bytes (need not be dma-safe) + * + * This performs a half duplex MicroWire style transaction with the + * device, sending txbuf and then reading rxbuf. The return value + * is zero for success, else a negative errno status code. + * + * Parameters to this routine are always copied using a small buffer, + * large transfers should use use spi_{async,sync}() calls with + * dma-safe buffers. + */ +int spi_write_then_read(struct spi_device *spi, + const u8 *txbuf, unsigned n_tx, + u8 *rxbuf, unsigned n_rx) +{ + static DECLARE_MUTEX(lock); + + int status; + struct spi_message message; + struct spi_transfer x[2]; + u8 *local_buf; + + /* Use preallocated DMA-safe buffer. We can't avoid copying here, + * (as a pure convenience thing), but we can keep heap costs + * out of the hot path ... + */ + if ((n_tx + n_rx) > SPI_BUFSIZ) + return -EINVAL; + + /* ... unless someone else is using the pre-allocated buffer */ + if (down_trylock(&lock)) { + local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL); + if (!local_buf) + return -ENOMEM; + } else + local_buf = buf; + + memset(x, 0, sizeof x); + + memcpy(local_buf, txbuf, n_tx); + x[0].tx_buf = local_buf; + x[0].len = n_tx; + + x[1].rx_buf = local_buf + n_tx; + x[1].len = n_rx; + + /* do the i/o */ + message.transfers = x; + message.n_transfer = ARRAY_SIZE(x); + status = spi_sync(spi, &message); + if (status == 0) { + memcpy(rxbuf, x[1].rx_buf, n_rx); + status = message.status; + } + + if (x[0].tx_buf == buf) + up(&lock); + else + kfree(local_buf); + + return status; +} +EXPORT_SYMBOL_GPL(spi_write_then_read); + +/*-------------------------------------------------------------------------*/ + +static int __init spi_init(void) +{ + buf = kmalloc(SPI_BUFSIZ, SLAB_KERNEL); + if (!buf) + return -ENOMEM; + + bus_register(&spi_bus_type); + class_register(&spi_master_class); + return 0; +} +/* board_info is normally registered in arch_initcall(), + * but even essential drivers wait till later + */ +subsys_initcall(spi_init); + diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h new file mode 100644 index 00000000000..51a6769114d --- /dev/null +++ b/include/linux/spi/spi.h @@ -0,0 +1,542 @@ +/* + * Copyright (C) 2005 David Brownell + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __LINUX_SPI_H +#define __LINUX_SPI_H + +/* + * INTERFACES between SPI master drivers and infrastructure + * (There's no SPI slave support for Linux yet...) + * + * A "struct device_driver" for an spi_device uses "spi_bus_type" and + * needs no special API wrappers (much like platform_bus). These drivers + * are bound to devices based on their names (much like platform_bus), + * and are available in dev->driver. + */ +extern struct bus_type spi_bus_type; + +/** + * struct spi_device - Master side proxy for an SPI slave device + * @dev: Driver model representation of the device. + * @master: SPI controller used with the device. + * @max_speed_hz: Maximum clock rate to be used with this chip + * (on this board); may be changed by the device's driver. + * @chip-select: Chipselect, distinguishing chips handled by "master". + * @mode: The spi mode defines how data is clocked out and in. + * This may be changed by the device's driver. + * @bits_per_word: Data transfers involve one or more words; word sizes + * like eight or 12 bits are common. In-memory wordsizes are + * powers of two bytes (e.g. 20 bit samples use 32 bits). + * This may be changed by the device's driver. + * @irq: Negative, or the number passed to request_irq() to receive + * interrupts from this device. + * @controller_state: Controller's runtime state + * @controller_data: Static board-specific definitions for controller, such + * as FIFO initialization parameters; from board_info.controller_data + * + * An spi_device is used to interchange data between an SPI slave + * (usually a discrete chip) and CPU memory. + * + * In "dev", the platform_data is used to hold information about this + * device that's meaningful to the device's protocol driver, but not + * to its controller. One example might be an identifier for a chip + * variant with slightly different functionality. + */ +struct spi_device { + struct device dev; + struct spi_master *master; + u32 max_speed_hz; + u8 chip_select; + u8 mode; +#define SPI_CPHA 0x01 /* clock phase */ +#define SPI_CPOL 0x02 /* clock polarity */ +#define SPI_MODE_0 (0|0) +#define SPI_MODE_1 (0|SPI_CPHA) +#define SPI_MODE_2 (SPI_CPOL|0) +#define SPI_MODE_3 (SPI_CPOL|SPI_CPHA) +#define SPI_CS_HIGH 0x04 /* chipselect active high? */ + u8 bits_per_word; + int irq; + void *controller_state; + const void *controller_data; + const char *modalias; + + // likely need more hooks for more protocol options affecting how + // the controller talks to its chips, like: + // - bit order (default is wordwise msb-first) + // - memory packing (12 bit samples into low bits, others zeroed) + // - priority + // - chipselect delays + // - ... +}; + +static inline struct spi_device *to_spi_device(struct device *dev) +{ + return container_of(dev, struct spi_device, dev); +} + +/* most drivers won't need to care about device refcounting */ +static inline struct spi_device *spi_dev_get(struct spi_device *spi) +{ + return (spi && get_device(&spi->dev)) ? spi : NULL; +} + +static inline void spi_dev_put(struct spi_device *spi) +{ + if (spi) + put_device(&spi->dev); +} + +/* ctldata is for the bus_master driver's runtime state */ +static inline void *spi_get_ctldata(struct spi_device *spi) +{ + return spi->controller_state; +} + +static inline void spi_set_ctldata(struct spi_device *spi, void *state) +{ + spi->controller_state = state; +} + + +struct spi_message; + + +/** + * struct spi_master - interface to SPI master controller + * @cdev: class interface to this driver + * @bus_num: board-specific (and often SOC-specific) identifier for a + * given SPI controller. + * @num_chipselects: chipselects are used to distinguish individual + * SPI slaves, and are numbered from zero to num_chipselects. + * each slave has a chipselect signal, but it's common that not + * every chipselect is connected to a slave. + * @setup: updates the device mode and clocking records used by a + * device's SPI controller; protocol code may call this. + * @transfer: adds a message to the controller's transfer queue. + * @cleanup: frees controller-specific state + * + * Each SPI master controller can communicate with one or more spi_device + * children. These make a small bus, sharing MOSI, MISO and SCK signals + * but not chip select signals. Each device may be configured to use a + * different clock rate, since those shared signals are ignored unless + * the chip is selected. + * + * The driver for an SPI controller manages access to those devices through + * a queue of spi_message transactions, copyin data between CPU memory and + * an SPI slave device). For each such message it queues, it calls the + * message's completion function when the transaction completes. + */ +struct spi_master { + struct class_device cdev; + + /* other than zero (== assign one dynamically), bus_num is fully + * board-specific. usually that simplifies to being SOC-specific. + * example: one SOC has three SPI controllers, numbered 1..3, + * and one board's schematics might show it using SPI-2. software + * would normally use bus_num=2 for that controller. + */ + u16 bus_num; + + /* chipselects will be integral to many controllers; some others + * might use board-specific GPIOs. + */ + u16 num_chipselect; + + /* setup mode and clock, etc (spi driver may call many times) */ + int (*setup)(struct spi_device *spi); + + /* bidirectional bulk transfers + * + * + The transfer() method may not sleep; its main role is + * just to add the message to the queue. + * + For now there's no remove-from-queue operation, or + * any other request management + * + To a given spi_device, message queueing is pure fifo + * + * + The master's main job is to process its message queue, + * selecting a chip then transferring data + * + If there are multiple spi_device children, the i/o queue + * arbitration algorithm is unspecified (round robin, fifo, + * priority, reservations, preemption, etc) + * + * + Chipselect stays active during the entire message + * (unless modified by spi_transfer.cs_change != 0). + * + The message transfers use clock and SPI mode parameters + * previously established by setup() for this device + */ + int (*transfer)(struct spi_device *spi, + struct spi_message *mesg); + + /* called on release() to free memory provided by spi_master */ + void (*cleanup)(const struct spi_device *spi); +}; + +/* the spi driver core manages memory for the spi_master classdev */ +extern struct spi_master * +spi_alloc_master(struct device *host, unsigned size); + +extern int spi_register_master(struct spi_master *master); +extern void spi_unregister_master(struct spi_master *master); + +extern struct spi_master *spi_busnum_to_master(u16 busnum); + +/*---------------------------------------------------------------------------*/ + +/* + * I/O INTERFACE between SPI controller and protocol drivers + * + * Protocol drivers use a queue of spi_messages, each transferring data + * between the controller and memory buffers. + * + * The spi_messages themselves consist of a series of read+write transfer + * segments. Those segments always read the same number of bits as they + * write; but one or the other is easily ignored by passing a null buffer + * pointer. (This is unlike most types of I/O API, because SPI hardware + * is full duplex.) + * + * NOTE: Allocation of spi_transfer and spi_message memory is entirely + * up to the protocol driver, which guarantees the integrity of both (as + * well as the data buffers) for as long as the message is queued. + */ + +/** + * struct spi_transfer - a read/write buffer pair + * @tx_buf: data to be written (dma-safe address), or NULL + * @rx_buf: data to be read (dma-safe address), or NULL + * @tx_dma: DMA address of buffer, if spi_message.is_dma_mapped + * @rx_dma: DMA address of buffer, if spi_message.is_dma_mapped + * @len: size of rx and tx buffers (in bytes) + * @cs_change: affects chipselect after this transfer completes + * @delay_usecs: microseconds to delay after this transfer before + * (optionally) changing the chipselect status, then starting + * the next transfer or completing this spi_message. + * + * SPI transfers always write the same number of bytes as they read. + * Protocol drivers should always provide rx_buf and/or tx_buf. + * In some cases, they may also want to provide DMA addresses for + * the data being transferred; that may reduce overhead, when the + * underlying driver uses dma. + * + * All SPI transfers start with the relevant chipselect active. Drivers + * can change behavior of the chipselect after the transfer finishes + * (including any mandatory delay). The normal behavior is to leave it + * selected, except for the last transfer in a message. Setting cs_change + * allows two additional behavior options: + * + * (i) If the transfer isn't the last one in the message, this flag is + * used to make the chipselect briefly go inactive in the middle of the + * message. Toggling chipselect in this way may be needed to terminate + * a chip command, letting a single spi_message perform all of group of + * chip transactions together. + * + * (ii) When the transfer is the last one in the message, the chip may + * stay selected until the next transfer. This is purely a performance + * hint; the controller driver may need to select a different device + * for the next message. + */ +struct spi_transfer { + /* it's ok if tx_buf == rx_buf (right?) + * for MicroWire, one buffer must be null + * buffers must work with dma_*map_single() calls + */ + const void *tx_buf; + void *rx_buf; + unsigned len; + + dma_addr_t tx_dma; + dma_addr_t rx_dma; + + unsigned cs_change:1; + u16 delay_usecs; +}; + +/** + * struct spi_message - one multi-segment SPI transaction + * @transfers: the segements of the transaction + * @n_transfer: how many segments + * @spi: SPI device to which the transaction is queued + * @is_dma_mapped: if true, the caller provided both dma and cpu virtual + * addresses for each transfer buffer + * @complete: called to report transaction completions + * @context: the argument to complete() when it's called + * @actual_length: how many bytes were transferd + * @status: zero for success, else negative errno + * @queue: for use by whichever driver currently owns the message + * @state: for use by whichever driver currently owns the message + */ +struct spi_message { + struct spi_transfer *transfers; + unsigned n_transfer; + + struct spi_device *spi; + + unsigned is_dma_mapped:1; + + /* REVISIT: we might want a flag affecting the behavior of the + * last transfer ... allowing things like "read 16 bit length L" + * immediately followed by "read L bytes". Basically imposing + * a specific message scheduling algorithm. + * + * Some controller drivers (message-at-a-time queue processing) + * could provide that as their default scheduling algorithm. But + * others (with multi-message pipelines) would need a flag to + * tell them about such special cases. + */ + + /* completion is reported through a callback */ + void FASTCALL((*complete)(void *context)); + void *context; + unsigned actual_length; + int status; + + /* for optional use by whatever driver currently owns the + * spi_message ... between calls to spi_async and then later + * complete(), that's the spi_master controller driver. + */ + struct list_head queue; + void *state; +}; + +/** + * spi_setup -- setup SPI mode and clock rate + * @spi: the device whose settings are being modified + * + * SPI protocol drivers may need to update the transfer mode if the + * device doesn't work with the mode 0 default. They may likewise need + * to update clock rates or word sizes from initial values. This function + * changes those settings, and must be called from a context that can sleep. + */ +static inline int +spi_setup(struct spi_device *spi) +{ + return spi->master->setup(spi); +} + + +/** + * spi_async -- asynchronous SPI transfer + * @spi: device with which data will be exchanged + * @message: describes the data transfers, including completion callback + * + * This call may be used in_irq and other contexts which can't sleep, + * as well as from task contexts which can sleep. + * + * The completion callback is invoked in a context which can't sleep. + * Before that invocation, the value of message->status is undefined. + * When the callback is issued, message->status holds either zero (to + * indicate complete success) or a negative error code. + * + * Note that although all messages to a spi_device are handled in + * FIFO order, messages may go to different devices in other orders. + * Some device might be higher priority, or have various "hard" access + * time requirements, for example. + */ +static inline int +spi_async(struct spi_device *spi, struct spi_message *message) +{ + message->spi = spi; + return spi->master->transfer(spi, message); +} + +/*---------------------------------------------------------------------------*/ + +/* All these synchronous SPI transfer routines are utilities layered + * over the core async transfer primitive. Here, "synchronous" means + * they will sleep uninterruptibly until the async transfer completes. + */ + +extern int spi_sync(struct spi_device *spi, struct spi_message *message); + +/** + * spi_write - SPI synchronous write + * @spi: device to which data will be written + * @buf: data buffer + * @len: data buffer size + * + * This writes the buffer and returns zero or a negative error code. + * Callable only from contexts that can sleep. + */ +static inline int +spi_write(struct spi_device *spi, const u8 *buf, size_t len) +{ + struct spi_transfer t = { + .tx_buf = buf, + .rx_buf = NULL, + .len = len, + .cs_change = 0, + }; + struct spi_message m = { + .transfers = &t, + .n_transfer = 1, + }; + + return spi_sync(spi, &m); +} + +/** + * spi_read - SPI synchronous read + * @spi: device from which data will be read + * @buf: data buffer + * @len: data buffer size + * + * This writes the buffer and returns zero or a negative error code. + * Callable only from contexts that can sleep. + */ +static inline int +spi_read(struct spi_device *spi, u8 *buf, size_t len) +{ + struct spi_transfer t = { + .tx_buf = NULL, + .rx_buf = buf, + .len = len, + .cs_change = 0, + }; + struct spi_message m = { + .transfers = &t, + .n_transfer = 1, + }; + + return spi_sync(spi, &m); +} + +extern int spi_write_then_read(struct spi_device *spi, + const u8 *txbuf, unsigned n_tx, + u8 *rxbuf, unsigned n_rx); + +/** + * spi_w8r8 - SPI synchronous 8 bit write followed by 8 bit read + * @spi: device with which data will be exchanged + * @cmd: command to be written before data is read back + * + * This returns the (unsigned) eight bit number returned by the + * device, or else a negative error code. Callable only from + * contexts that can sleep. + */ +static inline ssize_t spi_w8r8(struct spi_device *spi, u8 cmd) +{ + ssize_t status; + u8 result; + + status = spi_write_then_read(spi, &cmd, 1, &result, 1); + + /* return negative errno or unsigned value */ + return (status < 0) ? status : result; +} + +/** + * spi_w8r16 - SPI synchronous 8 bit write followed by 16 bit read + * @spi: device with which data will be exchanged + * @cmd: command to be written before data is read back + * + * This returns the (unsigned) sixteen bit number returned by the + * device, or else a negative error code. Callable only from + * contexts that can sleep. + * + * The number is returned in wire-order, which is at least sometimes + * big-endian. + */ +static inline ssize_t spi_w8r16(struct spi_device *spi, u8 cmd) +{ + ssize_t status; + u16 result; + + status = spi_write_then_read(spi, &cmd, 1, (u8 *) &result, 2); + + /* return negative errno or unsigned value */ + return (status < 0) ? status : result; +} + +/*---------------------------------------------------------------------------*/ + +/* + * INTERFACE between board init code and SPI infrastructure. + * + * No SPI driver ever sees these SPI device table segments, but + * it's how the SPI core (or adapters that get hotplugged) grows + * the driver model tree. + * + * As a rule, SPI devices can't be probed. Instead, board init code + * provides a table listing the devices which are present, with enough + * information to bind and set up the device's driver. There's basic + * support for nonstatic configurations too; enough to handle adding + * parport adapters, or microcontrollers acting as USB-to-SPI bridges. + */ + +/* board-specific information about each SPI device */ +struct spi_board_info { + /* the device name and module name are coupled, like platform_bus; + * "modalias" is normally the driver name. + * + * platform_data goes to spi_device.dev.platform_data, + * controller_data goes to spi_device.platform_data, + * irq is copied too + */ + char modalias[KOBJ_NAME_LEN]; + const void *platform_data; + const void *controller_data; + int irq; + + /* slower signaling on noisy or low voltage boards */ + u32 max_speed_hz; + + + /* bus_num is board specific and matches the bus_num of some + * spi_master that will probably be registered later. + * + * chip_select reflects how this chip is wired to that master; + * it's less than num_chipselect. + */ + u16 bus_num; + u16 chip_select; + + /* ... may need additional spi_device chip config data here. + * avoid stuff protocol drivers can set; but include stuff + * needed to behave without being bound to a driver: + * - chipselect polarity + * - quirks like clock rate mattering when not selected + */ +}; + +#ifdef CONFIG_SPI +extern int +spi_register_board_info(struct spi_board_info const *info, unsigned n); +#else +/* board init code may ignore whether SPI is configured or not */ +static inline int +spi_register_board_info(struct spi_board_info const *info, unsigned n) + { return 0; } +#endif + + +/* If you're hotplugging an adapter with devices (parport, usb, etc) + * use spi_new_device() to describe each device. You can also call + * spi_unregister_device() to get start making that device vanish, + * but normally that would be handled by spi_unregister_master(). + */ +extern struct spi_device * +spi_new_device(struct spi_master *, struct spi_board_info *); + +static inline void +spi_unregister_device(struct spi_device *spi) +{ + if (spi) + device_unregister(&spi->dev); +} + +#endif /* __LINUX_SPI_H */ -- GitLab From ffa458c1bd9b6f653008d450f337602f3d52a646 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sun, 8 Jan 2006 13:34:21 -0800 Subject: [PATCH 153/465] [PATCH] spi: ads7846 driver This is a driver for the ADS7846 touchscreen sensor, derived from the corgi_ts and omap_ts drivers. Key differences from those two: - Uses the new SPI framework (minimalist version) - abstracts board-specific touchscreen info - Sysfs attributes for the temperature and voltage sensors - Uses fewer ARM-specific IRQ primitives The temperature and voltage sensors show up in sysfs like this: $ pwd /sys/devices/platform/omap-uwire/spi2.0 $ ls bus@ input:event0@ power/ temp1 vbatt driver@ modalias temp0 vaux $ cat modalias ads7846 $ cat temp0 991 $ cat temp1 1177 $ So far only basic testing has been done. There's a fair amount of hardware that uses this sensor, and which also runs Linux, which should eventually be able to use this driver. One portability note may be of special interest. It turns out that not all SPI controllers are happy issuing requests that do things like "write 8 bit command, read 12 bit response". Most of them seem happy to handle various word sizes, so the issue isn't "12 bit response" but rather "different rx and tx write sizes", despite that being a common MicroWire convention. So this version of the driver no longer reads 12 bit native-endian words; it reads 16-bit big-endian responses, then byteswaps them and shifts the results to discard the noise. Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/input/touchscreen/Kconfig | 13 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/ads7846.c | 621 ++++++++++++++++++++++++++++ include/linux/spi/ads7846.h | 18 + 4 files changed, 653 insertions(+) create mode 100644 drivers/input/touchscreen/ads7846.c create mode 100644 include/linux/spi/ads7846.h diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 21d55ed4b88..2c674023a6a 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -11,6 +11,19 @@ menuconfig INPUT_TOUCHSCREEN if INPUT_TOUCHSCREEN +config TOUCHSCREEN_ADS7846 + tristate "ADS 7846 based touchscreens" + depends on SPI_MASTER + help + Say Y here if you have a touchscreen interface using the + ADS7846 controller, and your board-specific initialization + code includes that in its table of SPI devices. + + If unsure, say N (but it's safe to say "Y"). + + To compile this driver as a module, choose M here: the + module will be called ads7846. + config TOUCHSCREEN_BITSY tristate "Compaq iPAQ H3600 (Bitsy) touchscreen" depends on SA1100_BITSY diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 6842869c9a2..5e5557c4312 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -4,6 +4,7 @@ # Each configuration option enables a list of files. +obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c new file mode 100644 index 00000000000..24ff6c5a402 --- /dev/null +++ b/drivers/input/touchscreen/ads7846.c @@ -0,0 +1,621 @@ +/* + * ADS7846 based touchscreen and sensor driver + * + * Copyright (c) 2005 David Brownell + * + * Using code from: + * - corgi_ts.c + * Copyright (C) 2004-2005 Richard Purdie + * - omap_ts.[hc], ads7846.h, ts_osk.c + * Copyright (C) 2002 MontaVista Software + * Copyright (C) 2004 Texas Instruments + * Copyright (C) 2005 Dirk Behme + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_ARM +#include +#ifdef CONFIG_ARCH_OMAP +#include +#endif + +#else +#define set_irq_type(irq,type) do{}while(0) +#endif + + +/* + * This code has been lightly tested on an ads7846. + * Support for ads7843 and ads7845 has only been stubbed in. + * + * Not yet done: investigate the values reported. Are x/y/pressure + * event values sane enough for X11? How accurate are the temperature + * and voltage readings? (System-specific calibration should support + * accuracy of 0.3 degrees C; otherwise it's 2.0 degrees.) + * + * app note sbaa036 talks in more detail about accurate sampling... + * that ought to help in situations like LCDs inducing noise (which + * can also be helped by using synch signals) and more generally. + */ + +#define TS_POLL_PERIOD msecs_to_jiffies(10) + +struct ts_event { + /* For portability, we can't read 12 bit values using SPI (which + * would make the controller deliver them as native byteorder u16 + * with msbs zeroed). Instead, we read them as two 8-byte values, + * which need byteswapping then range adjustment. + */ + __be16 x; + __be16 y; + __be16 z1, z2; +}; + +struct ads7846 { + struct input_dev input; + char phys[32]; + + struct spi_device *spi; + u16 model; + u16 vref_delay_usecs; + u16 x_plate_ohms; + + struct ts_event tc; + + struct spi_transfer xfer[8]; + struct spi_message msg; + + spinlock_t lock; + struct timer_list timer; /* P: lock */ + unsigned pendown:1; /* P: lock */ + unsigned pending:1; /* P: lock */ +// FIXME remove "irq_disabled" + unsigned irq_disabled:1; /* P: lock */ +}; + +/* leave chip selected when we're done, for quicker re-select? */ +#if 0 +#define CS_CHANGE(xfer) ((xfer).cs_change = 1) +#else +#define CS_CHANGE(xfer) ((xfer).cs_change = 0) +#endif + +/*--------------------------------------------------------------------------*/ + +/* The ADS7846 has touchscreen and other sensors. + * Earlier ads784x chips are somewhat compatible. + */ +#define ADS_START (1 << 7) +#define ADS_A2A1A0_d_y (1 << 4) /* differential */ +#define ADS_A2A1A0_d_z1 (3 << 4) /* differential */ +#define ADS_A2A1A0_d_z2 (4 << 4) /* differential */ +#define ADS_A2A1A0_d_x (5 << 4) /* differential */ +#define ADS_A2A1A0_temp0 (0 << 4) /* non-differential */ +#define ADS_A2A1A0_vbatt (2 << 4) /* non-differential */ +#define ADS_A2A1A0_vaux (6 << 4) /* non-differential */ +#define ADS_A2A1A0_temp1 (7 << 4) /* non-differential */ +#define ADS_8_BIT (1 << 3) +#define ADS_12_BIT (0 << 3) +#define ADS_SER (1 << 2) /* non-differential */ +#define ADS_DFR (0 << 2) /* differential */ +#define ADS_PD10_PDOWN (0 << 0) /* lowpower mode + penirq */ +#define ADS_PD10_ADC_ON (1 << 0) /* ADC on */ +#define ADS_PD10_REF_ON (2 << 0) /* vREF on + penirq */ +#define ADS_PD10_ALL_ON (3 << 0) /* ADC + vREF on */ + +#define MAX_12BIT ((1<<12)-1) + +/* leave ADC powered up (disables penirq) between differential samples */ +#define READ_12BIT_DFR(x) (ADS_START | ADS_A2A1A0_d_ ## x \ + | ADS_12_BIT | ADS_DFR) + +static const u8 read_y = READ_12BIT_DFR(y) | ADS_PD10_ADC_ON; +static const u8 read_z1 = READ_12BIT_DFR(z1) | ADS_PD10_ADC_ON; +static const u8 read_z2 = READ_12BIT_DFR(z2) | ADS_PD10_ADC_ON; +static const u8 read_x = READ_12BIT_DFR(x) | ADS_PD10_PDOWN; /* LAST */ + +/* single-ended samples need to first power up reference voltage; + * we leave both ADC and VREF powered + */ +#define READ_12BIT_SER(x) (ADS_START | ADS_A2A1A0_ ## x \ + | ADS_12_BIT | ADS_SER) + +static const u8 ref_on = READ_12BIT_DFR(x) | ADS_PD10_ALL_ON; +static const u8 ref_off = READ_12BIT_DFR(y) | ADS_PD10_PDOWN; + +/*--------------------------------------------------------------------------*/ + +/* + * Non-touchscreen sensors only use single-ended conversions. + */ + +struct ser_req { + u8 command; + u16 scratch; + __be16 sample; + struct spi_message msg; + struct spi_transfer xfer[6]; +}; + +static int ads7846_read12_ser(struct device *dev, unsigned command) +{ + struct spi_device *spi = to_spi_device(dev); + struct ads7846 *ts = dev_get_drvdata(dev); + struct ser_req *req = kzalloc(sizeof *req, SLAB_KERNEL); + int status; + int sample; + + if (!req) + return -ENOMEM; + + /* activate reference, so it has time to settle; */ + req->xfer[0].tx_buf = &ref_on; + req->xfer[0].len = 1; + req->xfer[1].rx_buf = &req->scratch; + req->xfer[1].len = 2; + + /* + * for external VREF, 0 usec (and assume it's always on); + * for 1uF, use 800 usec; + * no cap, 100 usec. + */ + req->xfer[1].delay_usecs = ts->vref_delay_usecs; + + /* take sample */ + req->command = (u8) command; + req->xfer[2].tx_buf = &req->command; + req->xfer[2].len = 1; + req->xfer[3].rx_buf = &req->sample; + req->xfer[3].len = 2; + + /* REVISIT: take a few more samples, and compare ... */ + + /* turn off reference */ + req->xfer[4].tx_buf = &ref_off; + req->xfer[4].len = 1; + req->xfer[5].rx_buf = &req->scratch; + req->xfer[5].len = 2; + + CS_CHANGE(req->xfer[5]); + + /* group all the transfers together, so we can't interfere with + * reading touchscreen state; disable penirq while sampling + */ + req->msg.transfers = req->xfer; + req->msg.n_transfer = 6; + + disable_irq(spi->irq); + status = spi_sync(spi, &req->msg); + enable_irq(spi->irq); + + if (req->msg.status) + status = req->msg.status; + sample = be16_to_cpu(req->sample); + sample = sample >> 4; + kfree(req); + + return status ? status : sample; +} + +#define SHOW(name) static ssize_t \ +name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \ +{ \ + ssize_t v = ads7846_read12_ser(dev, \ + READ_12BIT_SER(name) | ADS_PD10_ALL_ON); \ + if (v < 0) \ + return v; \ + return sprintf(buf, "%u\n", (unsigned) v); \ +} \ +static DEVICE_ATTR(name, S_IRUGO, name ## _show, NULL); + +SHOW(temp0) +SHOW(temp1) +SHOW(vaux) +SHOW(vbatt) + +/*--------------------------------------------------------------------------*/ + +/* + * PENIRQ only kicks the timer. The timer only reissues the SPI transfer, + * to retrieve touchscreen status. + * + * The SPI transfer completion callback does the real work. It reports + * touchscreen events and reactivates the timer (or IRQ) as appropriate. + */ + +static void ads7846_rx(void *ads) +{ + struct ads7846 *ts = ads; + unsigned Rt; + unsigned sync = 0; + u16 x, y, z1, z2; + unsigned long flags; + + /* adjust: 12 bit samples (left aligned), built from + * two 8 bit values writen msb-first. + */ + x = be16_to_cpu(ts->tc.x) >> 4; + y = be16_to_cpu(ts->tc.y) >> 4; + z1 = be16_to_cpu(ts->tc.z1) >> 4; + z2 = be16_to_cpu(ts->tc.z2) >> 4; + + /* range filtering */ + if (x == MAX_12BIT) + x = 0; + + if (x && z1 && ts->spi->dev.power.power_state.event == PM_EVENT_ON) { + /* compute touch pressure resistance using equation #2 */ + Rt = z2; + Rt -= z1; + Rt *= x; + Rt *= ts->x_plate_ohms; + Rt /= z1; + Rt = (Rt + 2047) >> 12; + } else + Rt = 0; + + /* NOTE: "pendown" is inferred from pressure; we don't rely on + * being able to check nPENIRQ status, or "friendly" trigger modes + * (both-edges is much better than just-falling or low-level). + * + * REVISIT: some boards may require reading nPENIRQ; it's + * needed on 7843. and 7845 reads pressure differently... + * + * REVISIT: the touchscreen might not be connected; this code + * won't notice that, even if nPENIRQ never fires ... + */ + if (!ts->pendown && Rt != 0) { + input_report_key(&ts->input, BTN_TOUCH, 1); + sync = 1; + } else if (ts->pendown && Rt == 0) { + input_report_key(&ts->input, BTN_TOUCH, 0); + sync = 1; + } + + if (Rt) { + input_report_abs(&ts->input, ABS_X, x); + input_report_abs(&ts->input, ABS_Y, y); + input_report_abs(&ts->input, ABS_PRESSURE, Rt); + sync = 1; + } + if (sync) + input_sync(&ts->input); + +#ifdef VERBOSE + if (Rt || ts->pendown) + pr_debug("%s: %d/%d/%d%s\n", ts->spi->dev.bus_id, + x, y, Rt, Rt ? "" : " UP"); +#endif + + /* don't retrigger while we're suspended */ + spin_lock_irqsave(&ts->lock, flags); + + ts->pendown = (Rt != 0); + ts->pending = 0; + + if (ts->spi->dev.power.power_state.event == PM_EVENT_ON) { + if (ts->pendown) + mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD); + else if (ts->irq_disabled) { + ts->irq_disabled = 0; + enable_irq(ts->spi->irq); + } + } + + spin_unlock_irqrestore(&ts->lock, flags); +} + +static void ads7846_timer(unsigned long handle) +{ + struct ads7846 *ts = (void *)handle; + int status = 0; + unsigned long flags; + + spin_lock_irqsave(&ts->lock, flags); + if (!ts->pending) { + ts->pending = 1; + if (!ts->irq_disabled) { + ts->irq_disabled = 1; + disable_irq(ts->spi->irq); + } + status = spi_async(ts->spi, &ts->msg); + if (status) + dev_err(&ts->spi->dev, "spi_async --> %d\n", + status); + } + spin_unlock_irqrestore(&ts->lock, flags); +} + +static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs) +{ + ads7846_timer((unsigned long) handle); + return IRQ_HANDLED; +} + +/*--------------------------------------------------------------------------*/ + +/* non-empty "extra" is needed before 2.6.14-git5 or so */ +#define EXTRA // , u32 level +#define EXTRA2 // , 0 + +static int +ads7846_suspend(struct device *dev, pm_message_t message EXTRA) +{ + struct ads7846 *ts = dev_get_drvdata(dev); + unsigned long flags; + + spin_lock_irqsave(&ts->lock, flags); + + ts->spi->dev.power.power_state = message; + + /* are we waiting for IRQ, or polling? */ + if (!ts->pendown) { + if (!ts->irq_disabled) { + ts->irq_disabled = 1; + disable_irq(ts->spi->irq); + } + } else { + /* polling; force a final SPI completion; + * that will clean things up neatly + */ + if (!ts->pending) + mod_timer(&ts->timer, jiffies); + + while (ts->pendown || ts->pending) { + spin_unlock_irqrestore(&ts->lock, flags); + udelay(10); + spin_lock_irqsave(&ts->lock, flags); + } + } + + /* we know the chip's in lowpower mode since we always + * leave it that way after every request + */ + + spin_unlock_irqrestore(&ts->lock, flags); + return 0; +} + +static int ads7846_resume(struct device *dev EXTRA) +{ + struct ads7846 *ts = dev_get_drvdata(dev); + + ts->irq_disabled = 0; + enable_irq(ts->spi->irq); + dev->power.power_state = PMSG_ON; + return 0; +} + +static int __init ads7846_probe(struct device *dev) +{ + struct spi_device *spi = to_spi_device(dev); + struct ads7846 *ts; + struct ads7846_platform_data *pdata = dev->platform_data; + struct spi_transfer *x; + + if (!spi->irq) { + dev_dbg(dev, "no IRQ?\n"); + return -ENODEV; + } + + if (!pdata) { + dev_dbg(dev, "no platform data?\n"); + return -ENODEV; + } + + /* don't exceed max specified sample rate */ + if (spi->max_speed_hz > (125000 * 16)) { + dev_dbg(dev, "f(sample) %d KHz?\n", + (spi->max_speed_hz/16)/1000); + return -EINVAL; + } + + /* We'd set the wordsize to 12 bits ... except that some controllers + * will then treat the 8 bit command words as 12 bits (and drop the + * four MSBs of the 12 bit result). Result: inputs must be shifted + * to discard the four garbage LSBs. + */ + + if (!(ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL))) + return -ENOMEM; + + dev_set_drvdata(dev, ts); + + ts->spi = spi; + spi->dev.power.power_state = PMSG_ON; + + init_timer(&ts->timer); + ts->timer.data = (unsigned long) ts; + ts->timer.function = ads7846_timer; + + ts->model = pdata->model ? : 7846; + ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100; + ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; + + init_input_dev(&ts->input); + + ts->input.dev = dev; + ts->input.name = "ADS784x Touchscreen"; + snprintf(ts->phys, sizeof ts->phys, "%s/input0", dev->bus_id); + ts->input.phys = ts->phys; + + ts->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); + ts->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); + input_set_abs_params(&ts->input, ABS_X, + pdata->x_min ? : 0, + pdata->x_max ? : MAX_12BIT, + 0, 0); + input_set_abs_params(&ts->input, ABS_Y, + pdata->y_min ? : 0, + pdata->y_max ? : MAX_12BIT, + 0, 0); + input_set_abs_params(&ts->input, ABS_PRESSURE, + pdata->pressure_min, pdata->pressure_max, 0, 0); + + input_register_device(&ts->input); + + /* set up the transfers to read touchscreen state; this assumes we + * use formula #2 for pressure, not #3. + */ + x = ts->xfer; + + /* y- still on; turn on only y+ (and ADC) */ + x->tx_buf = &read_y; + x->len = 1; + x++; + x->rx_buf = &ts->tc.y; + x->len = 2; + x++; + + /* turn y+ off, x- on; we'll use formula #2 */ + if (ts->model == 7846) { + x->tx_buf = &read_z1; + x->len = 1; + x++; + x->rx_buf = &ts->tc.z1; + x->len = 2; + x++; + + x->tx_buf = &read_z2; + x->len = 1; + x++; + x->rx_buf = &ts->tc.z2; + x->len = 2; + x++; + } + + /* turn y- off, x+ on, then leave in lowpower */ + x->tx_buf = &read_x; + x->len = 1; + x++; + x->rx_buf = &ts->tc.x; + x->len = 2; + x++; + + CS_CHANGE(x[-1]); + + ts->msg.transfers = ts->xfer; + ts->msg.n_transfer = x - ts->xfer; + ts->msg.complete = ads7846_rx; + ts->msg.context = ts; + + if (request_irq(spi->irq, ads7846_irq, SA_SAMPLE_RANDOM, + dev->bus_id, ts)) { + dev_dbg(dev, "irq %d busy?\n", spi->irq); + input_unregister_device(&ts->input); + kfree(ts); + return -EBUSY; + } + set_irq_type(spi->irq, IRQT_FALLING); + + dev_info(dev, "touchscreen, irq %d\n", spi->irq); + + /* take a first sample, leaving nPENIRQ active; avoid + * the touchscreen, in case it's not connected. + */ + (void) ads7846_read12_ser(dev, + READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON); + + /* ads7843/7845 don't have temperature sensors, and + * use the other sensors a bit differently too + */ + if (ts->model == 7846) { + device_create_file(dev, &dev_attr_temp0); + device_create_file(dev, &dev_attr_temp1); + } + if (ts->model != 7845) + device_create_file(dev, &dev_attr_vbatt); + device_create_file(dev, &dev_attr_vaux); + + return 0; +} + +static int __exit ads7846_remove(struct device *dev) +{ + struct ads7846 *ts = dev_get_drvdata(dev); + + ads7846_suspend(dev, PMSG_SUSPEND EXTRA2); + free_irq(ts->spi->irq, ts); + if (ts->irq_disabled) + enable_irq(ts->spi->irq); + + if (ts->model == 7846) { + device_remove_file(dev, &dev_attr_temp0); + device_remove_file(dev, &dev_attr_temp1); + } + if (ts->model != 7845) + device_remove_file(dev, &dev_attr_vbatt); + device_remove_file(dev, &dev_attr_vaux); + + input_unregister_device(&ts->input); + kfree(ts); + + dev_dbg(dev, "unregistered touchscreen\n"); + return 0; +} + +static struct device_driver ads7846_driver = { + .name = "ads7846", + .bus = &spi_bus_type, + .probe = ads7846_probe, + .remove = __exit_p(ads7846_remove), + .suspend = ads7846_suspend, + .resume = ads7846_resume, +}; + +static int __init ads7846_init(void) +{ + /* grr, board-specific init should stay out of drivers!! */ + +#ifdef CONFIG_ARCH_OMAP + if (machine_is_omap_osk()) { + /* GPIO4 = PENIRQ; GPIO6 = BUSY */ + omap_request_gpio(4); + omap_set_gpio_direction(4, 1); + omap_request_gpio(6); + omap_set_gpio_direction(6, 1); + } + // also TI 1510 Innovator, bitbanging through FPGA + // also Nokia 770 + // also Palm Tungsten T2 +#endif + + // PXA: + // also Dell Axim X50 + // also HP iPaq H191x/H192x/H415x/H435x + // also Intel Lubbock (alternate to UCB1400) + // also Sharp Zaurus C7xx, C8xx (corgi/sheperd/husky) + + // also various AMD Au1x00 devel boards + + return driver_register(&ads7846_driver); +} +module_init(ads7846_init); + +static void __exit ads7846_exit(void) +{ + driver_unregister(&ads7846_driver); + +#ifdef CONFIG_ARCH_OMAP + if (machine_is_omap_osk()) { + omap_free_gpio(4); + omap_free_gpio(6); + } +#endif + +} +module_exit(ads7846_exit); + +MODULE_DESCRIPTION("ADS7846 TouchScreen Driver"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/spi/ads7846.h b/include/linux/spi/ads7846.h new file mode 100644 index 00000000000..84a27013d39 --- /dev/null +++ b/include/linux/spi/ads7846.h @@ -0,0 +1,18 @@ +/* linux/spi/ads7846.h */ + +/* Touchscreen characteristics vary between boards and models. The + * platform_data for the device's "struct device" holts this information. + * + * It's OK if the min/max values are zero. + */ +struct ads7846_platform_data { + u16 model; /* 7843, 7845, 7846. */ + u16 vref_delay_usecs; /* 0 for external vref; etc */ + u16 x_plate_ohms; + u16 y_plate_ohms; + + u16 x_min, x_max; + u16 y_min, y_max; + u16 pressure_min, pressure_max; +}; + -- GitLab From 1d6432fe10c3e724e307dd7137cd293a0edcae80 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sun, 8 Jan 2006 13:34:22 -0800 Subject: [PATCH 154/465] [PATCH] spi: mtd dataflash driver This is a conversion of the AT91rm9200 DataFlash MTD driver to use the lightweight SPI framework, and no longer be AT91-specific. It compiles down to less than 3KBytes on ARM. The driver allows board-specific init code to provide platform_data with the relevant MTD partitioning information, and hotplugs. This version has been lightly tested. Its parent at91_dataflash driver has been pretty well banged on, although kernel.org JFFS2 dataflash support was acting broken the last time I tried it. Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/devices/Kconfig | 8 + drivers/mtd/devices/Makefile | 1 + drivers/mtd/devices/mtd_dataflash.c | 623 ++++++++++++++++++++++++++++ include/linux/spi/flash.h | 27 ++ 4 files changed, 659 insertions(+) create mode 100644 drivers/mtd/devices/mtd_dataflash.c create mode 100644 include/linux/spi/flash.h diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index 9a2aa4033c6..84f2eb1fae0 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig @@ -47,6 +47,14 @@ config MTD_MS02NV accelerator. Say Y here if you have a DECstation 5000/2x0 or a DECsystem 5900 equipped with such a module. +config MTD_DATAFLASH + tristate "Support for AT45xxx DataFlash" + depends on MTD && SPI_MASTER && EXPERIMENTAL + help + This enables access to AT45xxx DataFlash chips, using SPI. + Sometimes DataFlash chips are packaged inside MMC-format + cards; at this writing, the MMC stack won't handle those. + config MTD_SLRAM tristate "Uncached system RAM" depends on MTD diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile index e38db348057..cd8d8074b5b 100644 --- a/drivers/mtd/devices/Makefile +++ b/drivers/mtd/devices/Makefile @@ -23,3 +23,4 @@ obj-$(CONFIG_MTD_MTDRAM) += mtdram.o obj-$(CONFIG_MTD_LART) += lart.o obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o +obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c new file mode 100644 index 00000000000..a39b3b6b266 --- /dev/null +++ b/drivers/mtd/devices/mtd_dataflash.c @@ -0,0 +1,623 @@ +/* + * Atmel AT45xxx DataFlash MTD driver for lightweight SPI framework + * + * Largely derived from at91_dataflash.c: + * Copyright (C) 2003-2005 SAN People (Pty) Ltd + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +/* + * DataFlash is a kind of SPI flash. Most AT45 chips have two buffers in + * each chip, which may be used for double buffered I/O; but this driver + * doesn't (yet) use these for any kind of i/o overlap or prefetching. + * + * Sometimes DataFlash is packaged in MMC-format cards, although the + * MMC stack can't use SPI (yet), or distinguish between MMC and DataFlash + * protocols during enumeration. + */ + +#define CONFIG_DATAFLASH_WRITE_VERIFY + +/* reads can bypass the buffers */ +#define OP_READ_CONTINUOUS 0xE8 +#define OP_READ_PAGE 0xD2 + +/* group B requests can run even while status reports "busy" */ +#define OP_READ_STATUS 0xD7 /* group B */ + +/* move data between host and buffer */ +#define OP_READ_BUFFER1 0xD4 /* group B */ +#define OP_READ_BUFFER2 0xD6 /* group B */ +#define OP_WRITE_BUFFER1 0x84 /* group B */ +#define OP_WRITE_BUFFER2 0x87 /* group B */ + +/* erasing flash */ +#define OP_ERASE_PAGE 0x81 +#define OP_ERASE_BLOCK 0x50 + +/* move data between buffer and flash */ +#define OP_TRANSFER_BUF1 0x53 +#define OP_TRANSFER_BUF2 0x55 +#define OP_MREAD_BUFFER1 0xD4 +#define OP_MREAD_BUFFER2 0xD6 +#define OP_MWERASE_BUFFER1 0x83 +#define OP_MWERASE_BUFFER2 0x86 +#define OP_MWRITE_BUFFER1 0x88 /* sector must be pre-erased */ +#define OP_MWRITE_BUFFER2 0x89 /* sector must be pre-erased */ + +/* write to buffer, then write-erase to flash */ +#define OP_PROGRAM_VIA_BUF1 0x82 +#define OP_PROGRAM_VIA_BUF2 0x85 + +/* compare buffer to flash */ +#define OP_COMPARE_BUF1 0x60 +#define OP_COMPARE_BUF2 0x61 + +/* read flash to buffer, then write-erase to flash */ +#define OP_REWRITE_VIA_BUF1 0x58 +#define OP_REWRITE_VIA_BUF2 0x59 + +/* newer chips report JEDEC manufacturer and device IDs; chip + * serial number and OTP bits; and per-sector writeprotect. + */ +#define OP_READ_ID 0x9F +#define OP_READ_SECURITY 0x77 +#define OP_WRITE_SECURITY 0x9A /* OTP bits */ + + +struct dataflash { + u8 command[4]; + char name[24]; + + unsigned partitioned:1; + + unsigned short page_offset; /* offset in flash address */ + unsigned int page_size; /* of bytes per page */ + + struct semaphore lock; + struct spi_device *spi; + + struct mtd_info mtd; +}; + +#ifdef CONFIG_MTD_PARTITIONS +#define mtd_has_partitions() (1) +#else +#define mtd_has_partitions() (0) +#endif + +/* ......................................................................... */ + +/* + * Return the status of the DataFlash device. + */ +static inline int dataflash_status(struct spi_device *spi) +{ + /* NOTE: at45db321c over 25 MHz wants to write + * a dummy byte after the opcode... + */ + return spi_w8r8(spi, OP_READ_STATUS); +} + +/* + * Poll the DataFlash device until it is READY. + * This usually takes 5-20 msec or so; more for sector erase. + */ +static int dataflash_waitready(struct spi_device *spi) +{ + int status; + + for (;;) { + status = dataflash_status(spi); + if (status < 0) { + DEBUG(MTD_DEBUG_LEVEL1, "%s: status %d?\n", + spi->dev.bus_id, status); + status = 0; + } + + if (status & (1 << 7)) /* RDY/nBSY */ + return status; + + msleep(3); + } +} + +/* ......................................................................... */ + +/* + * Erase pages of flash. + */ +static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + struct dataflash *priv = (struct dataflash *)mtd->priv; + struct spi_device *spi = priv->spi; + struct spi_transfer x[1] = { { .tx_dma = 0, }, }; + struct spi_message msg; + unsigned blocksize = priv->page_size << 3; + u8 *command; + + DEBUG(MTD_DEBUG_LEVEL2, "%s: erase addr=0x%x len 0x%x\n", + spi->dev.bus_id, + instr->addr, instr->len); + + /* Sanity checks */ + if ((instr->addr + instr->len) > mtd->size + || (instr->len % priv->page_size) != 0 + || (instr->addr % priv->page_size) != 0) + return -EINVAL; + + x[0].tx_buf = command = priv->command; + x[0].len = 4; + msg.transfers = x; + msg.n_transfer = 1; + + down(&priv->lock); + while (instr->len > 0) { + unsigned int pageaddr; + int status; + int do_block; + + /* Calculate flash page address; use block erase (for speed) if + * we're at a block boundary and need to erase the whole block. + */ + pageaddr = instr->addr / priv->page_size; + do_block = (pageaddr & 0x7) == 0 && instr->len <= blocksize; + pageaddr = pageaddr << priv->page_offset; + + command[0] = do_block ? OP_ERASE_BLOCK : OP_ERASE_PAGE; + command[1] = (u8)(pageaddr >> 16); + command[2] = (u8)(pageaddr >> 8); + command[3] = 0; + + DEBUG(MTD_DEBUG_LEVEL3, "ERASE %s: (%x) %x %x %x [%i]\n", + do_block ? "block" : "page", + command[0], command[1], command[2], command[3], + pageaddr); + + status = spi_sync(spi, &msg); + (void) dataflash_waitready(spi); + + if (status < 0) { + printk(KERN_ERR "%s: erase %x, err %d\n", + spi->dev.bus_id, pageaddr, status); + /* REVISIT: can retry instr->retries times; or + * giveup and instr->fail_addr = instr->addr; + */ + continue; + } + + if (do_block) { + instr->addr += blocksize; + instr->len -= blocksize; + } else { + instr->addr += priv->page_size; + instr->len -= priv->page_size; + } + } + up(&priv->lock); + + /* Inform MTD subsystem that erase is complete */ + instr->state = MTD_ERASE_DONE; + mtd_erase_callback(instr); + + return 0; +} + +/* + * Read from the DataFlash device. + * from : Start offset in flash device + * len : Amount to read + * retlen : About of data actually read + * buf : Buffer containing the data + */ +static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct dataflash *priv = (struct dataflash *)mtd->priv; + struct spi_transfer x[2] = { { .tx_dma = 0, }, }; + struct spi_message msg; + unsigned int addr; + u8 *command; + int status; + + DEBUG(MTD_DEBUG_LEVEL2, "%s: read 0x%x..0x%x\n", + priv->spi->dev.bus_id, (unsigned)from, (unsigned)(from + len)); + + *retlen = 0; + + /* Sanity checks */ + if (!len) + return 0; + if (from + len > mtd->size) + return -EINVAL; + + /* Calculate flash page/byte address */ + addr = (((unsigned)from / priv->page_size) << priv->page_offset) + + ((unsigned)from % priv->page_size); + + command = priv->command; + + DEBUG(MTD_DEBUG_LEVEL3, "READ: (%x) %x %x %x\n", + command[0], command[1], command[2], command[3]); + + x[0].tx_buf = command; + x[0].len = 8; + x[1].rx_buf = buf; + x[1].len = len; + msg.transfers = x; + msg.n_transfer = 2; + + down(&priv->lock); + + /* Continuous read, max clock = f(car) which may be less than + * the peak rate available. Some chips support commands with + * fewer "don't care" bytes. Both buffers stay unchanged. + */ + command[0] = OP_READ_CONTINUOUS; + command[1] = (u8)(addr >> 16); + command[2] = (u8)(addr >> 8); + command[3] = (u8)(addr >> 0); + /* plus 4 "don't care" bytes */ + + status = spi_sync(priv->spi, &msg); + up(&priv->lock); + + if (status >= 0) { + *retlen = msg.actual_length - 8; + status = 0; + } else + DEBUG(MTD_DEBUG_LEVEL1, "%s: read %x..%x --> %d\n", + priv->spi->dev.bus_id, + (unsigned)from, (unsigned)(from + len), + status); + return status; +} + +/* + * Write to the DataFlash device. + * to : Start offset in flash device + * len : Amount to write + * retlen : Amount of data actually written + * buf : Buffer containing the data + */ +static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t * retlen, const u_char * buf) +{ + struct dataflash *priv = (struct dataflash *)mtd->priv; + struct spi_device *spi = priv->spi; + struct spi_transfer x[2] = { { .tx_dma = 0, }, }; + struct spi_message msg; + unsigned int pageaddr, addr, offset, writelen; + size_t remaining = len; + u_char *writebuf = (u_char *) buf; + int status = -EINVAL; + u8 *command; + + DEBUG(MTD_DEBUG_LEVEL2, "%s: write 0x%x..0x%x\n", + spi->dev.bus_id, (unsigned)to, (unsigned)(to + len)); + + *retlen = 0; + + /* Sanity checks */ + if (!len) + return 0; + if ((to + len) > mtd->size) + return -EINVAL; + + x[0].tx_buf = command = priv->command; + x[0].len = 4; + msg.transfers = x; + + pageaddr = ((unsigned)to / priv->page_size); + offset = ((unsigned)to % priv->page_size); + if (offset + len > priv->page_size) + writelen = priv->page_size - offset; + else + writelen = len; + + down(&priv->lock); + while (remaining > 0) { + DEBUG(MTD_DEBUG_LEVEL3, "write @ %i:%i len=%i\n", + pageaddr, offset, writelen); + + /* REVISIT: + * (a) each page in a sector must be rewritten at least + * once every 10K sibling erase/program operations. + * (b) for pages that are already erased, we could + * use WRITE+MWRITE not PROGRAM for ~30% speedup. + * (c) WRITE to buffer could be done while waiting for + * a previous MWRITE/MWERASE to complete ... + * (d) error handling here seems to be mostly missing. + * + * Two persistent bits per page, plus a per-sector counter, + * could support (a) and (b) ... we might consider using + * the second half of sector zero, which is just one block, + * to track that state. (On AT91, that sector should also + * support boot-from-DataFlash.) + */ + + addr = pageaddr << priv->page_offset; + + /* (1) Maybe transfer partial page to Buffer1 */ + if (writelen != priv->page_size) { + command[0] = OP_TRANSFER_BUF1; + command[1] = (addr & 0x00FF0000) >> 16; + command[2] = (addr & 0x0000FF00) >> 8; + command[3] = 0; + + DEBUG(MTD_DEBUG_LEVEL3, "TRANSFER: (%x) %x %x %x\n", + command[0], command[1], command[2], command[3]); + + msg.n_transfer = 1; + status = spi_sync(spi, &msg); + if (status < 0) + DEBUG(MTD_DEBUG_LEVEL1, "%s: xfer %u -> %d \n", + spi->dev.bus_id, addr, status); + + (void) dataflash_waitready(priv->spi); + } + + /* (2) Program full page via Buffer1 */ + addr += offset; + command[0] = OP_PROGRAM_VIA_BUF1; + command[1] = (addr & 0x00FF0000) >> 16; + command[2] = (addr & 0x0000FF00) >> 8; + command[3] = (addr & 0x000000FF); + + DEBUG(MTD_DEBUG_LEVEL3, "PROGRAM: (%x) %x %x %x\n", + command[0], command[1], command[2], command[3]); + + x[1].tx_buf = writebuf; + x[1].len = writelen; + msg.n_transfer = 2; + status = spi_sync(spi, &msg); + if (status < 0) + DEBUG(MTD_DEBUG_LEVEL1, "%s: pgm %u/%u -> %d \n", + spi->dev.bus_id, addr, writelen, status); + + (void) dataflash_waitready(priv->spi); + +#ifdef CONFIG_DATAFLASH_WRITE_VERIFY + + /* (3) Compare to Buffer1 */ + addr = pageaddr << priv->page_offset; + command[0] = OP_COMPARE_BUF1; + command[1] = (addr & 0x00FF0000) >> 16; + command[2] = (addr & 0x0000FF00) >> 8; + command[3] = 0; + + DEBUG(MTD_DEBUG_LEVEL3, "COMPARE: (%x) %x %x %x\n", + command[0], command[1], command[2], command[3]); + + msg.n_transfer = 1; + status = spi_sync(spi, &msg); + if (status < 0) + DEBUG(MTD_DEBUG_LEVEL1, "%s: compare %u -> %d \n", + spi->dev.bus_id, addr, status); + + status = dataflash_waitready(priv->spi); + + /* Check result of the compare operation */ + if ((status & (1 << 6)) == 1) { + printk(KERN_ERR "%s: compare page %u, err %d\n", + spi->dev.bus_id, pageaddr, status); + remaining = 0; + status = -EIO; + break; + } else + status = 0; + +#endif /* CONFIG_DATAFLASH_WRITE_VERIFY */ + + remaining = remaining - writelen; + pageaddr++; + offset = 0; + writebuf += writelen; + *retlen += writelen; + + if (remaining > priv->page_size) + writelen = priv->page_size; + else + writelen = remaining; + } + up(&priv->lock); + + return status; +} + +/* ......................................................................... */ + +/* + * Register DataFlash device with MTD subsystem. + */ +static int __devinit +add_dataflash(struct spi_device *spi, char *name, + int nr_pages, int pagesize, int pageoffset) +{ + struct dataflash *priv; + struct mtd_info *device; + struct flash_platform_data *pdata = spi->dev.platform_data; + + priv = (struct dataflash *) kzalloc(sizeof *priv, GFP_KERNEL); + if (!priv) + return -ENOMEM; + + init_MUTEX(&priv->lock); + priv->spi = spi; + priv->page_size = pagesize; + priv->page_offset = pageoffset; + + /* name must be usable with cmdlinepart */ + sprintf(priv->name, "spi%d.%d-%s", + spi->master->bus_num, spi->chip_select, + name); + + device = &priv->mtd; + device->name = (pdata && pdata->name) ? pdata->name : priv->name; + device->size = nr_pages * pagesize; + device->erasesize = pagesize; + device->owner = THIS_MODULE; + device->type = MTD_DATAFLASH; + device->flags = MTD_CAP_NORFLASH; + device->erase = dataflash_erase; + device->read = dataflash_read; + device->write = dataflash_write; + device->priv = priv; + + dev_info(&spi->dev, "%s (%d KBytes)\n", name, device->size/1024); + dev_set_drvdata(&spi->dev, priv); + + if (mtd_has_partitions()) { + struct mtd_partition *parts; + int nr_parts = 0; + +#ifdef CONFIG_MTD_CMDLINE_PARTS + static const char *part_probes[] = { "cmdlinepart", NULL, }; + + nr_parts = parse_mtd_partitions(device, part_probes, &parts, 0); +#endif + + if (nr_parts <= 0 && pdata && pdata->parts) { + parts = pdata->parts; + nr_parts = pdata->nr_parts; + } + + if (nr_parts > 0) { + priv->partitioned = 1; + return add_mtd_partitions(device, parts, nr_parts); + } + } else if (pdata->nr_parts) + dev_warn(&spi->dev, "ignoring %d default partitions on %s\n", + pdata->nr_parts, device->name); + + return add_mtd_device(device) == 1 ? -ENODEV : 0; +} + +/* + * Detect and initialize DataFlash device: + * + * Device Density ID code #Pages PageSize Offset + * AT45DB011B 1Mbit (128K) xx0011xx (0x0c) 512 264 9 + * AT45DB021B 2Mbit (256K) xx0101xx (0x14) 1025 264 9 + * AT45DB041B 4Mbit (512K) xx0111xx (0x1c) 2048 264 9 + * AT45DB081B 8Mbit (1M) xx1001xx (0x24) 4096 264 9 + * AT45DB0161B 16Mbit (2M) xx1011xx (0x2c) 4096 528 10 + * AT45DB0321B 32Mbit (4M) xx1101xx (0x34) 8192 528 10 + * AT45DB0642 64Mbit (8M) xx111xxx (0x3c) 8192 1056 11 + * AT45DB1282 128Mbit (16M) xx0100xx (0x10) 16384 1056 11 + */ +static int __devinit dataflash_probe(struct spi_device *spi) +{ + int status; + + status = dataflash_status(spi); + if (status <= 0 || status == 0xff) { + DEBUG(MTD_DEBUG_LEVEL1, "%s: status error %d\n", + spi->dev.bus_id, status); + if (status == 0xff) + status = -ENODEV; + return status; + } + + /* if there's a device there, assume it's dataflash. + * board setup should have set spi->max_speed_max to + * match f(car) for continuous reads, mode 0 or 3. + */ + switch (status & 0x3c) { + case 0x0c: /* 0 0 1 1 x x */ + status = add_dataflash(spi, "AT45DB011B", 512, 264, 9); + break; + case 0x14: /* 0 1 0 1 x x */ + status = add_dataflash(spi, "AT45DB021B", 1025, 264, 9); + break; + case 0x1c: /* 0 1 1 1 x x */ + status = add_dataflash(spi, "AT45DB041x", 2048, 264, 9); + break; + case 0x24: /* 1 0 0 1 x x */ + status = add_dataflash(spi, "AT45DB081B", 4096, 264, 9); + break; + case 0x2c: /* 1 0 1 1 x x */ + status = add_dataflash(spi, "AT45DB161x", 4096, 528, 10); + break; + case 0x34: /* 1 1 0 1 x x */ + status = add_dataflash(spi, "AT45DB321x", 8192, 528, 10); + break; + case 0x38: /* 1 1 1 x x x */ + case 0x3c: + status = add_dataflash(spi, "AT45DB642x", 8192, 1056, 11); + break; + /* obsolete AT45DB1282 not (yet?) supported */ + default: + DEBUG(MTD_DEBUG_LEVEL1, "%s: unsupported device (%x)\n", + spi->dev.bus_id, status & 0x3c); + status = -ENODEV; + } + + if (status < 0) + DEBUG(MTD_DEBUG_LEVEL1, "%s: add_dataflash --> %d\n", + spi->dev.bus_id, status); + + return status; +} + +static int __devexit dataflash_remove(struct spi_device *spi) +{ + struct dataflash *flash = dev_get_drvdata(&spi->dev); + int status; + + DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", spi->dev.bus_id); + + if (mtd_has_partitions() && flash->partitioned) + status = del_mtd_partitions(&flash->mtd); + else + status = del_mtd_device(&flash->mtd); + if (status == 0) + kfree(flash); + return status; +} + +static struct spi_driver dataflash_driver = { + .driver = { + .name = "mtd_dataflash", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + + .probe = dataflash_probe, + .remove = __devexit_p(dataflash_remove), + + /* FIXME: investigate suspend and resume... */ +}; + +static int __init dataflash_init(void) +{ + return spi_register_driver(&dataflash_driver); +} +module_init(dataflash_init); + +static void __exit dataflash_exit(void) +{ + spi_unregister_driver(&dataflash_driver); +} +module_exit(dataflash_exit); + + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Andrew Victor, David Brownell"); +MODULE_DESCRIPTION("MTD DataFlash driver"); diff --git a/include/linux/spi/flash.h b/include/linux/spi/flash.h new file mode 100644 index 00000000000..2ce6558bf3f --- /dev/null +++ b/include/linux/spi/flash.h @@ -0,0 +1,27 @@ +#ifndef LINUX_SPI_FLASH_H +#define LINUX_SPI_FLASH_H + +struct mtd_partition; + +/** + * struct flash_platform_data: board-specific flash data + * @name: optional flash device name (eg, as used with mtdparts=) + * @parts: optional array of mtd_partitions for static partitioning + * @nr_parts: number of mtd_partitions for static partitoning + * + * Board init code (in arch/.../mach-xxx/board-yyy.c files) can + * provide information about SPI flash parts (such as DataFlash) to + * help set up the device and its appropriate default partitioning. + * + * Note that for DataFlash, sizes for pages, blocks, and sectors are + * rarely powers of two; and partitions should be sector-aligned. + */ +struct flash_platform_data { + char *name; + struct mtd_partition *parts; + unsigned int nr_parts; + + /* we'll likely add more ... use JEDEC IDs, etc */ +}; + +#endif -- GitLab From b885244eb2628e0b8206e7edaaa6a314da78e9a4 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sun, 8 Jan 2006 13:34:23 -0800 Subject: [PATCH 155/465] [PATCH] spi: add spi_driver to SPI framework This is a refresh of the "Simple SPI Framework" found in 2.6.15-rc3-mm1 which makes the following changes: * There's now a "struct spi_driver". This increase the footprint of the core a bit, since it now includes code to do what the driver core was previously handling directly. Documentation and comments were updated to match. * spi_alloc_master() now does class_device_initialize(), so it can at least be refcounted before spi_register_master(). To match, spi_register_master() switched over to class_device_add(). * States explicitly that after transfer errors, spi_devices will be deselected. We want fault recovery procedures to work the same for all controller drivers. * Minor tweaks: controller_data no longer points to readonly data; prevent some potential cast-from-null bugs with container_of calls; clarifies some existing kerneldoc, And a few small cleanups. Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- Documentation/spi/spi-summary | 52 +++++++++------ drivers/spi/spi.c | 118 +++++++++++++++++++++++++--------- include/linux/spi/spi.h | 75 ++++++++++++++------- 3 files changed, 170 insertions(+), 75 deletions(-) diff --git a/Documentation/spi/spi-summary b/Documentation/spi/spi-summary index 00497f95ca4..c6152d1ff2b 100644 --- a/Documentation/spi/spi-summary +++ b/Documentation/spi/spi-summary @@ -1,18 +1,19 @@ Overview of Linux kernel SPI support ==================================== -22-Nov-2005 +02-Dec-2005 What is SPI? ------------ -The "Serial Peripheral Interface" (SPI) is a four-wire point-to-point -serial link used to connect microcontrollers to sensors and memory. +The "Serial Peripheral Interface" (SPI) is a synchronous four wire serial +link used to connect microcontrollers to sensors, memory, and peripherals. The three signal wires hold a clock (SCLK, often on the order of 10 MHz), and parallel data lines with "Master Out, Slave In" (MOSI) or "Master In, Slave Out" (MISO) signals. (Other names are also used.) There are four clocking modes through which data is exchanged; mode-0 and mode-3 are most -commonly used. +commonly used. Each clock cycle shifts data out and data in; the clock +doesn't cycle except when there is data to shift. SPI masters may use a "chip select" line to activate a given SPI slave device, so those three signal wires may be connected to several chips @@ -79,11 +80,18 @@ The header file includes kerneldoc, as does the main source code, and you should certainly read that. This is just an overview, so you get the big picture before the details. +SPI requests always go into I/O queues. Requests for a given SPI device +are always executed in FIFO order, and complete asynchronously through +completion callbacks. There are also some simple synchronous wrappers +for those calls, including ones for common transaction types like writing +a command and then reading its response. + There are two types of SPI driver, here called: Controller drivers ... these are often built in to System-On-Chip processors, and often support both Master and Slave roles. These drivers touch hardware registers and may use DMA. + Or they can be PIO bitbangers, needing just GPIO pins. Protocol drivers ... these pass messages through the controller driver to communicate with a Slave or Master device on the @@ -116,11 +124,6 @@ shows up in sysfs in several locations: managing bus "B". All the spiB.* devices share the same physical SPI bus segment, with SCLK, MOSI, and MISO. -The basic I/O primitive submits an asynchronous message to an I/O queue -maintained by the controller driver. A completion callback is issued -asynchronously when the data transfer(s) in that message completes. -There are also some simple synchronous wrappers for those calls. - How does board-specific init code declare SPI devices? ------------------------------------------------------ @@ -263,33 +266,40 @@ would just be another kernel driver, probably offering some lowlevel access through aio_read(), aio_write(), and ioctl() calls and using the standard userspace sysfs mechanisms to bind to a given SPI device. -SPI protocol drivers are normal device drivers, with no more wrapper -than needed by platform devices: +SPI protocol drivers somewhat resemble platform device drivers: + + static struct spi_driver CHIP_driver = { + .driver = { + .name = "CHIP", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, - static struct device_driver CHIP_driver = { - .name = "CHIP", - .bus = &spi_bus_type, .probe = CHIP_probe, - .remove = __exit_p(CHIP_remove), + .remove = __devexit_p(CHIP_remove), .suspend = CHIP_suspend, .resume = CHIP_resume, }; -The SPI core will autmatically attempt to bind this driver to any SPI +The driver core will autmatically attempt to bind this driver to any SPI device whose board_info gave a modalias of "CHIP". Your probe() code might look like this unless you're creating a class_device: - static int __init CHIP_probe(struct device *dev) + static int __devinit CHIP_probe(struct spi_device *spi) { - struct spi_device *spi = to_spi_device(dev); struct CHIP *chip; - struct CHIP_platform_data *pdata = dev->platform_data; + struct CHIP_platform_data *pdata; + + /* assuming the driver requires board-specific data: */ + pdata = &spi->dev.platform_data; + if (!pdata) + return -ENODEV; /* get memory for driver's per-chip state */ chip = kzalloc(sizeof *chip, GFP_KERNEL); if (!chip) return -ENOMEM; - dev_set_drvdata(dev, chip); + dev_set_drvdata(&spi->dev, chip); ... etc return 0; @@ -328,6 +338,8 @@ the driver guarantees that it won't submit any more such messages. - The basic I/O primitive is spi_async(). Async requests may be issued in any context (irq handler, task, etc) and completion is reported using a callback provided with the message. + After any detected error, the chip is deselected and processing + of that spi_message is aborted. - There are also synchronous wrappers like spi_sync(), and wrappers like spi_read(), spi_write(), and spi_write_then_read(). These diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 7cd356b1764..2ecb86cb368 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -26,13 +26,9 @@ #include -/* SPI bustype and spi_master class are registered during early boot, - * usually before board init code provides the SPI device tables, and - * are available later when driver init code needs them. - * - * Drivers for SPI devices started out like those for platform bus - * devices. But both have changed in 2.6.15; maybe this should get - * an "spi_driver" structure at some point (not currently needed) +/* SPI bustype and spi_master class are registered after board init code + * provides the SPI device tables, ensuring that both are present by the + * time controller driver registration causes spi_devices to "enumerate". */ static void spidev_release(struct device *dev) { @@ -83,10 +79,7 @@ static int spi_uevent(struct device *dev, char **envp, int num_envp, #ifdef CONFIG_PM -/* Suspend/resume in "struct device_driver" don't really need that - * strange third parameter, so we just make it a constant and expect - * SPI drivers to ignore it just like most platform drivers do. - * +/* * NOTE: the suspend() method for an spi_master controller driver * should verify that all its child devices are marked as suspended; * suspend requests delivered through sysfs power/state files don't @@ -94,13 +87,14 @@ static int spi_uevent(struct device *dev, char **envp, int num_envp, */ static int spi_suspend(struct device *dev, pm_message_t message) { - int value; + int value; + struct spi_driver *drv = to_spi_driver(dev->driver); - if (!dev->driver || !dev->driver->suspend) + if (!drv || !drv->suspend) return 0; /* suspend will stop irqs and dma; no more i/o */ - value = dev->driver->suspend(dev, message); + value = drv->suspend(to_spi_device(dev), message); if (value == 0) dev->power.power_state = message; return value; @@ -108,13 +102,14 @@ static int spi_suspend(struct device *dev, pm_message_t message) static int spi_resume(struct device *dev) { - int value; + int value; + struct spi_driver *drv = to_spi_driver(dev->driver); - if (!dev->driver || !dev->driver->resume) + if (!drv || !drv->resume) return 0; /* resume may restart the i/o queue */ - value = dev->driver->resume(dev); + value = drv->resume(to_spi_device(dev)); if (value == 0) dev->power.power_state = PMSG_ON; return value; @@ -135,6 +130,41 @@ struct bus_type spi_bus_type = { }; EXPORT_SYMBOL_GPL(spi_bus_type); + +static int spi_drv_probe(struct device *dev) +{ + const struct spi_driver *sdrv = to_spi_driver(dev->driver); + + return sdrv->probe(to_spi_device(dev)); +} + +static int spi_drv_remove(struct device *dev) +{ + const struct spi_driver *sdrv = to_spi_driver(dev->driver); + + return sdrv->remove(to_spi_device(dev)); +} + +static void spi_drv_shutdown(struct device *dev) +{ + const struct spi_driver *sdrv = to_spi_driver(dev->driver); + + sdrv->shutdown(to_spi_device(dev)); +} + +int spi_register_driver(struct spi_driver *sdrv) +{ + sdrv->driver.bus = &spi_bus_type; + if (sdrv->probe) + sdrv->driver.probe = spi_drv_probe; + if (sdrv->remove) + sdrv->driver.remove = spi_drv_remove; + if (sdrv->shutdown) + sdrv->driver.shutdown = spi_drv_shutdown; + return driver_register(&sdrv->driver); +} +EXPORT_SYMBOL_GPL(spi_register_driver); + /*-------------------------------------------------------------------------*/ /* SPI devices should normally not be created by SPI device drivers; that @@ -208,13 +238,15 @@ spi_new_device(struct spi_master *master, struct spi_board_info *chip) if (status < 0) { dev_dbg(dev, "can't %s %s, status %d\n", "add", proxy->dev.bus_id, status); -fail: - class_device_put(&master->cdev); - kfree(proxy); - return NULL; + goto fail; } dev_dbg(dev, "registered child %s\n", proxy->dev.bus_id); return proxy; + +fail: + class_device_put(&master->cdev); + kfree(proxy); + return NULL; } EXPORT_SYMBOL_GPL(spi_new_device); @@ -237,11 +269,11 @@ spi_register_board_info(struct spi_board_info const *info, unsigned n) { struct boardinfo *bi; - bi = kmalloc (sizeof (*bi) + n * sizeof (*info), GFP_KERNEL); + bi = kmalloc(sizeof(*bi) + n * sizeof *info, GFP_KERNEL); if (!bi) return -ENOMEM; bi->n_board_info = n; - memcpy(bi->board_info, info, n * sizeof (*info)); + memcpy(bi->board_info, info, n * sizeof *info); down(&board_lock); list_add_tail(&bi->list, &board_list); @@ -330,6 +362,7 @@ spi_alloc_master(struct device *dev, unsigned size) if (!master) return NULL; + class_device_initialize(&master->cdev); master->cdev.class = &spi_master_class; master->cdev.dev = get_device(dev); class_set_devdata(&master->cdev, &master[1]); @@ -366,7 +399,7 @@ spi_register_master(struct spi_master *master) /* convention: dynamically assigned bus IDs count down from the max */ if (master->bus_num == 0) { master->bus_num = atomic_dec_return(&dyn_bus_id); - dynamic = 0; + dynamic = 1; } /* register the device, then userspace will see it. @@ -374,11 +407,9 @@ spi_register_master(struct spi_master *master) */ snprintf(master->cdev.class_id, sizeof master->cdev.class_id, "spi%u", master->bus_num); - status = class_device_register(&master->cdev); - if (status < 0) { - class_device_put(&master->cdev); + status = class_device_add(&master->cdev); + if (status < 0) goto done; - } dev_dbg(dev, "registered master %s%s\n", master->cdev.class_id, dynamic ? " (dynamic)" : ""); @@ -491,6 +522,7 @@ static u8 *buf; * This performs a half duplex MicroWire style transaction with the * device, sending txbuf and then reading rxbuf. The return value * is zero for success, else a negative errno status code. + * This call may only be used from a context that may sleep. * * Parameters to this routine are always copied using a small buffer, * large transfers should use use spi_{async,sync}() calls with @@ -553,16 +585,38 @@ EXPORT_SYMBOL_GPL(spi_write_then_read); static int __init spi_init(void) { + int status; + buf = kmalloc(SPI_BUFSIZ, SLAB_KERNEL); - if (!buf) - return -ENOMEM; + if (!buf) { + status = -ENOMEM; + goto err0; + } + + status = bus_register(&spi_bus_type); + if (status < 0) + goto err1; - bus_register(&spi_bus_type); - class_register(&spi_master_class); + status = class_register(&spi_master_class); + if (status < 0) + goto err2; return 0; + +err2: + bus_unregister(&spi_bus_type); +err1: + kfree(buf); + buf = NULL; +err0: + return status; } + /* board_info is normally registered in arch_initcall(), * but even essential drivers wait till later + * + * REVISIT only boardinfo really needs static linking. the rest (device and + * driver registration) _could_ be dynamically linked (modular) ... costs + * include needing to have boardinfo data structures be much more public. */ subsys_initcall(spi_init); diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 51a6769114d..c851b3d1320 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -20,13 +20,8 @@ #define __LINUX_SPI_H /* - * INTERFACES between SPI master drivers and infrastructure + * INTERFACES between SPI master-side drivers and SPI infrastructure. * (There's no SPI slave support for Linux yet...) - * - * A "struct device_driver" for an spi_device uses "spi_bus_type" and - * needs no special API wrappers (much like platform_bus). These drivers - * are bound to devices based on their names (much like platform_bus), - * and are available in dev->driver. */ extern struct bus_type spi_bus_type; @@ -46,8 +41,8 @@ extern struct bus_type spi_bus_type; * @irq: Negative, or the number passed to request_irq() to receive * interrupts from this device. * @controller_state: Controller's runtime state - * @controller_data: Static board-specific definitions for controller, such - * as FIFO initialization parameters; from board_info.controller_data + * @controller_data: Board-specific definitions for controller, such as + * FIFO initialization parameters; from board_info.controller_data * * An spi_device is used to interchange data between an SPI slave * (usually a discrete chip) and CPU memory. @@ -63,31 +58,32 @@ struct spi_device { u32 max_speed_hz; u8 chip_select; u8 mode; -#define SPI_CPHA 0x01 /* clock phase */ -#define SPI_CPOL 0x02 /* clock polarity */ +#define SPI_CPHA 0x01 /* clock phase */ +#define SPI_CPOL 0x02 /* clock polarity */ #define SPI_MODE_0 (0|0) -#define SPI_MODE_1 (0|SPI_CPHA) +#define SPI_MODE_1 (0|SPI_CPHA) /* (original MicroWire) */ #define SPI_MODE_2 (SPI_CPOL|0) #define SPI_MODE_3 (SPI_CPOL|SPI_CPHA) -#define SPI_CS_HIGH 0x04 /* chipselect active high? */ +#define SPI_CS_HIGH 0x04 /* chipselect active high? */ u8 bits_per_word; int irq; void *controller_state; - const void *controller_data; + void *controller_data; const char *modalias; // likely need more hooks for more protocol options affecting how - // the controller talks to its chips, like: + // the controller talks to each chip, like: // - bit order (default is wordwise msb-first) // - memory packing (12 bit samples into low bits, others zeroed) // - priority + // - drop chipselect after each word // - chipselect delays // - ... }; static inline struct spi_device *to_spi_device(struct device *dev) { - return container_of(dev, struct spi_device, dev); + return dev ? container_of(dev, struct spi_device, dev) : NULL; } /* most drivers won't need to care about device refcounting */ @@ -117,12 +113,38 @@ static inline void spi_set_ctldata(struct spi_device *spi, void *state) struct spi_message; + +struct spi_driver { + int (*probe)(struct spi_device *spi); + int (*remove)(struct spi_device *spi); + void (*shutdown)(struct spi_device *spi); + int (*suspend)(struct spi_device *spi, pm_message_t mesg); + int (*resume)(struct spi_device *spi); + struct device_driver driver; +}; + +static inline struct spi_driver *to_spi_driver(struct device_driver *drv) +{ + return drv ? container_of(drv, struct spi_driver, driver) : NULL; +} + +extern int spi_register_driver(struct spi_driver *sdrv); + +static inline void spi_unregister_driver(struct spi_driver *sdrv) +{ + if (!sdrv) + return; + driver_unregister(&sdrv->driver); +} + + + /** * struct spi_master - interface to SPI master controller * @cdev: class interface to this driver * @bus_num: board-specific (and often SOC-specific) identifier for a * given SPI controller. - * @num_chipselects: chipselects are used to distinguish individual + * @num_chipselect: chipselects are used to distinguish individual * SPI slaves, and are numbered from zero to num_chipselects. * each slave has a chipselect signal, but it's common that not * every chipselect is connected to a slave. @@ -275,7 +297,8 @@ struct spi_transfer { * addresses for each transfer buffer * @complete: called to report transaction completions * @context: the argument to complete() when it's called - * @actual_length: how many bytes were transferd + * @actual_length: the total number of bytes that were transferred in all + * successful segments * @status: zero for success, else negative errno * @queue: for use by whichever driver currently owns the message * @state: for use by whichever driver currently owns the message @@ -295,7 +318,7 @@ struct spi_message { * * Some controller drivers (message-at-a-time queue processing) * could provide that as their default scheduling algorithm. But - * others (with multi-message pipelines) would need a flag to + * others (with multi-message pipelines) could need a flag to * tell them about such special cases. */ @@ -346,6 +369,13 @@ spi_setup(struct spi_device *spi) * FIFO order, messages may go to different devices in other orders. * Some device might be higher priority, or have various "hard" access * time requirements, for example. + * + * On detection of any fault during the transfer, processing of + * the entire message is aborted, and the device is deselected. + * Until returning from the associated message completion callback, + * no other spi_message queued to that device will be processed. + * (This rule applies equally to all the synchronous transfer calls, + * which are wrappers around this core asynchronous primitive.) */ static inline int spi_async(struct spi_device *spi, struct spi_message *message) @@ -484,12 +514,12 @@ struct spi_board_info { * "modalias" is normally the driver name. * * platform_data goes to spi_device.dev.platform_data, - * controller_data goes to spi_device.platform_data, + * controller_data goes to spi_device.controller_data, * irq is copied too */ char modalias[KOBJ_NAME_LEN]; const void *platform_data; - const void *controller_data; + void *controller_data; int irq; /* slower signaling on noisy or low voltage boards */ @@ -525,9 +555,8 @@ spi_register_board_info(struct spi_board_info const *info, unsigned n) /* If you're hotplugging an adapter with devices (parport, usb, etc) - * use spi_new_device() to describe each device. You can also call - * spi_unregister_device() to get start making that device vanish, - * but normally that would be handled by spi_unregister_master(). + * use spi_new_device() to describe each device. You would then call + * spi_unregister_device() to start making that device vanish. */ extern struct spi_device * spi_new_device(struct spi_master *, struct spi_board_info *); -- GitLab From 0c868461fcb8413cb9f691d68e5b99b0fd3c0737 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sun, 8 Jan 2006 13:34:25 -0800 Subject: [PATCH 156/465] [PATCH] SPI core tweaks, bugfix This includes various updates to the SPI core: - Fixes a driver model refcount bug in spi_unregister_master() paths. - The spi_master structures now have wrappers which help keep drivers from needing class-level get/put for device data or for refcounts. - Check for a few setup errors that would cause oopsing later. - Docs say more about memory management. Highlights the use of DMA-safe i/o buffers, and zero-initializing spi_message and such metadata. - Provide a simple alloc/free for spi_message and its spi_transfer; this is only one of the possible memory management policies. Nothing to break code that already works. Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- Documentation/spi/spi-summary | 16 ++++++++ drivers/spi/spi.c | 45 +++++++++++++-------- include/linux/spi/spi.h | 75 ++++++++++++++++++++++++++++++++--- 3 files changed, 113 insertions(+), 23 deletions(-) diff --git a/Documentation/spi/spi-summary b/Documentation/spi/spi-summary index c6152d1ff2b..761debf748e 100644 --- a/Documentation/spi/spi-summary +++ b/Documentation/spi/spi-summary @@ -363,6 +363,22 @@ upper boundaries might include sysfs (especially for sensor readings), the input layer, ALSA, networking, MTD, the character device framework, or other Linux subsystems. +Note that there are two types of memory your driver must manage as part +of interacting with SPI devices. + + - I/O buffers use the usual Linux rules, and must be DMA-safe. + You'd normally allocate them from the heap or free page pool. + Don't use the stack, or anything that's declared "static". + + - The spi_message and spi_transfer metadata used to glue those + I/O buffers into a group of protocol transactions. These can + be allocated anywhere it's convenient, including as part of + other allocate-once driver data structures. Zero-init these. + +If you like, spi_message_alloc() and spi_message_free() convenience +routines are available to allocate and zero-initialize an spi_message +with several transfers. + How do I write an "SPI Master Controller Driver"? ------------------------------------------------- diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 2ecb86cb368..3ecedccdb96 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -38,7 +38,7 @@ static void spidev_release(struct device *dev) if (spi->master->cleanup) spi->master->cleanup(spi); - class_device_put(&spi->master->cdev); + spi_master_put(spi->master); kfree(dev); } @@ -90,7 +90,7 @@ static int spi_suspend(struct device *dev, pm_message_t message) int value; struct spi_driver *drv = to_spi_driver(dev->driver); - if (!drv || !drv->suspend) + if (!drv->suspend) return 0; /* suspend will stop irqs and dma; no more i/o */ @@ -105,7 +105,7 @@ static int spi_resume(struct device *dev) int value; struct spi_driver *drv = to_spi_driver(dev->driver); - if (!drv || !drv->resume) + if (!drv->resume) return 0; /* resume may restart the i/o queue */ @@ -198,7 +198,7 @@ spi_new_device(struct spi_master *master, struct spi_board_info *chip) /* NOTE: caller did any chip->bus_num checks necessary */ - if (!class_device_get(&master->cdev)) + if (!spi_master_get(master)) return NULL; proxy = kzalloc(sizeof *proxy, GFP_KERNEL); @@ -244,7 +244,7 @@ spi_new_device(struct spi_master *master, struct spi_board_info *chip) return proxy; fail: - class_device_put(&master->cdev); + spi_master_put(master); kfree(proxy); return NULL; } @@ -324,8 +324,6 @@ static void spi_master_release(struct class_device *cdev) struct spi_master *master; master = container_of(cdev, struct spi_master, cdev); - put_device(master->cdev.dev); - master->cdev.dev = NULL; kfree(master); } @@ -339,8 +337,9 @@ static struct class spi_master_class = { /** * spi_alloc_master - allocate SPI master controller * @dev: the controller, possibly using the platform_bus - * @size: how much driver-private data to preallocate; a pointer to this - * memory in the class_data field of the returned class_device + * @size: how much driver-private data to preallocate; the pointer to this + * memory is in the class_data field of the returned class_device, + * accessible with spi_master_get_devdata(). * * This call is used only by SPI master controller drivers, which are the * only ones directly touching chip registers. It's how they allocate @@ -350,14 +349,17 @@ static struct class spi_master_class = { * master structure on success, else NULL. * * The caller is responsible for assigning the bus number and initializing - * the master's methods before calling spi_add_master(), or else (on error) - * calling class_device_put() to prevent a memory leak. + * the master's methods before calling spi_add_master(); and (after errors + * adding the device) calling spi_master_put() to prevent a memory leak. */ struct spi_master * __init_or_module spi_alloc_master(struct device *dev, unsigned size) { struct spi_master *master; + if (!dev) + return NULL; + master = kzalloc(size + sizeof *master, SLAB_KERNEL); if (!master) return NULL; @@ -365,7 +367,7 @@ spi_alloc_master(struct device *dev, unsigned size) class_device_initialize(&master->cdev); master->cdev.class = &spi_master_class; master->cdev.dev = get_device(dev); - class_set_devdata(&master->cdev, &master[1]); + spi_master_set_devdata(master, &master[1]); return master; } @@ -387,6 +389,8 @@ EXPORT_SYMBOL_GPL(spi_alloc_master); * * This must be called from context that can sleep. It returns zero on * success, else a negative error code (dropping the master's refcount). + * After a successful return, the caller is responsible for calling + * spi_unregister_master(). */ int __init_or_module spi_register_master(struct spi_master *master) @@ -396,6 +400,9 @@ spi_register_master(struct spi_master *master) int status = -ENODEV; int dynamic = 0; + if (!dev) + return -ENODEV; + /* convention: dynamically assigned bus IDs count down from the max */ if (master->bus_num == 0) { master->bus_num = atomic_dec_return(&dyn_bus_id); @@ -425,7 +432,7 @@ EXPORT_SYMBOL_GPL(spi_register_master); static int __unregister(struct device *dev, void *unused) { /* note: before about 2.6.14-rc1 this would corrupt memory: */ - device_unregister(dev); + spi_unregister_device(to_spi_device(dev)); return 0; } @@ -440,8 +447,9 @@ static int __unregister(struct device *dev, void *unused) */ void spi_unregister_master(struct spi_master *master) { - class_device_unregister(&master->cdev); (void) device_for_each_child(master->cdev.dev, NULL, __unregister); + class_device_unregister(&master->cdev); + master->cdev.dev = NULL; } EXPORT_SYMBOL_GPL(spi_unregister_master); @@ -487,6 +495,9 @@ EXPORT_SYMBOL_GPL(spi_busnum_to_master); * by leaving it selected in anticipation that the next message will go * to the same chip. (That may increase power usage.) * + * Also, the caller is guaranteeing that the memory associated with the + * message will not be freed before this call returns. + * * The return value is a negative error code if the message could not be * submitted, else zero. When the value is zero, then message->status is * also defined: it's the completion code for the transfer, either zero @@ -524,9 +535,9 @@ static u8 *buf; * is zero for success, else a negative errno status code. * This call may only be used from a context that may sleep. * - * Parameters to this routine are always copied using a small buffer, - * large transfers should use use spi_{async,sync}() calls with - * dma-safe buffers. + * Parameters to this routine are always copied using a small buffer; + * performance-sensitive or bulk transfer code should instead use + * spi_{async,sync}() calls with dma-safe buffers. */ int spi_write_then_read(struct spi_device *spi, const u8 *txbuf, unsigned n_tx, diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index c851b3d1320..6a41e2650b2 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -60,8 +60,8 @@ struct spi_device { u8 mode; #define SPI_CPHA 0x01 /* clock phase */ #define SPI_CPOL 0x02 /* clock polarity */ -#define SPI_MODE_0 (0|0) -#define SPI_MODE_1 (0|SPI_CPHA) /* (original MicroWire) */ +#define SPI_MODE_0 (0|0) /* (original MicroWire) */ +#define SPI_MODE_1 (0|SPI_CPHA) #define SPI_MODE_2 (SPI_CPOL|0) #define SPI_MODE_3 (SPI_CPOL|SPI_CPHA) #define SPI_CS_HIGH 0x04 /* chipselect active high? */ @@ -209,6 +209,30 @@ struct spi_master { void (*cleanup)(const struct spi_device *spi); }; +static inline void *spi_master_get_devdata(struct spi_master *master) +{ + return class_get_devdata(&master->cdev); +} + +static inline void spi_master_set_devdata(struct spi_master *master, void *data) +{ + class_set_devdata(&master->cdev, data); +} + +static inline struct spi_master *spi_master_get(struct spi_master *master) +{ + if (!master || !class_device_get(&master->cdev)) + return NULL; + return master; +} + +static inline void spi_master_put(struct spi_master *master) +{ + if (master) + class_device_put(&master->cdev); +} + + /* the spi driver core manages memory for the spi_master classdev */ extern struct spi_master * spi_alloc_master(struct device *host, unsigned size); @@ -271,11 +295,17 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum); * stay selected until the next transfer. This is purely a performance * hint; the controller driver may need to select a different device * for the next message. + * + * The code that submits an spi_message (and its spi_transfers) + * to the lower layers is responsible for managing its memory. + * Zero-initialize every field you don't set up explicitly, to + * insulate against future API updates. */ struct spi_transfer { /* it's ok if tx_buf == rx_buf (right?) * for MicroWire, one buffer must be null - * buffers must work with dma_*map_single() calls + * buffers must work with dma_*map_single() calls, unless + * spi_message.is_dma_mapped reports a pre-existing mapping */ const void *tx_buf; void *rx_buf; @@ -302,6 +332,11 @@ struct spi_transfer { * @status: zero for success, else negative errno * @queue: for use by whichever driver currently owns the message * @state: for use by whichever driver currently owns the message + * + * The code that submits an spi_message (and its spi_transfers) + * to the lower layers is responsible for managing its memory. + * Zero-initialize every field you don't set up explicitly, to + * insulate against future API updates. */ struct spi_message { struct spi_transfer *transfers; @@ -336,6 +371,29 @@ struct spi_message { void *state; }; +/* It's fine to embed message and transaction structures in other data + * structures so long as you don't free them while they're in use. + */ + +static inline struct spi_message *spi_message_alloc(unsigned ntrans, gfp_t flags) +{ + struct spi_message *m; + + m = kzalloc(sizeof(struct spi_message) + + ntrans * sizeof(struct spi_transfer), + flags); + if (m) { + m->transfers = (void *)(m + 1); + m->n_transfer = ntrans; + } + return m; +} + +static inline void spi_message_free(struct spi_message *m) +{ + kfree(m); +} + /** * spi_setup -- setup SPI mode and clock rate * @spi: the device whose settings are being modified @@ -363,7 +421,10 @@ spi_setup(struct spi_device *spi) * The completion callback is invoked in a context which can't sleep. * Before that invocation, the value of message->status is undefined. * When the callback is issued, message->status holds either zero (to - * indicate complete success) or a negative error code. + * indicate complete success) or a negative error code. After that + * callback returns, the driver which issued the transfer request may + * deallocate the associated memory; it's no longer in use by any SPI + * core or controller driver code. * * Note that although all messages to a spi_device are handled in * FIFO order, messages may go to different devices in other orders. @@ -445,6 +506,7 @@ spi_read(struct spi_device *spi, u8 *buf, size_t len) return spi_sync(spi, &m); } +/* this copies txbuf and rxbuf data; for small transfers only! */ extern int spi_write_then_read(struct spi_device *spi, const u8 *txbuf, unsigned n_tx, u8 *rxbuf, unsigned n_rx); @@ -555,8 +617,9 @@ spi_register_board_info(struct spi_board_info const *info, unsigned n) /* If you're hotplugging an adapter with devices (parport, usb, etc) - * use spi_new_device() to describe each device. You would then call - * spi_unregister_device() to start making that device vanish. + * use spi_new_device() to describe each device. You can also call + * spi_unregister_device() to start making that device vanish, but + * normally that would be handled by spi_unregister_master(). */ extern struct spi_device * spi_new_device(struct spi_master *, struct spi_board_info *); -- GitLab From 2e5a7bd978bf4118a0c8edf2e6ff81d0a72fee47 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sun, 8 Jan 2006 13:34:25 -0800 Subject: [PATCH 157/465] [PATCH] spi: ads7836 uses spi_driver This updates the ads7864 driver to use the new "spi_driver" struct, and includes some minor unrelated cleanup. Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/input/touchscreen/ads7846.c | 84 ++++++++++++++--------------- include/linux/spi/ads7846.h | 2 +- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 24ff6c5a402..c741776ef3b 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -345,19 +345,15 @@ static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs) /*--------------------------------------------------------------------------*/ -/* non-empty "extra" is needed before 2.6.14-git5 or so */ -#define EXTRA // , u32 level -#define EXTRA2 // , 0 - static int -ads7846_suspend(struct device *dev, pm_message_t message EXTRA) +ads7846_suspend(struct spi_device *spi, pm_message_t message) { - struct ads7846 *ts = dev_get_drvdata(dev); + struct ads7846 *ts = dev_get_drvdata(&spi->dev); unsigned long flags; spin_lock_irqsave(&ts->lock, flags); - ts->spi->dev.power.power_state = message; + spi->dev.power.power_state = message; /* are we waiting for IRQ, or polling? */ if (!ts->pendown) { @@ -387,36 +383,35 @@ ads7846_suspend(struct device *dev, pm_message_t message EXTRA) return 0; } -static int ads7846_resume(struct device *dev EXTRA) +static int ads7846_resume(struct spi_device *spi) { - struct ads7846 *ts = dev_get_drvdata(dev); + struct ads7846 *ts = dev_get_drvdata(&spi->dev); ts->irq_disabled = 0; enable_irq(ts->spi->irq); - dev->power.power_state = PMSG_ON; + spi->dev.power.power_state = PMSG_ON; return 0; } -static int __init ads7846_probe(struct device *dev) +static int __devinit ads7846_probe(struct spi_device *spi) { - struct spi_device *spi = to_spi_device(dev); struct ads7846 *ts; - struct ads7846_platform_data *pdata = dev->platform_data; + struct ads7846_platform_data *pdata = spi->dev.platform_data; struct spi_transfer *x; if (!spi->irq) { - dev_dbg(dev, "no IRQ?\n"); + dev_dbg(&spi->dev, "no IRQ?\n"); return -ENODEV; } if (!pdata) { - dev_dbg(dev, "no platform data?\n"); + dev_dbg(&spi->dev, "no platform data?\n"); return -ENODEV; } /* don't exceed max specified sample rate */ if (spi->max_speed_hz > (125000 * 16)) { - dev_dbg(dev, "f(sample) %d KHz?\n", + dev_dbg(&spi->dev, "f(sample) %d KHz?\n", (spi->max_speed_hz/16)/1000); return -EINVAL; } @@ -430,7 +425,7 @@ static int __init ads7846_probe(struct device *dev) if (!(ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL))) return -ENOMEM; - dev_set_drvdata(dev, ts); + dev_set_drvdata(&spi->dev, ts); ts->spi = spi; spi->dev.power.power_state = PMSG_ON; @@ -445,9 +440,9 @@ static int __init ads7846_probe(struct device *dev) init_input_dev(&ts->input); - ts->input.dev = dev; + ts->input.dev = &spi->dev; ts->input.name = "ADS784x Touchscreen"; - snprintf(ts->phys, sizeof ts->phys, "%s/input0", dev->bus_id); + snprintf(ts->phys, sizeof ts->phys, "%s/input0", spi->dev.bus_id); ts->input.phys = ts->phys; ts->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); @@ -511,65 +506,68 @@ static int __init ads7846_probe(struct device *dev) ts->msg.context = ts; if (request_irq(spi->irq, ads7846_irq, SA_SAMPLE_RANDOM, - dev->bus_id, ts)) { - dev_dbg(dev, "irq %d busy?\n", spi->irq); + spi->dev.bus_id, ts)) { + dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); input_unregister_device(&ts->input); kfree(ts); return -EBUSY; } set_irq_type(spi->irq, IRQT_FALLING); - dev_info(dev, "touchscreen, irq %d\n", spi->irq); + dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq); /* take a first sample, leaving nPENIRQ active; avoid * the touchscreen, in case it's not connected. */ - (void) ads7846_read12_ser(dev, + (void) ads7846_read12_ser(&spi->dev, READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON); /* ads7843/7845 don't have temperature sensors, and * use the other sensors a bit differently too */ if (ts->model == 7846) { - device_create_file(dev, &dev_attr_temp0); - device_create_file(dev, &dev_attr_temp1); + device_create_file(&spi->dev, &dev_attr_temp0); + device_create_file(&spi->dev, &dev_attr_temp1); } if (ts->model != 7845) - device_create_file(dev, &dev_attr_vbatt); - device_create_file(dev, &dev_attr_vaux); + device_create_file(&spi->dev, &dev_attr_vbatt); + device_create_file(&spi->dev, &dev_attr_vaux); return 0; } -static int __exit ads7846_remove(struct device *dev) +static int __devexit ads7846_remove(struct spi_device *spi) { - struct ads7846 *ts = dev_get_drvdata(dev); + struct ads7846 *ts = dev_get_drvdata(&spi->dev); - ads7846_suspend(dev, PMSG_SUSPEND EXTRA2); + ads7846_suspend(spi, PMSG_SUSPEND); free_irq(ts->spi->irq, ts); if (ts->irq_disabled) enable_irq(ts->spi->irq); if (ts->model == 7846) { - device_remove_file(dev, &dev_attr_temp0); - device_remove_file(dev, &dev_attr_temp1); + device_remove_file(&spi->dev, &dev_attr_temp0); + device_remove_file(&spi->dev, &dev_attr_temp1); } if (ts->model != 7845) - device_remove_file(dev, &dev_attr_vbatt); - device_remove_file(dev, &dev_attr_vaux); + device_remove_file(&spi->dev, &dev_attr_vbatt); + device_remove_file(&spi->dev, &dev_attr_vaux); input_unregister_device(&ts->input); kfree(ts); - dev_dbg(dev, "unregistered touchscreen\n"); + dev_dbg(&spi->dev, "unregistered touchscreen\n"); return 0; } -static struct device_driver ads7846_driver = { - .name = "ads7846", - .bus = &spi_bus_type, +static struct spi_driver ads7846_driver = { + .driver = { + .name = "ads7846", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, .probe = ads7846_probe, - .remove = __exit_p(ads7846_remove), + .remove = __devexit_p(ads7846_remove), .suspend = ads7846_suspend, .resume = ads7846_resume, }; @@ -594,18 +592,20 @@ static int __init ads7846_init(void) // PXA: // also Dell Axim X50 // also HP iPaq H191x/H192x/H415x/H435x - // also Intel Lubbock (alternate to UCB1400) + // also Intel Lubbock (additional to UCB1400; as temperature sensor) // also Sharp Zaurus C7xx, C8xx (corgi/sheperd/husky) + // Atmel at91sam9261-EK uses ads7843 + // also various AMD Au1x00 devel boards - return driver_register(&ads7846_driver); + return spi_register_driver(&ads7846_driver); } module_init(ads7846_init); static void __exit ads7846_exit(void) { - driver_unregister(&ads7846_driver); + spi_unregister_driver(&ads7846_driver); #ifdef CONFIG_ARCH_OMAP if (machine_is_omap_osk()) { diff --git a/include/linux/spi/ads7846.h b/include/linux/spi/ads7846.h index 84a27013d39..72261e0f2ac 100644 --- a/include/linux/spi/ads7846.h +++ b/include/linux/spi/ads7846.h @@ -1,7 +1,7 @@ /* linux/spi/ads7846.h */ /* Touchscreen characteristics vary between boards and models. The - * platform_data for the device's "struct device" holts this information. + * platform_data for the device's "struct device" holds this information. * * It's OK if the min/max values are zero. */ -- GitLab From 9904f22a7202c6b54e96b0cc9870817013c350a1 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sun, 8 Jan 2006 13:34:26 -0800 Subject: [PATCH 158/465] [PATCH] spi: add spi_bitbang driver This adds a bitbanging spi master, hooking up to board/adapter-specific glue code which knows how to set and read the signals (gpios etc). This code kicks in after the glue code creates a platform_device with the right platform_data. That data includes I/O loops, which will usually come from expanding an inline function (provided in the header). One goal is that the I/O loops should be easily optimized down to a few GPIO register accesses, in common cases, for speed and minimized overhead. This understands all the currently defined protocol tweaking options in the SPI framework, and might eventually serve as as reference implementation. - different word sizes (1..32 bits) - differing clock rates - SPI modes differing by CPOL (affecting chip select and I/O loops) - SPI modes differing by CPHA (affecting I/O loops) - delays (usecs) after transfers - temporarily deselecting chips in mid-transfer A lot of hardware could work with this framework, though common types of controller can't reach peak performance without switching to a driver structure that supports pipelining of transfers (e.g. DMA queues) and maybe controllers (e.g. IRQ driven). Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/spi/Kconfig | 13 + drivers/spi/Makefile | 1 + drivers/spi/spi_bitbang.c | 460 ++++++++++++++++++++++++++++++++ include/linux/spi/spi_bitbang.h | 128 +++++++++ 4 files changed, 602 insertions(+) create mode 100644 drivers/spi/spi_bitbang.c create mode 100644 include/linux/spi/spi_bitbang.h diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index d3105104a29..9b21c5d77b4 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -51,6 +51,19 @@ config SPI_MASTER comment "SPI Master Controller Drivers" depends on SPI_MASTER +config SPI_BITBANG + tristate "Bitbanging SPI master" + depends on SPI_MASTER && EXPERIMENTAL + help + With a few GPIO pins, your system can bitbang the SPI protocol. + Select this to get SPI support through I/O pins (GPIO, parallel + port, etc). Or, some systems' SPI master controller drivers use + this code to manage the per-word or per-transfer accesses to the + hardware shift registers. + + This is library code, and is automatically selected by drivers that + need it. You only need to select this explicitly to support driver + modules that aren't part of this kernel tree. # # Add new SPI master controllers in alphabetical order above this line diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index afd2321753b..5da6a4df401 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -11,6 +11,7 @@ endif obj-$(CONFIG_SPI_MASTER) += spi.o # SPI master controller drivers (bus) +obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o # ... add above this line ... # SPI protocol drivers (device/link on bus) diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c new file mode 100644 index 00000000000..44aff198eb9 --- /dev/null +++ b/drivers/spi/spi_bitbang.c @@ -0,0 +1,460 @@ +/* + * spi_bitbang.c - polling/bitbanging SPI master controller driver utilities + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +/*----------------------------------------------------------------------*/ + +/* + * FIRST PART (OPTIONAL): word-at-a-time spi_transfer support. + * Use this for GPIO or shift-register level hardware APIs. + * + * spi_bitbang_cs is in spi_device->controller_state, which is unavailable + * to glue code. These bitbang setup() and cleanup() routines are always + * used, though maybe they're called from controller-aware code. + * + * chipselect() and friends may use use spi_device->controller_data and + * controller registers as appropriate. + * + * + * NOTE: SPI controller pins can often be used as GPIO pins instead, + * which means you could use a bitbang driver either to get hardware + * working quickly, or testing for differences that aren't speed related. + */ + +struct spi_bitbang_cs { + unsigned nsecs; /* (clock cycle time)/2 */ + u32 (*txrx_word)(struct spi_device *spi, unsigned nsecs, + u32 word, u8 bits); + unsigned (*txrx_bufs)(struct spi_device *, + u32 (*txrx_word)( + struct spi_device *spi, + unsigned nsecs, + u32 word, u8 bits), + unsigned, struct spi_transfer *); +}; + +static unsigned bitbang_txrx_8( + struct spi_device *spi, + u32 (*txrx_word)(struct spi_device *spi, + unsigned nsecs, + u32 word, u8 bits), + unsigned ns, + struct spi_transfer *t +) { + unsigned bits = spi->bits_per_word; + unsigned count = t->len; + const u8 *tx = t->tx_buf; + u8 *rx = t->rx_buf; + + while (likely(count > 0)) { + u8 word = 0; + + if (tx) + word = *tx++; + word = txrx_word(spi, ns, word, bits); + if (rx) + *rx++ = word; + count -= 1; + } + return t->len - count; +} + +static unsigned bitbang_txrx_16( + struct spi_device *spi, + u32 (*txrx_word)(struct spi_device *spi, + unsigned nsecs, + u32 word, u8 bits), + unsigned ns, + struct spi_transfer *t +) { + unsigned bits = spi->bits_per_word; + unsigned count = t->len; + const u16 *tx = t->tx_buf; + u16 *rx = t->rx_buf; + + while (likely(count > 1)) { + u16 word = 0; + + if (tx) + word = *tx++; + word = txrx_word(spi, ns, word, bits); + if (rx) + *rx++ = word; + count -= 2; + } + return t->len - count; +} + +static unsigned bitbang_txrx_32( + struct spi_device *spi, + u32 (*txrx_word)(struct spi_device *spi, + unsigned nsecs, + u32 word, u8 bits), + unsigned ns, + struct spi_transfer *t +) { + unsigned bits = spi->bits_per_word; + unsigned count = t->len; + const u32 *tx = t->tx_buf; + u32 *rx = t->rx_buf; + + while (likely(count > 3)) { + u32 word = 0; + + if (tx) + word = *tx++; + word = txrx_word(spi, ns, word, bits); + if (rx) + *rx++ = word; + count -= 4; + } + return t->len - count; +} + +/** + * spi_bitbang_setup - default setup for per-word I/O loops + */ +int spi_bitbang_setup(struct spi_device *spi) +{ + struct spi_bitbang_cs *cs = spi->controller_state; + struct spi_bitbang *bitbang; + + if (!cs) { + cs = kzalloc(sizeof *cs, SLAB_KERNEL); + if (!cs) + return -ENOMEM; + spi->controller_state = cs; + } + bitbang = spi_master_get_devdata(spi->master); + + if (!spi->bits_per_word) + spi->bits_per_word = 8; + + /* spi_transfer level calls that work per-word */ + if (spi->bits_per_word <= 8) + cs->txrx_bufs = bitbang_txrx_8; + else if (spi->bits_per_word <= 16) + cs->txrx_bufs = bitbang_txrx_16; + else if (spi->bits_per_word <= 32) + cs->txrx_bufs = bitbang_txrx_32; + else + return -EINVAL; + + /* per-word shift register access, in hardware or bitbanging */ + cs->txrx_word = bitbang->txrx_word[spi->mode & (SPI_CPOL|SPI_CPHA)]; + if (!cs->txrx_word) + return -EINVAL; + + if (!spi->max_speed_hz) + spi->max_speed_hz = 500 * 1000; + + /* nsecs = max(50, (clock period)/2), be optimistic */ + cs->nsecs = (1000000000/2) / (spi->max_speed_hz); + if (cs->nsecs < 50) + cs->nsecs = 50; + if (cs->nsecs > MAX_UDELAY_MS * 1000) + return -EINVAL; + + dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec\n", + __FUNCTION__, spi->mode & (SPI_CPOL | SPI_CPHA), + spi->bits_per_word, 2 * cs->nsecs); + + /* NOTE we _need_ to call chipselect() early, ideally with adapter + * setup, unless the hardware defaults cooperate to avoid confusion + * between normal (active low) and inverted chipselects. + */ + + /* deselect chip (low or high) */ + spin_lock(&bitbang->lock); + if (!bitbang->busy) { + bitbang->chipselect(spi, 0); + ndelay(cs->nsecs); + } + spin_unlock(&bitbang->lock); + + return 0; +} +EXPORT_SYMBOL_GPL(spi_bitbang_setup); + +/** + * spi_bitbang_cleanup - default cleanup for per-word I/O loops + */ +void spi_bitbang_cleanup(const struct spi_device *spi) +{ + kfree(spi->controller_state); +} +EXPORT_SYMBOL_GPL(spi_bitbang_cleanup); + +static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t) +{ + struct spi_bitbang_cs *cs = spi->controller_state; + unsigned nsecs = cs->nsecs; + + return cs->txrx_bufs(spi, cs->txrx_word, nsecs, t); +} + +/*----------------------------------------------------------------------*/ + +/* + * SECOND PART ... simple transfer queue runner. + * + * This costs a task context per controller, running the queue by + * performing each transfer in sequence. Smarter hardware can queue + * several DMA transfers at once, and process several controller queues + * in parallel; this driver doesn't match such hardware very well. + * + * Drivers can provide word-at-a-time i/o primitives, or provide + * transfer-at-a-time ones to leverage dma or fifo hardware. + */ +static void bitbang_work(void *_bitbang) +{ + struct spi_bitbang *bitbang = _bitbang; + unsigned long flags; + + spin_lock_irqsave(&bitbang->lock, flags); + bitbang->busy = 1; + while (!list_empty(&bitbang->queue)) { + struct spi_message *m; + struct spi_device *spi; + unsigned nsecs; + struct spi_transfer *t; + unsigned tmp; + unsigned chipselect; + int status; + + m = container_of(bitbang->queue.next, struct spi_message, + queue); + list_del_init(&m->queue); + spin_unlock_irqrestore(&bitbang->lock, flags); + +// FIXME this is made-up +nsecs = 100; + + spi = m->spi; + t = m->transfers; + tmp = 0; + chipselect = 0; + status = 0; + + for (;;t++) { + if (bitbang->shutdown) { + status = -ESHUTDOWN; + break; + } + + /* set up default clock polarity, and activate chip */ + if (!chipselect) { + bitbang->chipselect(spi, 1); + ndelay(nsecs); + } + if (!t->tx_buf && !t->rx_buf && t->len) { + status = -EINVAL; + break; + } + + /* transfer data */ + if (t->len) { + /* FIXME if bitbang->use_dma, dma_map_single() + * before the transfer, and dma_unmap_single() + * afterwards, for either or both buffers... + */ + status = bitbang->txrx_bufs(spi, t); + } + if (status != t->len) { + if (status > 0) + status = -EMSGSIZE; + break; + } + m->actual_length += status; + status = 0; + + /* protocol tweaks before next transfer */ + if (t->delay_usecs) + udelay(t->delay_usecs); + + tmp++; + if (tmp >= m->n_transfer) + break; + + chipselect = !t->cs_change; + if (chipselect); + continue; + + bitbang->chipselect(spi, 0); + + /* REVISIT do we want the udelay here instead? */ + msleep(1); + } + + tmp = m->n_transfer - 1; + tmp = m->transfers[tmp].cs_change; + + m->status = status; + m->complete(m->context); + + ndelay(2 * nsecs); + bitbang->chipselect(spi, status == 0 && tmp); + ndelay(nsecs); + + spin_lock_irqsave(&bitbang->lock, flags); + } + bitbang->busy = 0; + spin_unlock_irqrestore(&bitbang->lock, flags); +} + +/** + * spi_bitbang_transfer - default submit to transfer queue + */ +int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m) +{ + struct spi_bitbang *bitbang; + unsigned long flags; + + m->actual_length = 0; + m->status = -EINPROGRESS; + + bitbang = spi_master_get_devdata(spi->master); + if (bitbang->shutdown) + return -ESHUTDOWN; + + spin_lock_irqsave(&bitbang->lock, flags); + list_add_tail(&m->queue, &bitbang->queue); + queue_work(bitbang->workqueue, &bitbang->work); + spin_unlock_irqrestore(&bitbang->lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(spi_bitbang_transfer); + +/*----------------------------------------------------------------------*/ + +/** + * spi_bitbang_start - start up a polled/bitbanging SPI master driver + * @bitbang: driver handle + * + * Caller should have zero-initialized all parts of the structure, and then + * provided callbacks for chip selection and I/O loops. If the master has + * a transfer method, its final step should call spi_bitbang_transfer; or, + * that's the default if the transfer routine is not initialized. It should + * also set up the bus number and number of chipselects. + * + * For i/o loops, provide callbacks either per-word (for bitbanging, or for + * hardware that basically exposes a shift register) or per-spi_transfer + * (which takes better advantage of hardware like fifos or DMA engines). + * + * Drivers using per-word I/O loops should use (or call) spi_bitbang_setup and + * spi_bitbang_cleanup to handle those spi master methods. Those methods are + * the defaults if the bitbang->txrx_bufs routine isn't initialized. + * + * This routine registers the spi_master, which will process requests in a + * dedicated task, keeping IRQs unblocked most of the time. To stop + * processing those requests, call spi_bitbang_stop(). + */ +int spi_bitbang_start(struct spi_bitbang *bitbang) +{ + int status; + + if (!bitbang->master || !bitbang->chipselect) + return -EINVAL; + + INIT_WORK(&bitbang->work, bitbang_work, bitbang); + spin_lock_init(&bitbang->lock); + INIT_LIST_HEAD(&bitbang->queue); + + if (!bitbang->master->transfer) + bitbang->master->transfer = spi_bitbang_transfer; + if (!bitbang->txrx_bufs) { + bitbang->use_dma = 0; + bitbang->txrx_bufs = spi_bitbang_bufs; + if (!bitbang->master->setup) { + bitbang->master->setup = spi_bitbang_setup; + bitbang->master->cleanup = spi_bitbang_cleanup; + } + } else if (!bitbang->master->setup) + return -EINVAL; + + /* this task is the only thing to touch the SPI bits */ + bitbang->busy = 0; + bitbang->workqueue = create_singlethread_workqueue( + bitbang->master->cdev.dev->bus_id); + if (bitbang->workqueue == NULL) { + status = -EBUSY; + goto err1; + } + + /* driver may get busy before register() returns, especially + * if someone registered boardinfo for devices + */ + status = spi_register_master(bitbang->master); + if (status < 0) + goto err2; + + return status; + +err2: + destroy_workqueue(bitbang->workqueue); +err1: + return status; +} +EXPORT_SYMBOL_GPL(spi_bitbang_start); + +/** + * spi_bitbang_stop - stops the task providing spi communication + */ +int spi_bitbang_stop(struct spi_bitbang *bitbang) +{ + unsigned limit = 500; + + spin_lock_irq(&bitbang->lock); + bitbang->shutdown = 0; + while (!list_empty(&bitbang->queue) && limit--) { + spin_unlock_irq(&bitbang->lock); + + dev_dbg(bitbang->master->cdev.dev, "wait for queue\n"); + msleep(10); + + spin_lock_irq(&bitbang->lock); + } + spin_unlock_irq(&bitbang->lock); + if (!list_empty(&bitbang->queue)) { + dev_err(bitbang->master->cdev.dev, "queue didn't empty\n"); + return -EBUSY; + } + + destroy_workqueue(bitbang->workqueue); + + spi_unregister_master(bitbang->master); + + return 0; +} +EXPORT_SYMBOL_GPL(spi_bitbang_stop); + +MODULE_LICENSE("GPL"); + diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h new file mode 100644 index 00000000000..8dfe61a445f --- /dev/null +++ b/include/linux/spi/spi_bitbang.h @@ -0,0 +1,128 @@ +#ifndef __SPI_BITBANG_H +#define __SPI_BITBANG_H + +/* + * Mix this utility code with some glue code to get one of several types of + * simple SPI master driver. Two do polled word-at-a-time I/O: + * + * - GPIO/parport bitbangers. Provide chipselect() and txrx_word[](), + * expanding the per-word routines from the inline templates below. + * + * - Drivers for controllers resembling bare shift registers. Provide + * chipselect() and txrx_word[](), with custom setup()/cleanup() methods + * that use your controller's clock and chipselect registers. + * + * Some hardware works well with requests at spi_transfer scope: + * + * - Drivers leveraging smarter hardware, with fifos or DMA; or for half + * duplex (MicroWire) controllers. Provide chipslect() and txrx_bufs(), + * and custom setup()/cleanup() methods. + */ +struct spi_bitbang { + struct workqueue_struct *workqueue; + struct work_struct work; + + spinlock_t lock; + struct list_head queue; + u8 busy; + u8 shutdown; + u8 use_dma; + + struct spi_master *master; + + void (*chipselect)(struct spi_device *spi, int is_on); + + int (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t); + u32 (*txrx_word[4])(struct spi_device *spi, + unsigned nsecs, + u32 word, u8 bits); +}; + +/* you can call these default bitbang->master methods from your custom + * methods, if you like. + */ +extern int spi_bitbang_setup(struct spi_device *spi); +extern void spi_bitbang_cleanup(const struct spi_device *spi); +extern int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m); + +/* start or stop queue processing */ +extern int spi_bitbang_start(struct spi_bitbang *spi); +extern int spi_bitbang_stop(struct spi_bitbang *spi); + +#endif /* __SPI_BITBANG_H */ + +/*-------------------------------------------------------------------------*/ + +#ifdef EXPAND_BITBANG_TXRX + +/* + * The code that knows what GPIO pins do what should have declared four + * functions, ideally as inlines, before #defining EXPAND_BITBANG_TXRX + * and including this header: + * + * void setsck(struct spi_device *, int is_on); + * void setmosi(struct spi_device *, int is_on); + * int getmiso(struct spi_device *); + * void spidelay(unsigned); + * + * A non-inlined routine would call bitbang_txrx_*() routines. The + * main loop could easily compile down to a handful of instructions, + * especially if the delay is a NOP (to run at peak speed). + * + * Since this is software, the timings may not be exactly what your board's + * chips need ... there may be several reasons you'd need to tweak timings + * in these routines, not just make to make it faster or slower to match a + * particular CPU clock rate. + */ + +static inline u32 +bitbang_txrx_be_cpha0(struct spi_device *spi, + unsigned nsecs, unsigned cpol, + u32 word, u8 bits) +{ + /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */ + + /* clock starts at inactive polarity */ + for (word <<= (32 - bits); likely(bits); bits--) { + + /* setup MSB (to slave) on trailing edge */ + setmosi(spi, word & (1 << 31)); + spidelay(nsecs); /* T(setup) */ + + setsck(spi, !cpol); + spidelay(nsecs); + + /* sample MSB (from slave) on leading edge */ + word <<= 1; + word |= getmiso(spi); + setsck(spi, cpol); + } + return word; +} + +static inline u32 +bitbang_txrx_be_cpha1(struct spi_device *spi, + unsigned nsecs, unsigned cpol, + u32 word, u8 bits) +{ + /* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */ + + /* clock starts at inactive polarity */ + for (word <<= (32 - bits); likely(bits); bits--) { + + /* setup MSB (to slave) on leading edge */ + setsck(spi, !cpol); + setmosi(spi, word & (1 << 31)); + spidelay(nsecs); /* T(setup) */ + + setsck(spi, cpol); + spidelay(nsecs); + + /* sample MSB (from slave) on trailing edge */ + word <<= 1; + word |= getmiso(spi); + } + return word; +} + +#endif /* EXPAND_BITBANG_TXRX */ -- GitLab From 2f9f762879015d738a5ec2ac8a16be94b3a4a06d Mon Sep 17 00:00:00 2001 From: Mike Lavender Date: Sun, 8 Jan 2006 13:34:27 -0800 Subject: [PATCH 159/465] [PATCH] spi: M25 series SPI flash This was originally a driver for the ST M25P80 SPI flash. It's been updated slightly to handle other M25P series chips. For many of these chips, the specific type could be probed, but for now this just requires static setup with flash_platform_data that lists the chip type (size, format) and any default partitioning to use. Signed-off-by: David Brownell Cc: Mike Lavender Cc: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/devices/Kconfig | 8 + drivers/mtd/devices/Makefile | 1 + drivers/mtd/devices/m25p80.c | 580 +++++++++++++++++++++++++++++++++++ include/linux/spi/flash.h | 4 + 4 files changed, 593 insertions(+) create mode 100644 drivers/mtd/devices/m25p80.c diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index 84f2eb1fae0..5038e90ceb1 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig @@ -55,6 +55,14 @@ config MTD_DATAFLASH Sometimes DataFlash chips are packaged inside MMC-format cards; at this writing, the MMC stack won't handle those. +config MTD_M25P80 + tristate "Support for M25 SPI Flash" + depends on MTD && SPI_MASTER && EXPERIMENTAL + help + This enables access to ST M25P80 and similar SPI flash chips, + used for program and data storage. Set up your spi devices + with the right board-specific platform data. + config MTD_SLRAM tristate "Uncached system RAM" depends on MTD diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile index cd8d8074b5b..7c5ed217838 100644 --- a/drivers/mtd/devices/Makefile +++ b/drivers/mtd/devices/Makefile @@ -24,3 +24,4 @@ obj-$(CONFIG_MTD_LART) += lart.o obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o +obj-$(CONFIG_MTD_M25P80) += m25p80.o diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c new file mode 100644 index 00000000000..71a072103a7 --- /dev/null +++ b/drivers/mtd/devices/m25p80.c @@ -0,0 +1,580 @@ +/* + * MTD SPI driver for ST M25Pxx flash chips + * + * Author: Mike Lavender, mike@steroidmicros.com + * + * Copyright (c) 2005, Intec Automation Inc. + * + * Some parts are based on lart.c by Abraham Van Der Merwe + * + * Cleaned up and generalized based on mtd_dataflash.c + * + * This code is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +/* NOTE: AT 25F and SST 25LF series are very similar, + * but commands for sector erase and chip id differ... + */ + +#define FLASH_PAGESIZE 256 + +/* Flash opcodes. */ +#define OPCODE_WREN 6 /* Write enable */ +#define OPCODE_RDSR 5 /* Read status register */ +#define OPCODE_READ 3 /* Read data bytes */ +#define OPCODE_PP 2 /* Page program */ +#define OPCODE_SE 0xd8 /* Sector erase */ +#define OPCODE_RES 0xab /* Read Electronic Signature */ +#define OPCODE_RDID 0x9f /* Read JEDEC ID */ + +/* Status Register bits. */ +#define SR_WIP 1 /* Write in progress */ +#define SR_WEL 2 /* Write enable latch */ +#define SR_BP0 4 /* Block protect 0 */ +#define SR_BP1 8 /* Block protect 1 */ +#define SR_BP2 0x10 /* Block protect 2 */ +#define SR_SRWD 0x80 /* SR write protect */ + +/* Define max times to check status register before we give up. */ +#define MAX_READY_WAIT_COUNT 100000 + + +#ifdef CONFIG_MTD_PARTITIONS +#define mtd_has_partitions() (1) +#else +#define mtd_has_partitions() (0) +#endif + +/****************************************************************************/ + +struct m25p { + struct spi_device *spi; + struct semaphore lock; + struct mtd_info mtd; + unsigned partitioned; + u8 command[4]; +}; + +static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd) +{ + return container_of(mtd, struct m25p, mtd); +} + +/****************************************************************************/ + +/* + * Internal helper functions + */ + +/* + * Read the status register, returning its value in the location + * Return the status register value. + * Returns negative if error occurred. + */ +static int read_sr(struct m25p *flash) +{ + ssize_t retval; + u8 code = OPCODE_RDSR; + u8 val; + + retval = spi_write_then_read(flash->spi, &code, 1, &val, 1); + + if (retval < 0) { + dev_err(&flash->spi->dev, "error %d reading SR\n", + (int) retval); + return retval; + } + + return val; +} + + +/* + * Set write enable latch with Write Enable command. + * Returns negative if error occurred. + */ +static inline int write_enable(struct m25p *flash) +{ + u8 code = OPCODE_WREN; + + return spi_write_then_read(flash->spi, &code, 1, NULL, 0); +} + + +/* + * Service routine to read status register until ready, or timeout occurs. + * Returns non-zero if error. + */ +static int wait_till_ready(struct m25p *flash) +{ + int count; + int sr; + + /* one chip guarantees max 5 msec wait here after page writes, + * but potentially three seconds (!) after page erase. + */ + for (count = 0; count < MAX_READY_WAIT_COUNT; count++) { + if ((sr = read_sr(flash)) < 0) + break; + else if (!(sr & SR_WIP)) + return 0; + + /* REVISIT sometimes sleeping would be best */ + } + + return 1; +} + + +/* + * Erase one sector of flash memory at offset ``offset'' which is any + * address within the sector which should be erased. + * + * Returns 0 if successful, non-zero otherwise. + */ +static int erase_sector(struct m25p *flash, u32 offset) +{ + DEBUG(MTD_DEBUG_LEVEL3, "%s: %s at 0x%08x\n", flash->spi->dev.bus_id, + __FUNCTION__, offset); + + /* Wait until finished previous write command. */ + if (wait_till_ready(flash)) + return 1; + + /* Send write enable, then erase commands. */ + write_enable(flash); + + /* Set up command buffer. */ + flash->command[0] = OPCODE_SE; + flash->command[1] = offset >> 16; + flash->command[2] = offset >> 8; + flash->command[3] = offset; + + spi_write(flash->spi, flash->command, sizeof(flash->command)); + + return 0; +} + +/****************************************************************************/ + +/* + * MTD implementation + */ + +/* + * Erase an address range on the flash chip. The address range may extend + * one or more erase sectors. Return an error is there is a problem erasing. + */ +static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + struct m25p *flash = mtd_to_m25p(mtd); + u32 addr,len; + + DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", + flash->spi->dev.bus_id, __FUNCTION__, "at", + (u32)instr->addr, instr->len); + + /* sanity checks */ + if (instr->addr + instr->len > flash->mtd.size) + return -EINVAL; + if ((instr->addr % mtd->erasesize) != 0 + || (instr->len % mtd->erasesize) != 0) { + return -EINVAL; + } + + addr = instr->addr; + len = instr->len; + + down(&flash->lock); + + /* now erase those sectors */ + while (len) { + if (erase_sector(flash, addr)) { + instr->state = MTD_ERASE_FAILED; + up(&flash->lock); + return -EIO; + } + + addr += mtd->erasesize; + len -= mtd->erasesize; + } + + up(&flash->lock); + + instr->state = MTD_ERASE_DONE; + mtd_erase_callback(instr); + + return 0; +} + +/* + * Read an address range from the flash chip. The address range + * may be any size provided it is within the physical boundaries. + */ +static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct m25p *flash = mtd_to_m25p(mtd); + struct spi_transfer t[2]; + struct spi_message m; + + DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", + flash->spi->dev.bus_id, __FUNCTION__, "from", + (u32)from, len); + + /* sanity checks */ + if (!len) + return 0; + + if (from + len > flash->mtd.size) + return -EINVAL; + + down(&flash->lock); + + /* Wait till previous write/erase is done. */ + if (wait_till_ready(flash)) { + /* REVISIT status return?? */ + up(&flash->lock); + return 1; + } + + memset(t, 0, (sizeof t)); + + /* NOTE: OPCODE_FAST_READ (if available) is faster... */ + + /* Set up the write data buffer. */ + flash->command[0] = OPCODE_READ; + flash->command[1] = from >> 16; + flash->command[2] = from >> 8; + flash->command[3] = from; + + /* Byte count starts at zero. */ + if (retlen) + *retlen = 0; + + t[0].tx_buf = flash->command; + t[0].len = sizeof(flash->command); + + t[1].rx_buf = buf; + t[1].len = len; + + m.transfers = t; + m.n_transfer = 2; + + spi_sync(flash->spi, &m); + + *retlen = m.actual_length - sizeof(flash->command); + + up(&flash->lock); + + return 0; +} + +/* + * Write an address range to the flash chip. Data must be written in + * FLASH_PAGESIZE chunks. The address range may be any size provided + * it is within the physical boundaries. + */ +static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + struct m25p *flash = mtd_to_m25p(mtd); + u32 page_offset, page_size; + struct spi_transfer t[2]; + struct spi_message m; + + DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", + flash->spi->dev.bus_id, __FUNCTION__, "to", + (u32)to, len); + + if (retlen) + *retlen = 0; + + /* sanity checks */ + if (!len) + return(0); + + if (to + len > flash->mtd.size) + return -EINVAL; + + down(&flash->lock); + + /* Wait until finished previous write command. */ + if (wait_till_ready(flash)) + return 1; + + write_enable(flash); + + memset(t, 0, (sizeof t)); + + /* Set up the opcode in the write buffer. */ + flash->command[0] = OPCODE_PP; + flash->command[1] = to >> 16; + flash->command[2] = to >> 8; + flash->command[3] = to; + + t[0].tx_buf = flash->command; + t[0].len = sizeof(flash->command); + + m.transfers = t; + m.n_transfer = 2; + + /* what page do we start with? */ + page_offset = to % FLASH_PAGESIZE; + + /* do all the bytes fit onto one page? */ + if (page_offset + len <= FLASH_PAGESIZE) { + t[1].tx_buf = buf; + t[1].len = len; + + spi_sync(flash->spi, &m); + + *retlen = m.actual_length - sizeof(flash->command); + } else { + u32 i; + + /* the size of data remaining on the first page */ + page_size = FLASH_PAGESIZE - page_offset; + + t[1].tx_buf = buf; + t[1].len = page_size; + spi_sync(flash->spi, &m); + + *retlen = m.actual_length - sizeof(flash->command); + + /* write everything in PAGESIZE chunks */ + for (i = page_size; i < len; i += page_size) { + page_size = len - i; + if (page_size > FLASH_PAGESIZE) + page_size = FLASH_PAGESIZE; + + /* write the next page to flash */ + flash->command[1] = (to + i) >> 16; + flash->command[2] = (to + i) >> 8; + flash->command[3] = (to + i); + + t[1].tx_buf = buf + i; + t[1].len = page_size; + + wait_till_ready(flash); + + write_enable(flash); + + spi_sync(flash->spi, &m); + + *retlen += m.actual_length - sizeof(flash->command); + } + } + + up(&flash->lock); + + return 0; +} + + +/****************************************************************************/ + +/* + * SPI device driver setup and teardown + */ + +struct flash_info { + char *name; + u8 id; + u16 jedec_id; + unsigned sector_size; + unsigned n_sectors; +}; + +static struct flash_info __devinitdata m25p_data [] = { + /* REVISIT: fill in JEDEC ids, for parts that have them */ + { "m25p05", 0x05, 0x0000, 32 * 1024, 2 }, + { "m25p10", 0x10, 0x0000, 32 * 1024, 4 }, + { "m25p20", 0x11, 0x0000, 64 * 1024, 4 }, + { "m25p40", 0x12, 0x0000, 64 * 1024, 8 }, + { "m25p80", 0x13, 0x0000, 64 * 1024, 16 }, + { "m25p16", 0x14, 0x0000, 64 * 1024, 32 }, + { "m25p32", 0x15, 0x0000, 64 * 1024, 64 }, + { "m25p64", 0x16, 0x2017, 64 * 1024, 128 }, +}; + +/* + * board specific setup should have ensured the SPI clock used here + * matches what the READ command supports, at least until this driver + * understands FAST_READ (for clocks over 25 MHz). + */ +static int __devinit m25p_probe(struct spi_device *spi) +{ + struct flash_platform_data *data; + struct m25p *flash; + struct flash_info *info; + unsigned i; + + /* Platform data helps sort out which chip type we have, as + * well as how this board partitions it. + */ + data = spi->dev.platform_data; + if (!data || !data->type) { + /* FIXME some chips can identify themselves with RES + * or JEDEC get-id commands. Try them ... + */ + DEBUG(MTD_DEBUG_LEVEL1, "%s: no chip id\n", + flash->spi->dev.bus_id); + return -ENODEV; + } + + for (i = 0, info = m25p_data; i < ARRAY_SIZE(m25p_data); i++, info++) { + if (strcmp(data->type, info->name) == 0) + break; + } + if (i == ARRAY_SIZE(m25p_data)) { + DEBUG(MTD_DEBUG_LEVEL1, "%s: unrecognized id %s\n", + flash->spi->dev.bus_id, data->type); + return -ENODEV; + } + + flash = kzalloc(sizeof *flash, SLAB_KERNEL); + if (!flash) + return -ENOMEM; + + flash->spi = spi; + init_MUTEX(&flash->lock); + dev_set_drvdata(&spi->dev, flash); + + if (data->name) + flash->mtd.name = data->name; + else + flash->mtd.name = spi->dev.bus_id; + + flash->mtd.type = MTD_NORFLASH; + flash->mtd.flags = MTD_CAP_NORFLASH; + flash->mtd.size = info->sector_size * info->n_sectors; + flash->mtd.erasesize = info->sector_size; + flash->mtd.erase = m25p80_erase; + flash->mtd.read = m25p80_read; + flash->mtd.write = m25p80_write; + + dev_info(&spi->dev, "%s (%d Kbytes)\n", info->name, + flash->mtd.size / 1024); + + DEBUG(MTD_DEBUG_LEVEL2, + "mtd .name = %s, .size = 0x%.8x (%uM) " + ".erasesize = 0x%.8x (%uK) .numeraseregions = %d\n", + flash->mtd.name, + flash->mtd.size, flash->mtd.size / (1024*1024), + flash->mtd.erasesize, flash->mtd.erasesize / 1024, + flash->mtd.numeraseregions); + + if (flash->mtd.numeraseregions) + for (i = 0; i < flash->mtd.numeraseregions; i++) + DEBUG(MTD_DEBUG_LEVEL2, + "mtd.eraseregions[%d] = { .offset = 0x%.8x, " + ".erasesize = 0x%.8x (%uK), " + ".numblocks = %d }\n", + i, flash->mtd.eraseregions[i].offset, + flash->mtd.eraseregions[i].erasesize, + flash->mtd.eraseregions[i].erasesize / 1024, + flash->mtd.eraseregions[i].numblocks); + + + /* partitions should match sector boundaries; and it may be good to + * use readonly partitions for writeprotected sectors (BP2..BP0). + */ + if (mtd_has_partitions()) { + struct mtd_partition *parts = NULL; + int nr_parts = 0; + +#ifdef CONFIG_MTD_CMDLINE_PARTS + static const char *part_probes[] = { "cmdlinepart", NULL, }; + + nr_parts = parse_mtd_partitions(&flash->mtd, + part_probes, &parts, 0); +#endif + + if (nr_parts <= 0 && data && data->parts) { + parts = data->parts; + nr_parts = data->nr_parts; + } + + if (nr_parts > 0) { + for (i = 0; i < data->nr_parts; i++) { + DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = " + "{.name = %s, .offset = 0x%.8x, " + ".size = 0x%.8x (%uK) }\n", + i, data->parts[i].name, + data->parts[i].offset, + data->parts[i].size, + data->parts[i].size / 1024); + } + flash->partitioned = 1; + return add_mtd_partitions(&flash->mtd, parts, nr_parts); + } + } else if (data->nr_parts) + dev_warn(&spi->dev, "ignoring %d default partitions on %s\n", + data->nr_parts, data->name); + + return add_mtd_device(&flash->mtd) == 1 ? -ENODEV : 0; +} + + +static int __devexit m25p_remove(struct spi_device *spi) +{ + struct m25p *flash = dev_get_drvdata(&spi->dev); + int status; + + /* Clean up MTD stuff. */ + if (mtd_has_partitions() && flash->partitioned) + status = del_mtd_partitions(&flash->mtd); + else + status = del_mtd_device(&flash->mtd); + if (status == 0) + kfree(flash); + return 0; +} + + +static struct spi_driver m25p80_driver = { + .driver = { + .name = "m25p80", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = m25p_probe, + .remove = __devexit_p(m25p_remove), +}; + + +static int m25p80_init(void) +{ + return spi_register_driver(&m25p80_driver); +} + + +static void m25p80_exit(void) +{ + spi_unregister_driver(&m25p80_driver); +} + + +module_init(m25p80_init); +module_exit(m25p80_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mike Lavender"); +MODULE_DESCRIPTION("MTD SPI driver for ST M25Pxx flash chips"); diff --git a/include/linux/spi/flash.h b/include/linux/spi/flash.h index 2ce6558bf3f..3f22932e67a 100644 --- a/include/linux/spi/flash.h +++ b/include/linux/spi/flash.h @@ -8,6 +8,8 @@ struct mtd_partition; * @name: optional flash device name (eg, as used with mtdparts=) * @parts: optional array of mtd_partitions for static partitioning * @nr_parts: number of mtd_partitions for static partitoning + * @type: optional flash device type (e.g. m25p80 vs m25p64), for use + * with chips that can't be queried for JEDEC or other IDs * * Board init code (in arch/.../mach-xxx/board-yyy.c files) can * provide information about SPI flash parts (such as DataFlash) to @@ -21,6 +23,8 @@ struct flash_platform_data { struct mtd_partition *parts; unsigned int nr_parts; + char *type; + /* we'll likely add more ... use JEDEC IDs, etc */ }; -- GitLab From 8275c642ccdce09a2146d0a9eb022e3698ee927e Mon Sep 17 00:00:00 2001 From: Vitaly Wool Date: Sun, 8 Jan 2006 13:34:28 -0800 Subject: [PATCH 160/465] [PATCH] spi: use linked lists rather than an array This makes the SPI core and its users access transfers in the SPI message structure as linked list not as an array, as discussed on LKML. From: David Brownell Updates including doc, bugfixes to the list code, add spi_message_add_tail(). Plus, initialize things _before_ grabbing the locks in some cases (in case it grows more expensive). This also merges some bitbang updates of mine that didn't yet make it into the mm tree. Signed-off-by: Vitaly Wool Signed-off-by: Dmitry Pervushin Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/input/touchscreen/ads7846.c | 12 ++-- drivers/mtd/devices/m25p80.c | 50 ++++++++-------- drivers/mtd/devices/mtd_dataflash.c | 28 +++++---- drivers/spi/spi.c | 18 +++--- drivers/spi/spi_bitbang.c | 86 +++++++++++++++------------ include/linux/spi/spi.h | 92 ++++++++++++++++++++--------- include/linux/spi/spi_bitbang.h | 7 +++ 7 files changed, 180 insertions(+), 113 deletions(-) diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index c741776ef3b..dd8c6a9ffc7 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -155,10 +155,13 @@ static int ads7846_read12_ser(struct device *dev, unsigned command) struct ser_req *req = kzalloc(sizeof *req, SLAB_KERNEL); int status; int sample; + int i; if (!req) return -ENOMEM; + INIT_LIST_HEAD(&req->msg.transfers); + /* activate reference, so it has time to settle; */ req->xfer[0].tx_buf = &ref_on; req->xfer[0].len = 1; @@ -192,8 +195,8 @@ static int ads7846_read12_ser(struct device *dev, unsigned command) /* group all the transfers together, so we can't interfere with * reading touchscreen state; disable penirq while sampling */ - req->msg.transfers = req->xfer; - req->msg.n_transfer = 6; + for (i = 0; i < 6; i++) + spi_message_add_tail(&req->xfer[i], &req->msg); disable_irq(spi->irq); status = spi_sync(spi, &req->msg); @@ -398,6 +401,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) struct ads7846 *ts; struct ads7846_platform_data *pdata = spi->dev.platform_data; struct spi_transfer *x; + int i; if (!spi->irq) { dev_dbg(&spi->dev, "no IRQ?\n"); @@ -500,8 +504,8 @@ static int __devinit ads7846_probe(struct spi_device *spi) CS_CHANGE(x[-1]); - ts->msg.transfers = ts->xfer; - ts->msg.n_transfer = x - ts->xfer; + for (i = 0; i < x - ts->xfer; i++) + spi_message_add_tail(&ts->xfer[i], &ts->msg); ts->msg.complete = ads7846_rx; ts->msg.context = ts; diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 71a072103a7..45108ed8558 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -245,6 +245,21 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, if (from + len > flash->mtd.size) return -EINVAL; + spi_message_init(&m); + memset(t, 0, (sizeof t)); + + t[0].tx_buf = flash->command; + t[0].len = sizeof(flash->command); + spi_message_add_tail(&t[0], &m); + + t[1].rx_buf = buf; + t[1].len = len; + spi_message_add_tail(&t[1], &m); + + /* Byte count starts at zero. */ + if (retlen) + *retlen = 0; + down(&flash->lock); /* Wait till previous write/erase is done. */ @@ -254,8 +269,6 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, return 1; } - memset(t, 0, (sizeof t)); - /* NOTE: OPCODE_FAST_READ (if available) is faster... */ /* Set up the write data buffer. */ @@ -264,19 +277,6 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, flash->command[2] = from >> 8; flash->command[3] = from; - /* Byte count starts at zero. */ - if (retlen) - *retlen = 0; - - t[0].tx_buf = flash->command; - t[0].len = sizeof(flash->command); - - t[1].rx_buf = buf; - t[1].len = len; - - m.transfers = t; - m.n_transfer = 2; - spi_sync(flash->spi, &m); *retlen = m.actual_length - sizeof(flash->command); @@ -313,6 +313,16 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, if (to + len > flash->mtd.size) return -EINVAL; + spi_message_init(&m); + memset(t, 0, (sizeof t)); + + t[0].tx_buf = flash->command; + t[0].len = sizeof(flash->command); + spi_message_add_tail(&t[0], &m); + + t[1].tx_buf = buf; + spi_message_add_tail(&t[1], &m); + down(&flash->lock); /* Wait until finished previous write command. */ @@ -321,26 +331,17 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, write_enable(flash); - memset(t, 0, (sizeof t)); - /* Set up the opcode in the write buffer. */ flash->command[0] = OPCODE_PP; flash->command[1] = to >> 16; flash->command[2] = to >> 8; flash->command[3] = to; - t[0].tx_buf = flash->command; - t[0].len = sizeof(flash->command); - - m.transfers = t; - m.n_transfer = 2; - /* what page do we start with? */ page_offset = to % FLASH_PAGESIZE; /* do all the bytes fit onto one page? */ if (page_offset + len <= FLASH_PAGESIZE) { - t[1].tx_buf = buf; t[1].len = len; spi_sync(flash->spi, &m); @@ -352,7 +353,6 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, /* the size of data remaining on the first page */ page_size = FLASH_PAGESIZE - page_offset; - t[1].tx_buf = buf; t[1].len = page_size; spi_sync(flash->spi, &m); diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index a39b3b6b266..99d3a0320fc 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c @@ -147,7 +147,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr) { struct dataflash *priv = (struct dataflash *)mtd->priv; struct spi_device *spi = priv->spi; - struct spi_transfer x[1] = { { .tx_dma = 0, }, }; + struct spi_transfer x = { .tx_dma = 0, }; struct spi_message msg; unsigned blocksize = priv->page_size << 3; u8 *command; @@ -162,10 +162,11 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr) || (instr->addr % priv->page_size) != 0) return -EINVAL; - x[0].tx_buf = command = priv->command; - x[0].len = 4; - msg.transfers = x; - msg.n_transfer = 1; + spi_message_init(&msg); + + x.tx_buf = command = priv->command; + x.len = 4; + spi_message_add_tail(&x, &msg); down(&priv->lock); while (instr->len > 0) { @@ -256,12 +257,15 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, DEBUG(MTD_DEBUG_LEVEL3, "READ: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]); + spi_message_init(&msg); + x[0].tx_buf = command; x[0].len = 8; + spi_message_add_tail(&x[0], &msg); + x[1].rx_buf = buf; x[1].len = len; - msg.transfers = x; - msg.n_transfer = 2; + spi_message_add_tail(&x[1], &msg); down(&priv->lock); @@ -320,9 +324,11 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, if ((to + len) > mtd->size) return -EINVAL; + spi_message_init(&msg); + x[0].tx_buf = command = priv->command; x[0].len = 4; - msg.transfers = x; + spi_message_add_tail(&x[0], &msg); pageaddr = ((unsigned)to / priv->page_size); offset = ((unsigned)to % priv->page_size); @@ -364,7 +370,6 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, DEBUG(MTD_DEBUG_LEVEL3, "TRANSFER: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]); - msg.n_transfer = 1; status = spi_sync(spi, &msg); if (status < 0) DEBUG(MTD_DEBUG_LEVEL1, "%s: xfer %u -> %d \n", @@ -385,14 +390,16 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, x[1].tx_buf = writebuf; x[1].len = writelen; - msg.n_transfer = 2; + spi_message_add_tail(x + 1, &msg); status = spi_sync(spi, &msg); + spi_transfer_del(x + 1); if (status < 0) DEBUG(MTD_DEBUG_LEVEL1, "%s: pgm %u/%u -> %d \n", spi->dev.bus_id, addr, writelen, status); (void) dataflash_waitready(priv->spi); + #ifdef CONFIG_DATAFLASH_WRITE_VERIFY /* (3) Compare to Buffer1 */ @@ -405,7 +412,6 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, DEBUG(MTD_DEBUG_LEVEL3, "COMPARE: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]); - msg.n_transfer = 1; status = spi_sync(spi, &msg); if (status < 0) DEBUG(MTD_DEBUG_LEVEL1, "%s: compare %u -> %d \n", diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 3ecedccdb96..cdb242de901 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -557,6 +557,17 @@ int spi_write_then_read(struct spi_device *spi, if ((n_tx + n_rx) > SPI_BUFSIZ) return -EINVAL; + spi_message_init(&message); + memset(x, 0, sizeof x); + if (n_tx) { + x[0].len = n_tx; + spi_message_add_tail(&x[0], &message); + } + if (n_rx) { + x[1].len = n_rx; + spi_message_add_tail(&x[1], &message); + } + /* ... unless someone else is using the pre-allocated buffer */ if (down_trylock(&lock)) { local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL); @@ -565,18 +576,11 @@ int spi_write_then_read(struct spi_device *spi, } else local_buf = buf; - memset(x, 0, sizeof x); - memcpy(local_buf, txbuf, n_tx); x[0].tx_buf = local_buf; - x[0].len = n_tx; - x[1].rx_buf = local_buf + n_tx; - x[1].len = n_rx; /* do the i/o */ - message.transfers = x; - message.n_transfer = ARRAY_SIZE(x); status = spi_sync(spi, &message); if (status == 0) { memcpy(rxbuf, x[1].rx_buf, n_rx); diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c index 44aff198eb9..f037e559326 100644 --- a/drivers/spi/spi_bitbang.c +++ b/drivers/spi/spi_bitbang.c @@ -146,6 +146,9 @@ int spi_bitbang_setup(struct spi_device *spi) struct spi_bitbang_cs *cs = spi->controller_state; struct spi_bitbang *bitbang; + if (!spi->max_speed_hz) + return -EINVAL; + if (!cs) { cs = kzalloc(sizeof *cs, SLAB_KERNEL); if (!cs) @@ -172,13 +175,8 @@ int spi_bitbang_setup(struct spi_device *spi) if (!cs->txrx_word) return -EINVAL; - if (!spi->max_speed_hz) - spi->max_speed_hz = 500 * 1000; - - /* nsecs = max(50, (clock period)/2), be optimistic */ + /* nsecs = (clock period)/2 */ cs->nsecs = (1000000000/2) / (spi->max_speed_hz); - if (cs->nsecs < 50) - cs->nsecs = 50; if (cs->nsecs > MAX_UDELAY_MS * 1000) return -EINVAL; @@ -194,7 +192,7 @@ int spi_bitbang_setup(struct spi_device *spi) /* deselect chip (low or high) */ spin_lock(&bitbang->lock); if (!bitbang->busy) { - bitbang->chipselect(spi, 0); + bitbang->chipselect(spi, BITBANG_CS_INACTIVE); ndelay(cs->nsecs); } spin_unlock(&bitbang->lock); @@ -244,9 +242,9 @@ static void bitbang_work(void *_bitbang) struct spi_message *m; struct spi_device *spi; unsigned nsecs; - struct spi_transfer *t; + struct spi_transfer *t = NULL; unsigned tmp; - unsigned chipselect; + unsigned cs_change; int status; m = container_of(bitbang->queue.next, struct spi_message, @@ -254,37 +252,49 @@ static void bitbang_work(void *_bitbang) list_del_init(&m->queue); spin_unlock_irqrestore(&bitbang->lock, flags); -// FIXME this is made-up -nsecs = 100; + /* FIXME this is made-up ... the correct value is known to + * word-at-a-time bitbang code, and presumably chipselect() + * should enforce these requirements too? + */ + nsecs = 100; spi = m->spi; - t = m->transfers; tmp = 0; - chipselect = 0; + cs_change = 1; status = 0; - for (;;t++) { + list_for_each_entry (t, &m->transfers, transfer_list) { if (bitbang->shutdown) { status = -ESHUTDOWN; break; } - /* set up default clock polarity, and activate chip */ - if (!chipselect) { - bitbang->chipselect(spi, 1); + /* set up default clock polarity, and activate chip; + * this implicitly updates clock and spi modes as + * previously recorded for this device via setup(). + * (and also deselects any other chip that might be + * selected ...) + */ + if (cs_change) { + bitbang->chipselect(spi, BITBANG_CS_ACTIVE); ndelay(nsecs); } + cs_change = t->cs_change; if (!t->tx_buf && !t->rx_buf && t->len) { status = -EINVAL; break; } - /* transfer data */ + /* transfer data. the lower level code handles any + * new dma mappings it needs. our caller always gave + * us dma-safe buffers. + */ if (t->len) { - /* FIXME if bitbang->use_dma, dma_map_single() - * before the transfer, and dma_unmap_single() - * afterwards, for either or both buffers... + /* REVISIT dma API still needs a designated + * DMA_ADDR_INVALID; ~0 might be better. */ + if (!m->is_dma_mapped) + t->rx_dma = t->tx_dma = 0; status = bitbang->txrx_bufs(spi, t); } if (status != t->len) { @@ -299,29 +309,31 @@ nsecs = 100; if (t->delay_usecs) udelay(t->delay_usecs); - tmp++; - if (tmp >= m->n_transfer) - break; - - chipselect = !t->cs_change; - if (chipselect); + if (!cs_change) continue; + if (t->transfer_list.next == &m->transfers) + break; - bitbang->chipselect(spi, 0); - - /* REVISIT do we want the udelay here instead? */ - msleep(1); + /* sometimes a short mid-message deselect of the chip + * may be needed to terminate a mode or command + */ + ndelay(nsecs); + bitbang->chipselect(spi, BITBANG_CS_INACTIVE); + ndelay(nsecs); } - tmp = m->n_transfer - 1; - tmp = m->transfers[tmp].cs_change; - m->status = status; m->complete(m->context); - ndelay(2 * nsecs); - bitbang->chipselect(spi, status == 0 && tmp); - ndelay(nsecs); + /* normally deactivate chipselect ... unless no error and + * cs_change has hinted that the next message will probably + * be for this chip too. + */ + if (!(status == 0 && cs_change)) { + ndelay(nsecs); + bitbang->chipselect(spi, BITBANG_CS_INACTIVE); + ndelay(nsecs); + } spin_lock_irqsave(&bitbang->lock, flags); } diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 6a41e2650b2..939afd3a2e7 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -263,15 +263,16 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum); /** * struct spi_transfer - a read/write buffer pair - * @tx_buf: data to be written (dma-safe address), or NULL - * @rx_buf: data to be read (dma-safe address), or NULL - * @tx_dma: DMA address of buffer, if spi_message.is_dma_mapped - * @rx_dma: DMA address of buffer, if spi_message.is_dma_mapped + * @tx_buf: data to be written (dma-safe memory), or NULL + * @rx_buf: data to be read (dma-safe memory), or NULL + * @tx_dma: DMA address of tx_buf, if spi_message.is_dma_mapped + * @rx_dma: DMA address of rx_buf, if spi_message.is_dma_mapped * @len: size of rx and tx buffers (in bytes) * @cs_change: affects chipselect after this transfer completes * @delay_usecs: microseconds to delay after this transfer before * (optionally) changing the chipselect status, then starting * the next transfer or completing this spi_message. + * @transfer_list: transfers are sequenced through spi_message.transfers * * SPI transfers always write the same number of bytes as they read. * Protocol drivers should always provide rx_buf and/or tx_buf. @@ -279,11 +280,16 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum); * the data being transferred; that may reduce overhead, when the * underlying driver uses dma. * - * All SPI transfers start with the relevant chipselect active. Drivers - * can change behavior of the chipselect after the transfer finishes - * (including any mandatory delay). The normal behavior is to leave it - * selected, except for the last transfer in a message. Setting cs_change - * allows two additional behavior options: + * If the transmit buffer is null, undefined data will be shifted out + * while filling rx_buf. If the receive buffer is null, the data + * shifted in will be discarded. Only "len" bytes shift out (or in). + * It's an error to try to shift out a partial word. (For example, by + * shifting out three bytes with word size of sixteen or twenty bits; + * the former uses two bytes per word, the latter uses four bytes.) + * + * All SPI transfers start with the relevant chipselect active. Normally + * it stays selected until after the last transfer in a message. Drivers + * can affect the chipselect signal using cs_change: * * (i) If the transfer isn't the last one in the message, this flag is * used to make the chipselect briefly go inactive in the middle of the @@ -299,7 +305,8 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum); * The code that submits an spi_message (and its spi_transfers) * to the lower layers is responsible for managing its memory. * Zero-initialize every field you don't set up explicitly, to - * insulate against future API updates. + * insulate against future API updates. After you submit a message + * and its transfers, ignore them until its completion callback. */ struct spi_transfer { /* it's ok if tx_buf == rx_buf (right?) @@ -316,12 +323,13 @@ struct spi_transfer { unsigned cs_change:1; u16 delay_usecs; + + struct list_head transfer_list; }; /** * struct spi_message - one multi-segment SPI transaction - * @transfers: the segements of the transaction - * @n_transfer: how many segments + * @transfers: list of transfer segments in this transaction * @spi: SPI device to which the transaction is queued * @is_dma_mapped: if true, the caller provided both dma and cpu virtual * addresses for each transfer buffer @@ -333,14 +341,22 @@ struct spi_transfer { * @queue: for use by whichever driver currently owns the message * @state: for use by whichever driver currently owns the message * + * An spi_message is used to execute an atomic sequence of data transfers, + * each represented by a struct spi_transfer. The sequence is "atomic" + * in the sense that no other spi_message may use that SPI bus until that + * sequence completes. On some systems, many such sequences can execute as + * as single programmed DMA transfer. On all systems, these messages are + * queued, and might complete after transactions to other devices. Messages + * sent to a given spi_device are alway executed in FIFO order. + * * The code that submits an spi_message (and its spi_transfers) * to the lower layers is responsible for managing its memory. * Zero-initialize every field you don't set up explicitly, to - * insulate against future API updates. + * insulate against future API updates. After you submit a message + * and its transfers, ignore them until its completion callback. */ struct spi_message { - struct spi_transfer *transfers; - unsigned n_transfer; + struct list_head transfers; struct spi_device *spi; @@ -371,6 +387,24 @@ struct spi_message { void *state; }; +static inline void spi_message_init(struct spi_message *m) +{ + memset(m, 0, sizeof *m); + INIT_LIST_HEAD(&m->transfers); +} + +static inline void +spi_message_add_tail(struct spi_transfer *t, struct spi_message *m) +{ + list_add_tail(&t->transfer_list, &m->transfers); +} + +static inline void +spi_transfer_del(struct spi_transfer *t) +{ + list_del(&t->transfer_list); +} + /* It's fine to embed message and transaction structures in other data * structures so long as you don't free them while they're in use. */ @@ -383,8 +417,12 @@ static inline struct spi_message *spi_message_alloc(unsigned ntrans, gfp_t flags + ntrans * sizeof(struct spi_transfer), flags); if (m) { - m->transfers = (void *)(m + 1); - m->n_transfer = ntrans; + int i; + struct spi_transfer *t = (struct spi_transfer *)(m + 1); + + INIT_LIST_HEAD(&m->transfers); + for (i = 0; i < ntrans; i++, t++) + spi_message_add_tail(t, m); } return m; } @@ -402,6 +440,8 @@ static inline void spi_message_free(struct spi_message *m) * device doesn't work with the mode 0 default. They may likewise need * to update clock rates or word sizes from initial values. This function * changes those settings, and must be called from a context that can sleep. + * The changes take effect the next time the device is selected and data + * is transferred to or from it. */ static inline int spi_setup(struct spi_device *spi) @@ -468,15 +508,12 @@ spi_write(struct spi_device *spi, const u8 *buf, size_t len) { struct spi_transfer t = { .tx_buf = buf, - .rx_buf = NULL, .len = len, - .cs_change = 0, - }; - struct spi_message m = { - .transfers = &t, - .n_transfer = 1, }; + struct spi_message m; + spi_message_init(&m); + spi_message_add_tail(&t, &m); return spi_sync(spi, &m); } @@ -493,16 +530,13 @@ static inline int spi_read(struct spi_device *spi, u8 *buf, size_t len) { struct spi_transfer t = { - .tx_buf = NULL, .rx_buf = buf, .len = len, - .cs_change = 0, - }; - struct spi_message m = { - .transfers = &t, - .n_transfer = 1, }; + struct spi_message m; + spi_message_init(&m); + spi_message_add_tail(&t, &m); return spi_sync(spi, &m); } diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h index 8dfe61a445f..c961fe9bf3e 100644 --- a/include/linux/spi/spi_bitbang.h +++ b/include/linux/spi/spi_bitbang.h @@ -31,8 +31,15 @@ struct spi_bitbang { struct spi_master *master; void (*chipselect)(struct spi_device *spi, int is_on); +#define BITBANG_CS_ACTIVE 1 /* normally nCS, active low */ +#define BITBANG_CS_INACTIVE 0 + /* txrx_bufs() may handle dma mapping for transfers that don't + * already have one (transfer.{tx,rx}_dma is zero), or use PIO + */ int (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t); + + /* txrx_word[SPI_MODE_*]() just looks like a shift register */ u32 (*txrx_word[4])(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits); -- GitLab From 7111763d391b0c5a949a4f2575aa88cd585f0ff6 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sun, 8 Jan 2006 13:34:29 -0800 Subject: [PATCH 161/465] [PATCH] spi: misc fixes This collects some small SPI patches that seem to be missing from the MM tree: - spi_butterfly kbuild hooks got dropped somehow; this restores them - quick fix for a (theoretical?) m25p80_write() oops noted by Andrew - quick fix for a potential config-specific oops for mtd_dataflash() - minor doc tweaks Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- Documentation/spi/spi-summary | 13 +++++++++++++ drivers/mtd/devices/m25p80.c | 4 +++- drivers/mtd/devices/mtd_dataflash.c | 2 +- drivers/spi/Kconfig | 10 ++++++++++ drivers/spi/Makefile | 1 + 5 files changed, 28 insertions(+), 2 deletions(-) diff --git a/Documentation/spi/spi-summary b/Documentation/spi/spi-summary index 761debf748e..a5ffba33a35 100644 --- a/Documentation/spi/spi-summary +++ b/Documentation/spi/spi-summary @@ -115,6 +115,9 @@ shows up in sysfs in several locations: /sys/devices/.../CTLR/spiB.C ... spi_device for on bus "B", chipselect C, accessed through CTLR. + /sys/devices/.../CTLR/spiB.C/modalias ... identifies the driver + that should be used with this device (for hotplug/coldplug) + /sys/bus/spi/devices/spiB.C ... symlink to the physical spiB-C device @@ -247,6 +250,12 @@ driver is registered: Like with other static board-specific setup, you won't unregister those. +The widely used "card" style computers bundle memory, cpu, and little else +onto a card that's maybe just thirty square centimeters. On such systems, +your arch/.../mach-.../board-*.c file would primarily provide information +about the devices on the mainboard into which such a card is plugged. That +certainly includes SPI devices hooked up through the card connectors! + NON-STATIC CONFIGURATIONS @@ -258,6 +267,10 @@ up the spi bus master, and will likely need spi_new_device() to provide the board info based on the board that was hotplugged. Of course, you'd later call at least spi_unregister_device() when that board is removed. +When Linux includes support for MMC/SD/SDIO/DataFlash cards through SPI, those +configurations will also be dynamic. Fortunately, those devices all support +basic device identification probes, so that support should hotplug normally. + How do I write an "SPI Protocol Driver"? ---------------------------------------- diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 45108ed8558..d5f24089be7 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -378,7 +378,9 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, spi_sync(flash->spi, &m); - *retlen += m.actual_length - sizeof(flash->command); + if (retlen) + *retlen += m.actual_length + - sizeof(flash->command); } } diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index 99d3a0320fc..155737e7483 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c @@ -508,7 +508,7 @@ add_dataflash(struct spi_device *spi, char *name, priv->partitioned = 1; return add_mtd_partitions(device, parts, nr_parts); } - } else if (pdata->nr_parts) + } else if (pdata && pdata->nr_parts) dev_warn(&spi->dev, "ignoring %d default partitions on %s\n", pdata->nr_parts, device->name); diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 9b21c5d77b4..7a75faeb052 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -65,6 +65,16 @@ config SPI_BITBANG need it. You only need to select this explicitly to support driver modules that aren't part of this kernel tree. +config SPI_BUTTERFLY + tristate "Parallel port adapter for AVR Butterfly (DEVELOPMENT)" + depends on SPI_MASTER && PARPORT && EXPERIMENTAL + select SPI_BITBANG + help + This uses a custom parallel port cable to connect to an AVR + Butterfly , an + inexpensive battery powered microcontroller evaluation board. + This same cable can be used to flash new firmware. + # # Add new SPI master controllers in alphabetical order above this line # diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 5da6a4df401..c2c87e845ab 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_SPI_MASTER) += spi.o # SPI master controller drivers (bus) obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o +obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o # ... add above this line ... # SPI protocol drivers (device/link on bus) -- GitLab From 5d870c8e216f121307445c71caa72e7e10a20061 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 11 Jan 2006 11:23:49 -0800 Subject: [PATCH 162/465] [PATCH] spi: remove fastcall crap gcc4 generates warnings when a non-FASTCALL function pointer is assigned to a FASTCALL one. Perhaps it has taste. Cc: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/spi/spi.c | 7 ++++++- include/linux/spi/spi.h | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index cdb242de901..791c4dc550a 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -480,6 +480,11 @@ EXPORT_SYMBOL_GPL(spi_busnum_to_master); /*-------------------------------------------------------------------------*/ +static void spi_complete(void *arg) +{ + complete(arg); +} + /** * spi_sync - blocking/synchronous SPI data transfers * @spi: device with which data will be exchanged @@ -508,7 +513,7 @@ int spi_sync(struct spi_device *spi, struct spi_message *message) DECLARE_COMPLETION(done); int status; - message->complete = (void (*)(void *)) complete; + message->complete = spi_complete; message->context = &done; status = spi_async(spi, message); if (status == 0) diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 939afd3a2e7..b05f1463a26 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -374,7 +374,7 @@ struct spi_message { */ /* completion is reported through a callback */ - void FASTCALL((*complete)(void *context)); + void (*complete)(void *context); void *context; unsigned actual_length; int status; -- GitLab From 2e10c84b9cf0b2d269c5629048d8d6e35eaf6b2b Mon Sep 17 00:00:00 2001 From: David Brownell Date: Wed, 11 Jan 2006 11:23:49 -0800 Subject: [PATCH 163/465] [PATCH] SPI: add spi_butterfly driver This adds a bitbanging parport based adaptor cable for AVR Butterfly, giving SPI links to its DataFlash chip and (eventually) firmware running in the card. Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- Documentation/spi/butterfly | 57 +++++ drivers/spi/Kconfig | 10 + drivers/spi/spi_butterfly.c | 423 ++++++++++++++++++++++++++++++++++++ 3 files changed, 490 insertions(+) create mode 100644 Documentation/spi/butterfly create mode 100644 drivers/spi/spi_butterfly.c diff --git a/Documentation/spi/butterfly b/Documentation/spi/butterfly new file mode 100644 index 00000000000..a2e8c8d90e3 --- /dev/null +++ b/Documentation/spi/butterfly @@ -0,0 +1,57 @@ +spi_butterfly - parport-to-butterfly adapter driver +=================================================== + +This is a hardware and software project that includes building and using +a parallel port adapter cable, together with an "AVR Butterfly" to run +firmware for user interfacing and/or sensors. A Butterfly is a $US20 +battery powered card with an AVR microcontroller and lots of goodies: +sensors, LCD, flash, toggle stick, and more. You can use AVR-GCC to +develop firmware for this, and flash it using this adapter cable. + +You can make this adapter from an old printer cable and solder things +directly to the Butterfly. Or (if you have the parts and skills) you +can come up with something fancier, providing ciruit protection to the +Butterfly and the printer port, or with a better power supply than two +signal pins from the printer port. + + +The first cable connections will hook Linux up to one SPI bus, with the +AVR and a DataFlash chip; and to the AVR reset line. This is all you +need to reflash the firmware, and the pins are the standard Atmel "ISP" +connector pins (used also on non-Butterfly AVR boards). + + Signal Butterfly Parport (DB-25) + ------ --------- --------------- + SCK = J403.PB1/SCK = pin 2/D0 + RESET = J403.nRST = pin 3/D1 + VCC = J403.VCC_EXT = pin 8/D6 + MOSI = J403.PB2/MOSI = pin 9/D7 + MISO = J403.PB3/MISO = pin 11/S7,nBUSY + GND = J403.GND = pin 23/GND + +Then to let Linux master that bus to talk to the DataFlash chip, you must +(a) flash new firmware that disables SPI (set PRR.2, and disable pullups +by clearing PORTB.[0-3]); (b) configure the mtd_dataflash driver; and +(c) cable in the chipselect. + + Signal Butterfly Parport (DB-25) + ------ --------- --------------- + VCC = J400.VCC_EXT = pin 7/D5 + SELECT = J400.PB0/nSS = pin 17/C3,nSELECT + GND = J400.GND = pin 24/GND + +The "USI" controller, using J405, can be used for a second SPI bus. That +would let you talk to the AVR over SPI, running firmware that makes it act +as an SPI slave, while letting either Linux or the AVR use the DataFlash. +There are plenty of spare parport pins to wire this one up, such as: + + Signal Butterfly Parport (DB-25) + ------ --------- --------------- + SCK = J403.PE4/USCK = pin 5/D3 + MOSI = J403.PE5/DI = pin 6/D4 + MISO = J403.PE6/DO = pin 12/S5,nPAPEROUT + GND = J403.GND = pin 22/GND + + IRQ = J402.PF4 = pin 10/S6,ACK + GND = J402.GND(P2) = pin 25/GND + diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 7a75faeb052..b77dbd63e59 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -75,6 +75,16 @@ config SPI_BUTTERFLY inexpensive battery powered microcontroller evaluation board. This same cable can be used to flash new firmware. +config SPI_BUTTERFLY + tristate "Parallel port adapter for AVR Butterfly (DEVELOPMENT)" + depends on SPI_MASTER && PARPORT && EXPERIMENTAL + select SPI_BITBANG + help + This uses a custom parallel port cable to connect to an AVR + Butterfly , an + inexpensive battery powered microcontroller evaluation board. + This same cable can be used to flash new firmware. + # # Add new SPI master controllers in alphabetical order above this line # diff --git a/drivers/spi/spi_butterfly.c b/drivers/spi/spi_butterfly.c new file mode 100644 index 00000000000..79a3c59615a --- /dev/null +++ b/drivers/spi/spi_butterfly.c @@ -0,0 +1,423 @@ +/* + * spi_butterfly.c - parport-to-butterfly adapter + * + * Copyright (C) 2005 David Brownell + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + + +/* + * This uses SPI to talk with an "AVR Butterfly", which is a $US20 card + * with a battery powered AVR microcontroller and lots of goodies. You + * can use GCC to develop firmware for this. + * + * See Documentation/spi/butterfly for information about how to build + * and use this custom parallel port cable. + */ + +#undef HAVE_USI /* nyet */ + + +/* DATA output bits (pins 2..9 == D0..D7) */ +#define butterfly_nreset (1 << 1) /* pin 3 */ + +#define spi_sck_bit (1 << 0) /* pin 2 */ +#define spi_mosi_bit (1 << 7) /* pin 9 */ + +#define usi_sck_bit (1 << 3) /* pin 5 */ +#define usi_mosi_bit (1 << 4) /* pin 6 */ + +#define vcc_bits ((1 << 6) | (1 << 5)) /* pins 7, 8 */ + +/* STATUS input bits */ +#define spi_miso_bit PARPORT_STATUS_BUSY /* pin 11 */ + +#define usi_miso_bit PARPORT_STATUS_PAPEROUT /* pin 12 */ + +/* CONTROL output bits */ +#define spi_cs_bit PARPORT_CONTROL_SELECT /* pin 17 */ +/* USI uses no chipselect */ + + + +static inline struct butterfly *spidev_to_pp(struct spi_device *spi) +{ + return spi->controller_data; +} + +static inline int is_usidev(struct spi_device *spi) +{ +#ifdef HAVE_USI + return spi->chip_select != 1; +#else + return 0; +#endif +} + + +struct butterfly { + /* REVISIT ... for now, this must be first */ + struct spi_bitbang bitbang; + + struct parport *port; + struct pardevice *pd; + + u8 lastbyte; + + struct spi_device *dataflash; + struct spi_device *butterfly; + struct spi_board_info info[2]; + +}; + +/*----------------------------------------------------------------------*/ + +/* + * these routines may be slower than necessary because they're hiding + * the fact that there are two different SPI busses on this cable: one + * to the DataFlash chip (or AVR SPI controller), the other to the + * AVR USI controller. + */ + +static inline void +setsck(struct spi_device *spi, int is_on) +{ + struct butterfly *pp = spidev_to_pp(spi); + u8 bit, byte = pp->lastbyte; + + if (is_usidev(spi)) + bit = usi_sck_bit; + else + bit = spi_sck_bit; + + if (is_on) + byte |= bit; + else + byte &= ~bit; + parport_write_data(pp->port, byte); + pp->lastbyte = byte; +} + +static inline void +setmosi(struct spi_device *spi, int is_on) +{ + struct butterfly *pp = spidev_to_pp(spi); + u8 bit, byte = pp->lastbyte; + + if (is_usidev(spi)) + bit = usi_mosi_bit; + else + bit = spi_mosi_bit; + + if (is_on) + byte |= bit; + else + byte &= ~bit; + parport_write_data(pp->port, byte); + pp->lastbyte = byte; +} + +static inline int getmiso(struct spi_device *spi) +{ + struct butterfly *pp = spidev_to_pp(spi); + int value; + u8 bit; + + if (is_usidev(spi)) + bit = usi_miso_bit; + else + bit = spi_miso_bit; + + /* only STATUS_BUSY is NOT negated */ + value = !(parport_read_status(pp->port) & bit); + return (bit == PARPORT_STATUS_BUSY) ? value : !value; +} + +static void butterfly_chipselect(struct spi_device *spi, int value) +{ + struct butterfly *pp = spidev_to_pp(spi); + + /* set default clock polarity */ + if (value) + setsck(spi, spi->mode & SPI_CPOL); + + /* no chipselect on this USI link config */ + if (is_usidev(spi)) + return; + + /* here, value == "activate or not" */ + + /* most PARPORT_CONTROL_* bits are negated */ + if (spi_cs_bit == PARPORT_CONTROL_INIT) + value = !value; + + /* here, value == "bit value to write in control register" */ + + parport_frob_control(pp->port, spi_cs_bit, value ? spi_cs_bit : 0); +} + + +/* we only needed to implement one mode here, and choose SPI_MODE_0 */ + +#define spidelay(X) do{}while(0) +//#define spidelay ndelay + +#define EXPAND_BITBANG_TXRX +#include + +static u32 +butterfly_txrx_word_mode0(struct spi_device *spi, + unsigned nsecs, + u32 word, u8 bits) +{ + return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits); +} + +/*----------------------------------------------------------------------*/ + +/* override default partitioning with cmdlinepart */ +static struct mtd_partition partitions[] = { { + /* JFFS2 wants partitions of 4*N blocks for this device ... */ + + /* sector 0 = 8 pages * 264 bytes/page (1 block) + * sector 1 = 248 pages * 264 bytes/page + */ + .name = "bookkeeping", // 66 KB + .offset = 0, + .size = (8 + 248) * 264, +// .mask_flags = MTD_WRITEABLE, +}, { + /* sector 2 = 256 pages * 264 bytes/page + * sectors 3-5 = 512 pages * 264 bytes/page + */ + .name = "filesystem", // 462 KB + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, +} }; + +static struct flash_platform_data flash = { + .name = "butterflash", + .parts = partitions, + .nr_parts = ARRAY_SIZE(partitions), +}; + + +/* REVISIT remove this ugly global and its "only one" limitation */ +static struct butterfly *butterfly; + +static void butterfly_attach(struct parport *p) +{ + struct pardevice *pd; + int status; + struct butterfly *pp; + struct spi_master *master; + struct platform_device *pdev; + + if (butterfly) + return; + + /* REVISIT: this just _assumes_ a butterfly is there ... no probe, + * and no way to be selective about what it binds to. + */ + + /* FIXME where should master->cdev.dev come from? + * e.g. /sys/bus/pnp0/00:0b, some PCI thing, etc + * setting up a platform device like this is an ugly kluge... + */ + pdev = platform_device_register_simple("butterfly", -1, NULL, 0); + + master = spi_alloc_master(&pdev->dev, sizeof *pp); + if (!master) { + status = -ENOMEM; + goto done; + } + pp = spi_master_get_devdata(master); + + /* + * SPI and bitbang hookup + * + * use default setup(), cleanup(), and transfer() methods; and + * only bother implementing mode 0. Start it later. + */ + master->bus_num = 42; + master->num_chipselect = 2; + + pp->bitbang.master = spi_master_get(master); + pp->bitbang.chipselect = butterfly_chipselect; + pp->bitbang.txrx_word[SPI_MODE_0] = butterfly_txrx_word_mode0; + + /* + * parport hookup + */ + pp->port = p; + pd = parport_register_device(p, "spi_butterfly", + NULL, NULL, NULL, + 0 /* FLAGS */, pp); + if (!pd) { + status = -ENOMEM; + goto clean0; + } + pp->pd = pd; + + status = parport_claim(pd); + if (status < 0) + goto clean1; + + /* + * Butterfly reset, powerup, run firmware + */ + pr_debug("%s: powerup/reset Butterfly\n", p->name); + + /* nCS for dataflash (this bit is inverted on output) */ + parport_frob_control(pp->port, spi_cs_bit, 0); + + /* stabilize power with chip in reset (nRESET), and + * both spi_sck_bit and usi_sck_bit clear (CPOL=0) + */ + pp->lastbyte |= vcc_bits; + parport_write_data(pp->port, pp->lastbyte); + msleep(5); + + /* take it out of reset; assume long reset delay */ + pp->lastbyte |= butterfly_nreset; + parport_write_data(pp->port, pp->lastbyte); + msleep(100); + + + /* + * Start SPI ... for now, hide that we're two physical busses. + */ + status = spi_bitbang_start(&pp->bitbang); + if (status < 0) + goto clean2; + + /* Bus 1 lets us talk to at45db041b (firmware disables AVR) + * or AVR (firmware resets at45, acts as spi slave) + */ + pp->info[0].max_speed_hz = 15 * 1000 * 1000; + strcpy(pp->info[0].modalias, "mtd_dataflash"); + pp->info[0].platform_data = &flash; + pp->info[0].chip_select = 1; + pp->info[0].controller_data = pp; + pp->dataflash = spi_new_device(pp->bitbang.master, &pp->info[0]); + if (pp->dataflash) + pr_debug("%s: dataflash at %s\n", p->name, + pp->dataflash->dev.bus_id); + +#ifdef HAVE_USI + /* even more custom AVR firmware */ + pp->info[1].max_speed_hz = 10 /* ?? */ * 1000 * 1000; + strcpy(pp->info[1].modalias, "butterfly"); + // pp->info[1].platform_data = ... TBD ... ; + pp->info[1].chip_select = 2, + pp->info[1].controller_data = pp; + pp->butterfly = spi_new_device(pp->bitbang.master, &pp->info[1]); + if (pp->butterfly) + pr_debug("%s: butterfly at %s\n", p->name, + pp->butterfly->dev.bus_id); + + /* FIXME setup ACK for the IRQ line ... */ +#endif + + // dev_info(_what?_, ...) + pr_info("%s: AVR Butterfly\n", p->name); + butterfly = pp; + return; + +clean2: + /* turn off VCC */ + parport_write_data(pp->port, 0); + + parport_release(pp->pd); +clean1: + parport_unregister_device(pd); +clean0: + (void) spi_master_put(pp->bitbang.master); +done: + platform_device_unregister(pdev); + pr_debug("%s: butterfly probe, fail %d\n", p->name, status); +} + +static void butterfly_detach(struct parport *p) +{ + struct butterfly *pp; + struct platform_device *pdev; + int status; + + /* FIXME this global is ugly ... but, how to quickly get from + * the parport to the "struct butterfly" associated with it? + * "old school" driver-internal device lists? + */ + if (!butterfly || butterfly->port != p) + return; + pp = butterfly; + butterfly = NULL; + +#ifdef HAVE_USI + spi_unregister_device(pp->butterfly); + pp->butterfly = NULL; +#endif + spi_unregister_device(pp->dataflash); + pp->dataflash = NULL; + + status = spi_bitbang_stop(&pp->bitbang); + + /* turn off VCC */ + parport_write_data(pp->port, 0); + msleep(10); + + parport_release(pp->pd); + parport_unregister_device(pp->pd); + + pdev = to_platform_device(pp->bitbang.master->cdev.dev); + + (void) spi_master_put(pp->bitbang.master); + + platform_device_unregister(pdev); +} + +static struct parport_driver butterfly_driver = { + .name = "spi_butterfly", + .attach = butterfly_attach, + .detach = butterfly_detach, +}; + + +static int __init butterfly_init(void) +{ + return parport_register_driver(&butterfly_driver); +} +device_initcall(butterfly_init); + +static void __exit butterfly_exit(void) +{ + parport_unregister_driver(&butterfly_driver); +} +module_exit(butterfly_exit); + +MODULE_LICENSE("GPL"); -- GitLab From 91f62a2491f45b5d46ebe5aca1fac3477355c9c1 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 14 Jan 2006 11:17:32 +1100 Subject: [PATCH 164/465] ppc: Remove duplicate export of get_wchan The arch/powerpc version of process.c exports get_wchan itself. When I moved ARCH=ppc over to using arch/powerpc/kernel/process.c the get_wchan export in arch/ppc/kernel/ppc_ksyms.c became redundant, so remove it. Signed-off-by: Paul Mackerras (cherry picked from 9871166ad692121d6b944159ef3f053570158ea8 commit) --- arch/ppc/kernel/ppc_ksyms.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index 95075f99a6d..fb0da7c209d 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c @@ -270,7 +270,6 @@ EXPORT_SYMBOL(__delay); EXPORT_SYMBOL(timer_interrupt); EXPORT_SYMBOL(irq_desc); EXPORT_SYMBOL(tb_ticks_per_jiffy); -EXPORT_SYMBOL(get_wchan); EXPORT_SYMBOL(console_drivers); #ifdef CONFIG_XMON EXPORT_SYMBOL(xmon); -- GitLab From 91dc182ca6e25ee8b648ed2fb2a41859ead34903 Mon Sep 17 00:00:00 2001 From: Dave C Boutcher Date: Fri, 13 Jan 2006 18:39:24 -0600 Subject: [PATCH 165/465] [PATCH] powerpc: special-case ibm,suspend-me RTAS call Handle the ibm,suspend-me RTAS call specially. It needs to be wrapped in a set of synchronization hypervisor calls (H_Join). When the H_Join calls are made on all CPUs, the intent is that only one will return with H_Continue, meaning that he is the "last man standing". That CPU then issues the ibm,suspend-me call. What is interesting, of course, is that the CPU running when the rtas syscall is made, may NOT be the CPU that ultimately executes the ibm,suspend-me rtas call. Signed-off-by: Dave Boutcher Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/rtas.c | 96 +++++++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 4b9cfe4637b..7fe4a5c944c 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -36,6 +36,11 @@ struct rtas_t rtas = { .lock = SPIN_LOCK_UNLOCKED }; +struct rtas_suspend_me_data { + long waiting; + struct rtas_args *args; +}; + EXPORT_SYMBOL(rtas); DEFINE_SPINLOCK(rtas_data_buf_lock); @@ -556,6 +561,80 @@ void rtas_os_term(char *str) } while (status == RTAS_BUSY); } +static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE; +#ifdef CONFIG_PPC_PSERIES +static void rtas_percpu_suspend_me(void *info) +{ + long rc; + long flags; + struct rtas_suspend_me_data *data = + (struct rtas_suspend_me_data *)info; + + /* + * We use "waiting" to indicate our state. As long + * as it is >0, we are still trying to all join up. + * If it goes to 0, we have successfully joined up and + * one thread got H_Continue. If any error happens, + * we set it to <0. + */ + local_irq_save(flags); + do { + rc = plpar_hcall_norets(H_JOIN); + smp_rmb(); + } while (rc == H_Success && data->waiting > 0); + if (rc == H_Success) + goto out; + + if (rc == H_Continue) { + data->waiting = 0; + rtas_call(ibm_suspend_me_token, 0, 1, + data->args->args); + } else { + data->waiting = -EBUSY; + printk(KERN_ERR "Error on H_Join hypervisor call\n"); + } + +out: + /* before we restore interrupts, make sure we don't + * generate a spurious soft lockup errors + */ + touch_softlockup_watchdog(); + local_irq_restore(flags); + return; +} + +static int rtas_ibm_suspend_me(struct rtas_args *args) +{ + int i; + + struct rtas_suspend_me_data data; + + data.waiting = 1; + data.args = args; + + /* Call function on all CPUs. One of us will make the + * rtas call + */ + if (on_each_cpu(rtas_percpu_suspend_me, &data, 1, 0)) + data.waiting = -EINVAL; + + if (data.waiting != 0) + printk(KERN_ERR "Error doing global join\n"); + + /* Prod each CPU. This won't hurt, and will wake + * anyone we successfully put to sleep with H_Join + */ + for_each_cpu(i) + plpar_hcall_norets(H_PROD, i); + + return data.waiting; +} +#else /* CONFIG_PPC_PSERIES */ +static int rtas_ibm_suspend_me(struct rtas_args *args) +{ + return -ENOSYS; +} +#endif asmlinkage int ppc_rtas(struct rtas_args __user *uargs) { @@ -563,6 +642,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) unsigned long flags; char *buff_copy, *errbuf = NULL; int nargs; + int rc; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -581,6 +661,17 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) nargs * sizeof(rtas_arg_t)) != 0) return -EFAULT; + if (args.token == RTAS_UNKNOWN_SERVICE) + return -EINVAL; + + /* Need to handle ibm,suspend_me call specially */ + if (args.token == ibm_suspend_me_token) { + rc = rtas_ibm_suspend_me(&args); + if (rc) + return rc; + goto copy_return; + } + buff_copy = get_errorlog_buffer(); spin_lock_irqsave(&rtas.lock, flags); @@ -604,6 +695,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) kfree(buff_copy); } + copy_return: /* Copy out args. */ if (copy_to_user(uargs->args + nargs, args.args + nargs, @@ -675,8 +767,10 @@ void __init rtas_initialize(void) * the stop-self token if any */ #ifdef CONFIG_PPC64 - if (_machine == PLATFORM_PSERIES_LPAR) + if (_machine == PLATFORM_PSERIES_LPAR) { rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX); + ibm_suspend_me_token = rtas_token("ibm,suspend-me"); + } #endif rtas_rmo_buf = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, rtas_region); -- GitLab From 575e321606c5673efabf28c0fa075e198980c44e Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Sat, 14 Jan 2006 00:13:49 +0000 Subject: [PATCH 166/465] [PATCH] powerpc: Make CHRP build again This makes CHRP build again, although it's untested because my Pegasos is currently in pieces. Signed-off-by: David Woodhouse Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/chrp/pci.c | 27 +++++++++++++++++---------- arch/powerpc/platforms/chrp/setup.c | 7 ++++--- arch/powerpc/platforms/chrp/time.c | 7 +++++-- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c index 82c429d487f..00c52f27ef4 100644 --- a/arch/powerpc/platforms/chrp/pci.c +++ b/arch/powerpc/platforms/chrp/pci.c @@ -135,12 +135,13 @@ int __init hydra_init(void) { struct device_node *np; + struct resource r; np = find_devices("mac-io"); - if (np == NULL || np->n_addrs == 0) + if (np == NULL || of_address_to_resource(np, 0, &r)) return 0; - Hydra = ioremap(np->addrs[0].address, np->addrs[0].size); - printk("Hydra Mac I/O at %lx\n", np->addrs[0].address); + Hydra = ioremap(r.start, r.end-r.start); + printk("Hydra Mac I/O at %lx\n", r.start); printk("Hydra Feature_Control was %x", in_le32(&Hydra->Feature_Control)); out_le32(&Hydra->Feature_Control, (HYDRA_FC_SCC_CELL_EN | @@ -177,18 +178,24 @@ setup_python(struct pci_controller *hose, struct device_node *dev) { u32 __iomem *reg; u32 val; - unsigned long addr = dev->addrs[0].address; + struct resource r; - setup_indirect_pci(hose, addr + 0xf8000, addr + 0xf8010); + if (of_address_to_resource(dev, 0, &r)) { + printk(KERN_ERR "No address for Python PCI controller\n"); + return; + } /* Clear the magic go-slow bit */ - reg = ioremap(dev->addrs[0].address + 0xf6000, 0x40); + reg = ioremap(r.start + 0xf6000, 0x40); + BUG_ON(!reg); val = in_be32(®[12]); if (val & PRG_CL_RESET_VALID) { out_be32(®[12], val & ~PRG_CL_RESET_VALID); in_be32(®[12]); } iounmap(reg); + + setup_indirect_pci(hose, r.start + 0xf8000, r.start + 0xf8010); } /* Marvell Discovery II based Pegasos 2 */ @@ -218,7 +225,7 @@ chrp_find_bridges(void) char *model, *machine; int is_longtrail = 0, is_mot = 0, is_pegasos = 0; struct device_node *root = find_path_device("/"); - + struct resource r; /* * The PCI host bridge nodes on some machines don't have * properties to adequately identify them, so we have to @@ -238,7 +245,7 @@ chrp_find_bridges(void) continue; ++index; /* The GG2 bridge on the LongTrail doesn't have an address */ - if (dev->n_addrs < 1 && !is_longtrail) { + if (of_address_to_resource(dev, 0, &r) && !is_longtrail) { printk(KERN_WARNING "Can't use %s: no address\n", dev->full_name); continue; @@ -255,8 +262,8 @@ chrp_find_bridges(void) printk(KERN_INFO "PCI buses %d..%d", bus_range[0], bus_range[1]); printk(" controlled by %s", dev->type); - if (dev->n_addrs > 0) - printk(" at %lx", dev->addrs[0].address); + if (!is_longtrail) + printk(" at %lx", r.start); printk("\n"); hose = pcibios_alloc_controller(); diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 4ec8ba737e7..2dc87aa5962 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -352,9 +352,10 @@ static void __init chrp_find_openpic(void) opaddr = opprop[na-1]; /* assume 32-bit */ oplen /= na * sizeof(unsigned int); } else { - if (np->n_addrs == 0) + struct resource r; + if (of_address_to_resource(np, 0, &r)) return; - opaddr = np->addrs[0].address; + opaddr = r.start; oplen = 0; } @@ -377,7 +378,7 @@ static void __init chrp_find_openpic(void) */ if (oplen < len) { printk(KERN_ERR "Insufficient addresses for distributed" - " OpenPIC (%d < %d)\n", np->n_addrs, len); + " OpenPIC (%d < %d)\n", oplen, len); len = oplen; } diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c index 737ee5d9f0a..36a0f97bb7b 100644 --- a/arch/powerpc/platforms/chrp/time.c +++ b/arch/powerpc/platforms/chrp/time.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -37,14 +38,16 @@ static int nvram_data = NVRAM_DATA; long __init chrp_time_init(void) { struct device_node *rtcs; + struct resource r; int base; rtcs = find_compatible_devices("rtc", "pnpPNP,b00"); if (rtcs == NULL) rtcs = find_compatible_devices("rtc", "ds1385-rtc"); - if (rtcs == NULL || rtcs->addrs == NULL) + if (rtcs == NULL || of_address_to_resource(rtcs, 0, &r)) return 0; - base = rtcs->addrs[0].address; + + base = r.start; nvram_as1 = 0; nvram_as0 = base; nvram_data = base + 1; -- GitLab From 36874579dbf4cafa31486d4207c6807efbbf1378 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Sat, 14 Jan 2006 00:15:19 +0000 Subject: [PATCH 167/465] [PATCH] powerpc: macio-adb build fix This makes macio-adb.c build again. Entirely untested. Signed-off-by: David Woodhouse Signed-off-by: Paul Mackerras --- drivers/macintosh/macio-adb.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/macintosh/macio-adb.c b/drivers/macintosh/macio-adb.c index cf6a6f2248a..314fc0830d9 100644 --- a/drivers/macintosh/macio-adb.c +++ b/drivers/macintosh/macio-adb.c @@ -17,6 +17,7 @@ #include #include #include +#include struct preg { unsigned char r; @@ -88,24 +89,26 @@ int macio_probe(void) int macio_init(void) { struct device_node *adbs; + struct resource r; adbs = find_compatible_devices("adb", "chrp,adb0"); if (adbs == 0) return -ENXIO; #if 0 - { int i; + { int i = 0; printk("macio_adb_init: node = %p, addrs =", adbs->node); - for (i = 0; i < adbs->n_addrs; ++i) - printk(" %x(%x)", adbs->addrs[i].address, adbs->addrs[i].size); + while(!of_address_to_resource(adbs, i, &r)) + printk(" %x(%x)", r.start, r.end - r.start); printk(", intrs ="); for (i = 0; i < adbs->n_intrs; ++i) printk(" %x", adbs->intrs[i].line); printk("\n"); } #endif - - adb = ioremap(adbs->addrs->address, sizeof(struct adb_regs)); + if (of_address_to_resource(adbs, 0, &r)) + return -ENXIO; + adb = ioremap(r.start, sizeof(struct adb_regs)); out_8(&adb->ctrl.r, 0); out_8(&adb->intr.r, 0); -- GitLab From 66a45dd3620ee5f913ba1af3d2dca8b9bdfa2b96 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 14 Jan 2006 15:04:06 +1100 Subject: [PATCH 168/465] powerpc: Make COFF zImages for old 32-bit powermacs This adds code to build zImage.coff and/or zImage.initrd.coff when CONFIG_PPC32 and CONFIG_PPC_PMAC are defined. It also restructures the OF client code and adds some workarounds for OF quirks on the older machines. Signed-off-by: Paul Mackerras --- arch/powerpc/boot/Makefile | 49 ++- arch/powerpc/boot/crt0.S | 21 +- arch/powerpc/boot/hack-coff.c | 84 +++++ arch/powerpc/boot/main.c | 46 ++- arch/powerpc/boot/prom.c | 538 ++++++------------------------ arch/powerpc/boot/prom.h | 36 +- arch/powerpc/boot/rs6000.h | 243 ++++++++++++++ arch/powerpc/boot/stdio.c | 325 ++++++++++++++++++ arch/powerpc/boot/stdio.h | 6 - arch/powerpc/boot/zImage.coff.lds | 46 +++ 10 files changed, 895 insertions(+), 499 deletions(-) create mode 100644 arch/powerpc/boot/hack-coff.c create mode 100644 arch/powerpc/boot/rs6000.h create mode 100644 arch/powerpc/boot/stdio.c create mode 100644 arch/powerpc/boot/zImage.coff.lds diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index b53d677f674..788dec4c7ef 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -25,8 +25,8 @@ HOSTCC := gcc BOOTCFLAGS := $(HOSTCFLAGS) -fno-builtin -nostdinc -isystem \ $(shell $(CROSS32CC) -print-file-name=include) -fPIC BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc -BOOTLFLAGS := -T $(srctree)/$(src)/zImage.lds OBJCOPYFLAGS := contents,alloc,load,readonly,data +OBJCOPY_COFF_ARGS := -O aixcoff-rs6000 --set-start 0x500000 zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c zlibheader := infblock.h infcodes.h inffast.h inftrees.h infutil.h @@ -35,7 +35,7 @@ zliblinuxheader := zlib.h zconf.h zutil.h $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader)) #$(addprefix $(obj)/,main.o): $(addprefix $(obj)/,zlib.h) -src-boot := string.S prom.c main.c div64.S crt0.S +src-boot := crt0.S string.S prom.c stdio.c main.c div64.S src-boot += $(zlib) src-boot := $(addprefix $(obj)/, $(src-boot)) obj-boot := $(addsuffix .o, $(basename $(src-boot))) @@ -70,7 +70,7 @@ quiet_cmd_bootas = BOOTAS $@ cmd_bootas = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $< quiet_cmd_bootld = BOOTLD $@ - cmd_bootld = $(CROSS32LD) $(BOOTLFLAGS) -o $@ $(2) + cmd_bootld = $(CROSS32LD) -T $(srctree)/$(src)/$(3) -o $@ $(2) $(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c $(call if_changed_dep,bootcc) @@ -87,12 +87,14 @@ obj-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.o, $(section))) src-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.c, $(section))) gz-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.gz, $(section))) -hostprogs-y := addnote addRamDisk -targets += zImage.vmode zImage.initrd.vmode zImage zImage.initrd \ - $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \ - $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \ - $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \ - vmlinux.initrd +hostprogs-y := addnote addRamDisk hack-coff + +targets += zImage.vmode zImage.initrd.vmode zImage zImage.initrd \ + zImage.coff zImage.initrd.coff \ + $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \ + $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \ + $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \ + vmlinux.initrd extra-y := initrd.o quiet_cmd_ramdisk = RAMDISK $@ @@ -114,6 +116,10 @@ quiet_cmd_addsection = ADDSEC $@ quiet_cmd_addnote = ADDNOTE $@ cmd_addnote = $(obj)/addnote $@ +quiet_cmd_gencoff = COFF $@ + cmd_gencoff = $(OBJCOPY) $(OBJCOPY_COFF_ARGS) $@ && \ + $(obj)/hack-coff $@ + $(call gz-sec, $(required)): $(obj)/kernel-%.gz: % $(call if_changed,gzip) @@ -127,22 +133,35 @@ $(call obj-sec, $(required) $(initrd)): $(obj)/kernel-%.o: $(obj)/kernel-%.c $(call if_changed_dep,bootcc) $(call cmd,addsection) -$(obj)/zImage.vmode: obj-boot += $(call obj-sec, $(required)) +$(obj)/zImage.vmode $(obj)/zImage.coff: obj-boot += $(call obj-sec, $(required)) $(obj)/zImage.vmode: $(call obj-sec, $(required)) $(obj-boot) $(srctree)/$(src)/zImage.lds - $(call cmd,bootld,$(obj-boot)) + $(call cmd,bootld,$(obj-boot),zImage.lds) -$(obj)/zImage.initrd.vmode: obj-boot += $(call obj-sec, $(required) $(initrd)) +$(obj)/zImage.initrd.vmode $(obj)/zImage.initrd.coff: obj-boot += $(call obj-sec, $(required) $(initrd)) $(obj)/zImage.initrd.vmode: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(srctree)/$(src)/zImage.lds - $(call cmd,bootld,$(obj-boot)) + $(call cmd,bootld,$(obj-boot),zImage.lds) + +# For 32-bit powermacs, build the COFF images as well as the ELF images. +coffimage-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/zImage.coff +coffrdimg-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/zImage.initrd.coff -$(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote +$(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote $(coffimage-y-y) @cp -f $< $@ $(call if_changed,addnote) -$(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote +$(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote $(coffrdimg-y-y) @cp -f $< $@ $(call if_changed,addnote) +$(obj)/zImage.coff: $(call obj-sec, $(required)) $(obj-boot) $(srctree)/$(src)/zImage.coff.lds $(obj)/hack-coff + $(call cmd,bootld,$(obj-boot),zImage.coff.lds) + $(call cmd,gencoff) + +$(obj)/zImage.initrd.coff: $(call obj-sec, $(required) $(initrd)) $(obj-boot) \ + $(srctree)/$(src)/zImage.coff.lds $(obj)/hack-coff + $(call cmd,bootld,$(obj-boot),zImage.coff.lds) + $(call cmd,gencoff) + #----------------------------------------------------------- # build u-boot images #----------------------------------------------------------- diff --git a/arch/powerpc/boot/crt0.S b/arch/powerpc/boot/crt0.S index d2f2ace56cd..e0192c26037 100644 --- a/arch/powerpc/boot/crt0.S +++ b/arch/powerpc/boot/crt0.S @@ -12,17 +12,23 @@ #include "ppc_asm.h" .text + /* a procedure descriptor used when booting this as a COFF file */ +_zimage_start_opd: + .long _zimage_start, 0, 0, 0 + .globl _zimage_start _zimage_start: + /* Work out the offset between the address we were linked at + and the address where we're running. */ bl 1f - -1: - mflr r0 +1: mflr r0 lis r9,1b@ha addi r9,r9,1b@l subf. r0,r9,r0 - beq 3f + beq 3f /* if running at same address as linked */ + /* The .got2 section contains a list of addresses, so add + the address offset onto each entry. */ lis r9,__got2_start@ha addi r9,r9,__got2_start@l lis r8,__got2_end@ha @@ -32,15 +38,14 @@ _zimage_start: srwi. r8,r8,2 mtctr r8 add r9,r0,r9 -2: - lwz r8,0(r9) +2: lwz r8,0(r9) add r8,r8,r0 stw r8,0(r9) addi r9,r9,4 bdnz 2b -3: - lis r9,_start@h + /* Do a cache flush for our text, in case OF didn't */ +3: lis r9,_start@h add r9,r0,r9 lis r8,_etext@ha addi r8,r8,_etext@l diff --git a/arch/powerpc/boot/hack-coff.c b/arch/powerpc/boot/hack-coff.c new file mode 100644 index 00000000000..5e5a6573a1e --- /dev/null +++ b/arch/powerpc/boot/hack-coff.c @@ -0,0 +1,84 @@ +/* + * hack-coff.c - hack the header of an xcoff file to fill in + * a few fields needed by the Open Firmware xcoff loader on + * Power Macs but not initialized by objcopy. + * + * Copyright (C) Paul Mackerras 1997. + * + * 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 +#include +#include +#include +#include +#include "rs6000.h" + +#define AOUT_MAGIC 0x010b + +#define get_16be(x) ((((unsigned char *)(x))[0] << 8) \ + + ((unsigned char *)(x))[1]) +#define put_16be(x, v) (((unsigned char *)(x))[0] = (v) >> 8, \ + ((unsigned char *)(x))[1] = (v) & 0xff) +#define get_32be(x) ((((unsigned char *)(x))[0] << 24) \ + + (((unsigned char *)(x))[1] << 16) \ + + (((unsigned char *)(x))[2] << 8) \ + + ((unsigned char *)(x))[3]) + +int +main(int ac, char **av) +{ + int fd; + int i, nsect; + int aoutsz; + struct external_filehdr fhdr; + AOUTHDR aout; + struct external_scnhdr shdr; + + if (ac != 2) { + fprintf(stderr, "Usage: hack-coff coff-file\n"); + exit(1); + } + if ((fd = open(av[1], 2)) == -1) { + perror(av[2]); + exit(1); + } + if (read(fd, &fhdr, sizeof(fhdr)) != sizeof(fhdr)) + goto readerr; + i = get_16be(fhdr.f_magic); + if (i != U802TOCMAGIC && i != U802WRMAGIC && i != U802ROMAGIC) { + fprintf(stderr, "%s: not an xcoff file\n", av[1]); + exit(1); + } + aoutsz = get_16be(fhdr.f_opthdr); + if (read(fd, &aout, aoutsz) != aoutsz) + goto readerr; + nsect = get_16be(fhdr.f_nscns); + for (i = 0; i < nsect; ++i) { + if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr)) + goto readerr; + if (strcmp(shdr.s_name, ".text") == 0) { + put_16be(aout.o_snentry, i+1); + put_16be(aout.o_sntext, i+1); + } else if (strcmp(shdr.s_name, ".data") == 0) { + put_16be(aout.o_sndata, i+1); + } else if (strcmp(shdr.s_name, ".bss") == 0) { + put_16be(aout.o_snbss, i+1); + } + } + put_16be(aout.magic, AOUT_MAGIC); + if (lseek(fd, (long) sizeof(struct external_filehdr), 0) == -1 + || write(fd, &aout, aoutsz) != aoutsz) { + fprintf(stderr, "%s: write error\n", av[1]); + exit(1); + } + close(fd); + exit(0); + +readerr: + fprintf(stderr, "%s: read error or file too short\n", av[1]); + exit(1); +} diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c index 64ec93116fa..55ec5986725 100644 --- a/arch/powerpc/boot/main.c +++ b/arch/powerpc/boot/main.c @@ -21,8 +21,8 @@ extern void flush_cache(void *, unsigned long); /* Value picked to match that used by yaboot */ -#define PROG_START 0x01400000 -#define RAM_END (512<<20) // Fixme: use OF */ +#define PROG_START 0x01400000 /* only used on 64-bit systems */ +#define RAM_END (512<<20) /* Fixme: use OF */ #define ONE_MB 0x100000 extern char _start[]; @@ -160,6 +160,17 @@ static int is_elf64(void *hdr) elfoffset = (unsigned long)elf64ph->p_offset; vmlinux.size = (unsigned long)elf64ph->p_filesz + elfoffset; vmlinux.memsize = (unsigned long)elf64ph->p_memsz + elfoffset; + +#if defined(PROG_START) + /* + * Maintain a "magic" minimum address. This keeps some older + * firmware platforms running. + */ + + if (claim_base < PROG_START) + claim_base = PROG_START; +#endif + return 1; } @@ -206,12 +217,18 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) exit(); if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4) exit(); - stderr = stdout; - if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4) - exit(); printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start, sp); + /* + * The first available claim_base must be above the end of the + * the loaded kernel wrapper file (_start to _end includes the + * initrd image if it is present) and rounded up to a nice + * 1 MB boundary for good measure. + */ + + claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB); + vmlinuz.addr = (unsigned long)_vmlinux_start; vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start); @@ -228,25 +245,6 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) exit(); } - /* - * The first available claim_base must be above the end of the - * the loaded kernel wrapper file (_start to _end includes the - * initrd image if it is present) and rounded up to a nice - * 1 MB boundary for good measure. - */ - - claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB); - -#if defined(PROG_START) - /* - * Maintain a "magic" minimum address. This keeps some older - * firmware platforms running. - */ - - if (claim_base < PROG_START) - claim_base = PROG_START; -#endif - /* We need to claim the memsize plus the file offset since gzip * will expand the header (file offset), then the kernel, then * possible rubbish we don't care about. But the kernel bss must diff --git a/arch/powerpc/boot/prom.c b/arch/powerpc/boot/prom.c index 4bea2f4dcb0..fa0057736f6 100644 --- a/arch/powerpc/boot/prom.c +++ b/arch/powerpc/boot/prom.c @@ -13,487 +13,153 @@ #include "prom.h" int (*prom)(void *); +phandle chosen_handle; +ihandle stdout; -void *chosen_handle; - -void *stdin; -void *stdout; -void *stderr; - - -int -write(void *handle, void *ptr, int nb) -{ - struct prom_args { - char *service; - int nargs; - int nret; - void *ihandle; - void *addr; - int len; - int actual; - } args; - - args.service = "write"; - args.nargs = 3; - args.nret = 1; - args.ihandle = handle; - args.addr = ptr; - args.len = nb; - args.actual = -1; - (*prom)(&args); - return args.actual; -} - -int -read(void *handle, void *ptr, int nb) +int call_prom(const char *service, int nargs, int nret, ...) { + int i; struct prom_args { - char *service; + const char *service; int nargs; int nret; - void *ihandle; - void *addr; - int len; - int actual; - } args; - - args.service = "read"; - args.nargs = 3; - args.nret = 1; - args.ihandle = handle; - args.addr = ptr; - args.len = nb; - args.actual = -1; - (*prom)(&args); - return args.actual; -} - -void -exit() -{ - struct prom_args { - char *service; - } args; - - for (;;) { - args.service = "exit"; - (*prom)(&args); - } -} - -void -pause(void) -{ - struct prom_args { - char *service; + unsigned int args[12]; } args; + va_list list; - args.service = "enter"; - (*prom)(&args); -} + args.service = service; + args.nargs = nargs; + args.nret = nret; -void * -finddevice(const char *name) -{ - struct prom_args { - char *service; - int nargs; - int nret; - const char *devspec; - void *phandle; - } args; + va_start(list, nret); + for (i = 0; i < nargs; i++) + args.args[i] = va_arg(list, unsigned int); + va_end(list); - args.service = "finddevice"; - args.nargs = 1; - args.nret = 1; - args.devspec = name; - args.phandle = (void *) -1; - (*prom)(&args); - return args.phandle; -} + for (i = 0; i < nret; i++) + args.args[nargs+i] = 0; -void * -claim(unsigned long virt, unsigned long size, unsigned long align) -{ - struct prom_args { - char *service; - int nargs; - int nret; - unsigned int virt; - unsigned int size; - unsigned int align; - void *ret; - } args; + if (prom(&args) < 0) + return -1; - args.service = "claim"; - args.nargs = 3; - args.nret = 1; - args.virt = virt; - args.size = size; - args.align = align; - (*prom)(&args); - return args.ret; + return (nret > 0)? args.args[nargs]: 0; } -int -getprop(void *phandle, const char *name, void *buf, int buflen) +int call_prom_ret(const char *service, int nargs, int nret, + unsigned int *rets, ...) { + int i; struct prom_args { - char *service; + const char *service; int nargs; int nret; - void *phandle; - const char *name; - void *buf; - int buflen; - int size; + unsigned int args[12]; } args; + va_list list; - args.service = "getprop"; - args.nargs = 4; - args.nret = 1; - args.phandle = phandle; - args.name = name; - args.buf = buf; - args.buflen = buflen; - args.size = -1; - (*prom)(&args); - return args.size; -} + args.service = service; + args.nargs = nargs; + args.nret = nret; -int -putc(int c, void *f) -{ - char ch = c; + va_start(list, rets); + for (i = 0; i < nargs; i++) + args.args[i] = va_arg(list, unsigned int); + va_end(list); - if (c == '\n') - putc('\r', f); - return write(f, &ch, 1) == 1? c: -1; -} + for (i = 0; i < nret; i++) + args.args[nargs+i] = 0; -int -putchar(int c) -{ - return putc(c, stdout); -} + if (prom(&args) < 0) + return -1; -int -fputs(char *str, void *f) -{ - int n = strlen(str); + if (rets != (void *) 0) + for (i = 1; i < nret; ++i) + rets[i-1] = args.args[nargs+i]; - return write(f, str, n) == n? 0: -1; + return (nret > 0)? args.args[nargs]: 0; } -size_t strnlen(const char * s, size_t count) +int write(void *handle, void *ptr, int nb) { - const char *sc; - - for (sc = s; count-- && *sc != '\0'; ++sc) - /* nothing */; - return sc - s; + return call_prom("write", 3, 1, handle, ptr, nb); } -extern unsigned int __div64_32(unsigned long long *dividend, - unsigned int divisor); - -/* The unnecessary pointer compare is there - * to check for type safety (n must be 64bit) +/* + * Older OF's require that when claiming a specific range of addresses, + * we claim the physical space in the /memory node and the virtual + * space in the chosen mmu node, and then do a map operation to + * map virtual to physical. */ -# define do_div(n,base) ({ \ - unsigned int __base = (base); \ - unsigned int __rem; \ - (void)(((typeof((n)) *)0) == ((unsigned long long *)0)); \ - if (((n) >> 32) == 0) { \ - __rem = (unsigned int)(n) % __base; \ - (n) = (unsigned int)(n) / __base; \ - } else \ - __rem = __div64_32(&(n), __base); \ - __rem; \ - }) +static int need_map = -1; +static ihandle chosen_mmu; +static phandle memory; -static int skip_atoi(const char **s) +/* returns true if s2 is a prefix of s1 */ +static int string_match(const char *s1, const char *s2) { - int i, c; - - for (i = 0; '0' <= (c = **s) && c <= '9'; ++*s) - i = i*10 + c - '0'; - return i; + for (; *s2; ++s2) + if (*s1++ != *s2) + return 0; + return 1; } -#define ZEROPAD 1 /* pad with zero */ -#define SIGN 2 /* unsigned/signed long */ -#define PLUS 4 /* show plus */ -#define SPACE 8 /* space if plus */ -#define LEFT 16 /* left justified */ -#define SPECIAL 32 /* 0x */ -#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ - -static char * number(char * str, unsigned long long num, int base, int size, int precision, int type) +static int check_of_version(void) { - char c,sign,tmp[66]; - const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; - int i; + phandle oprom, chosen; + char version[64]; - if (type & LARGE) - digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - if (type & LEFT) - type &= ~ZEROPAD; - if (base < 2 || base > 36) + oprom = finddevice("/openprom"); + if (oprom == (phandle) -1) return 0; - c = (type & ZEROPAD) ? '0' : ' '; - sign = 0; - if (type & SIGN) { - if ((signed long long)num < 0) { - sign = '-'; - num = - (signed long long)num; - size--; - } else if (type & PLUS) { - sign = '+'; - size--; - } else if (type & SPACE) { - sign = ' '; - size--; + if (getprop(oprom, "model", version, sizeof(version)) <= 0) + return 0; + version[sizeof(version)-1] = 0; + printf("OF version = '%s'\r\n", version); + if (!string_match(version, "Open Firmware, 1.") + && !string_match(version, "FirmWorks,3.")) + return 0; + chosen = finddevice("/chosen"); + if (chosen == (phandle) -1) { + chosen = finddevice("/chosen@0"); + if (chosen == (phandle) -1) { + printf("no chosen\n"); + return 0; } } - if (type & SPECIAL) { - if (base == 16) - size -= 2; - else if (base == 8) - size--; - } - i = 0; - if (num == 0) - tmp[i++]='0'; - else while (num != 0) { - tmp[i++] = digits[do_div(num, base)]; + if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) { + printf("no mmu\n"); + return 0; } - if (i > precision) - precision = i; - size -= precision; - if (!(type&(ZEROPAD+LEFT))) - while(size-->0) - *str++ = ' '; - if (sign) - *str++ = sign; - if (type & SPECIAL) { - if (base==8) - *str++ = '0'; - else if (base==16) { - *str++ = '0'; - *str++ = digits[33]; + memory = (ihandle) call_prom("open", 1, 1, "/memory"); + if (memory == (ihandle) -1) { + memory = (ihandle) call_prom("open", 1, 1, "/memory@0"); + if (memory == (ihandle) -1) { + printf("no memory node\n"); + return 0; } } - if (!(type & LEFT)) - while (size-- > 0) - *str++ = c; - while (i < precision--) - *str++ = '0'; - while (i-- > 0) - *str++ = tmp[i]; - while (size-- > 0) - *str++ = ' '; - return str; + printf("old OF detected\r\n"); + return 1; } -int vsprintf(char *buf, const char *fmt, va_list args) +void *claim(unsigned long virt, unsigned long size, unsigned long align) { - int len; - unsigned long long num; - int i, base; - char * str; - const char *s; - - int flags; /* flags to number() */ - - int field_width; /* width of output field */ - int precision; /* min. # of digits for integers; max - number of chars for from string */ - int qualifier; /* 'h', 'l', or 'L' for integer fields */ - /* 'z' support added 23/7/1999 S.H. */ - /* 'z' changed to 'Z' --davidm 1/25/99 */ + int ret; + unsigned int result; + if (need_map < 0) + need_map = check_of_version(); + if (align || !need_map) + return (void *) call_prom("claim", 3, 1, virt, size, align); - for (str=buf ; *fmt ; ++fmt) { - if (*fmt != '%') { - *str++ = *fmt; - continue; - } - - /* process flags */ - flags = 0; - repeat: - ++fmt; /* this also skips first '%' */ - switch (*fmt) { - case '-': flags |= LEFT; goto repeat; - case '+': flags |= PLUS; goto repeat; - case ' ': flags |= SPACE; goto repeat; - case '#': flags |= SPECIAL; goto repeat; - case '0': flags |= ZEROPAD; goto repeat; - } - - /* get field width */ - field_width = -1; - if ('0' <= *fmt && *fmt <= '9') - field_width = skip_atoi(&fmt); - else if (*fmt == '*') { - ++fmt; - /* it's the next argument */ - field_width = va_arg(args, int); - if (field_width < 0) { - field_width = -field_width; - flags |= LEFT; - } - } - - /* get the precision */ - precision = -1; - if (*fmt == '.') { - ++fmt; - if ('0' <= *fmt && *fmt <= '9') - precision = skip_atoi(&fmt); - else if (*fmt == '*') { - ++fmt; - /* it's the next argument */ - precision = va_arg(args, int); - } - if (precision < 0) - precision = 0; - } - - /* get the conversion qualifier */ - qualifier = -1; - if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') { - qualifier = *fmt; - ++fmt; - } - - /* default base */ - base = 10; - - switch (*fmt) { - case 'c': - if (!(flags & LEFT)) - while (--field_width > 0) - *str++ = ' '; - *str++ = (unsigned char) va_arg(args, int); - while (--field_width > 0) - *str++ = ' '; - continue; - - case 's': - s = va_arg(args, char *); - if (!s) - s = ""; - - len = strnlen(s, precision); - - if (!(flags & LEFT)) - while (len < field_width--) - *str++ = ' '; - for (i = 0; i < len; ++i) - *str++ = *s++; - while (len < field_width--) - *str++ = ' '; - continue; - - case 'p': - if (field_width == -1) { - field_width = 2*sizeof(void *); - flags |= ZEROPAD; - } - str = number(str, - (unsigned long) va_arg(args, void *), 16, - field_width, precision, flags); - continue; - - - case 'n': - if (qualifier == 'l') { - long * ip = va_arg(args, long *); - *ip = (str - buf); - } else if (qualifier == 'Z') { - size_t * ip = va_arg(args, size_t *); - *ip = (str - buf); - } else { - int * ip = va_arg(args, int *); - *ip = (str - buf); - } - continue; - - case '%': - *str++ = '%'; - continue; - - /* integer number formats - set up the flags and "break" */ - case 'o': - base = 8; - break; - - case 'X': - flags |= LARGE; - case 'x': - base = 16; - break; - - case 'd': - case 'i': - flags |= SIGN; - case 'u': - break; - - default: - *str++ = '%'; - if (*fmt) - *str++ = *fmt; - else - --fmt; - continue; - } - if (qualifier == 'l') { - num = va_arg(args, unsigned long); - if (flags & SIGN) - num = (signed long) num; - } else if (qualifier == 'Z') { - num = va_arg(args, size_t); - } else if (qualifier == 'h') { - num = (unsigned short) va_arg(args, int); - if (flags & SIGN) - num = (signed short) num; - } else { - num = va_arg(args, unsigned int); - if (flags & SIGN) - num = (signed int) num; - } - str = number(str, num, base, field_width, precision, flags); - } - *str = '\0'; - return str-buf; -} - -int sprintf(char * buf, const char *fmt, ...) -{ - va_list args; - int i; - - va_start(args, fmt); - i=vsprintf(buf,fmt,args); - va_end(args); - return i; -} - -static char sprint_buf[1024]; - -int -printf(const char *fmt, ...) -{ - va_list args; - int n; - - va_start(args, fmt); - n = vsprintf(sprint_buf, fmt, args); - va_end(args); - write(stdout, sprint_buf, n); - return n; + ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory, + align, size, virt); + if (ret != 0 || result == -1) + return (void *) -1; + ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu, + align, size, virt); + /* 0x12 == coherent + read/write */ + ret = call_prom("call-method", 6, 1, "map", chosen_mmu, + 0x12, size, virt, virt); + return (void *) virt; } diff --git a/arch/powerpc/boot/prom.h b/arch/powerpc/boot/prom.h index 96ab5aec740..3e2ddd4a5a8 100644 --- a/arch/powerpc/boot/prom.h +++ b/arch/powerpc/boot/prom.h @@ -1,18 +1,34 @@ #ifndef _PPC_BOOT_PROM_H_ #define _PPC_BOOT_PROM_H_ +typedef void *phandle; +typedef void *ihandle; + extern int (*prom) (void *); -extern void *chosen_handle; +extern phandle chosen_handle; +extern ihandle stdout; -extern void *stdin; -extern void *stdout; -extern void *stderr; +int call_prom(const char *service, int nargs, int nret, ...); +int call_prom_ret(const char *service, int nargs, int nret, + unsigned int *rets, ...); extern int write(void *handle, void *ptr, int nb); -extern int read(void *handle, void *ptr, int nb); -extern void exit(void); -extern void pause(void); -extern void *finddevice(const char *); -extern void *claim(unsigned long virt, unsigned long size, unsigned long align); -extern int getprop(void *phandle, const char *name, void *buf, int buflen); +extern void *claim(unsigned long virt, unsigned long size, unsigned long aln); + +static inline void exit(void) +{ + call_prom("exit", 0, 0); +} + +static inline phandle finddevice(const char *name) +{ + return (phandle) call_prom("finddevice", 1, 1, name); +} + +static inline int getprop(void *phandle, const char *name, + void *buf, int buflen) +{ + return call_prom("getprop", 4, 1, phandle, name, buf, buflen); +} + #endif /* _PPC_BOOT_PROM_H_ */ diff --git a/arch/powerpc/boot/rs6000.h b/arch/powerpc/boot/rs6000.h new file mode 100644 index 00000000000..433f45084e4 --- /dev/null +++ b/arch/powerpc/boot/rs6000.h @@ -0,0 +1,243 @@ +/* IBM RS/6000 "XCOFF" file definitions for BFD. + Copyright (C) 1990, 1991 Free Software Foundation, Inc. + FIXME: Can someone provide a transliteration of this name into ASCII? + Using the following chars caused a compiler warning on HIUX (so I replaced + them with octal escapes), and isn't useful without an understanding of what + character set it is. + Written by Mimi Ph\373\364ng-Th\345o V\365 of IBM + and John Gilmore of Cygnus Support. */ + +/********************** FILE HEADER **********************/ + +struct external_filehdr { + char f_magic[2]; /* magic number */ + char f_nscns[2]; /* number of sections */ + char f_timdat[4]; /* time & date stamp */ + char f_symptr[4]; /* file pointer to symtab */ + char f_nsyms[4]; /* number of symtab entries */ + char f_opthdr[2]; /* sizeof(optional hdr) */ + char f_flags[2]; /* flags */ +}; + + /* IBM RS/6000 */ +#define U802WRMAGIC 0730 /* writeable text segments **chh** */ +#define U802ROMAGIC 0735 /* readonly sharable text segments */ +#define U802TOCMAGIC 0737 /* readonly text segments and TOC */ + +#define BADMAG(x) \ + ((x).f_magic != U802ROMAGIC && (x).f_magic != U802WRMAGIC && \ + (x).f_magic != U802TOCMAGIC) + +#define FILHDR struct external_filehdr +#define FILHSZ 20 + + +/********************** AOUT "OPTIONAL HEADER" **********************/ + + +typedef struct +{ + unsigned char magic[2]; /* type of file */ + unsigned char vstamp[2]; /* version stamp */ + unsigned char tsize[4]; /* text size in bytes, padded to FW bdry */ + unsigned char dsize[4]; /* initialized data " " */ + unsigned char bsize[4]; /* uninitialized data " " */ + unsigned char entry[4]; /* entry pt. */ + unsigned char text_start[4]; /* base of text used for this file */ + unsigned char data_start[4]; /* base of data used for this file */ + unsigned char o_toc[4]; /* address of TOC */ + unsigned char o_snentry[2]; /* section number of entry point */ + unsigned char o_sntext[2]; /* section number of .text section */ + unsigned char o_sndata[2]; /* section number of .data section */ + unsigned char o_sntoc[2]; /* section number of TOC */ + unsigned char o_snloader[2]; /* section number of .loader section */ + unsigned char o_snbss[2]; /* section number of .bss section */ + unsigned char o_algntext[2]; /* .text alignment */ + unsigned char o_algndata[2]; /* .data alignment */ + unsigned char o_modtype[2]; /* module type (??) */ + unsigned char o_cputype[2]; /* cpu type */ + unsigned char o_maxstack[4]; /* max stack size (??) */ + unsigned char o_maxdata[4]; /* max data size (??) */ + unsigned char o_resv2[12]; /* reserved */ +} +AOUTHDR; + +#define AOUTSZ 72 +#define SMALL_AOUTSZ (28) +#define AOUTHDRSZ 72 + +#define RS6K_AOUTHDR_OMAGIC 0x0107 /* old: text & data writeable */ +#define RS6K_AOUTHDR_NMAGIC 0x0108 /* new: text r/o, data r/w */ +#define RS6K_AOUTHDR_ZMAGIC 0x010B /* paged: text r/o, both page-aligned */ + + +/********************** SECTION HEADER **********************/ + + +struct external_scnhdr { + char s_name[8]; /* section name */ + char s_paddr[4]; /* physical address, aliased s_nlib */ + char s_vaddr[4]; /* virtual address */ + char s_size[4]; /* section size */ + char s_scnptr[4]; /* file ptr to raw data for section */ + char s_relptr[4]; /* file ptr to relocation */ + char s_lnnoptr[4]; /* file ptr to line numbers */ + char s_nreloc[2]; /* number of relocation entries */ + char s_nlnno[2]; /* number of line number entries*/ + char s_flags[4]; /* flags */ +}; + +/* + * names of "special" sections + */ +#define _TEXT ".text" +#define _DATA ".data" +#define _BSS ".bss" +#define _PAD ".pad" +#define _LOADER ".loader" + +#define SCNHDR struct external_scnhdr +#define SCNHSZ 40 + +/* XCOFF uses a special .loader section with type STYP_LOADER. */ +#define STYP_LOADER 0x1000 + +/* XCOFF uses a special .debug section with type STYP_DEBUG. */ +#define STYP_DEBUG 0x2000 + +/* XCOFF handles line number or relocation overflow by creating + another section header with STYP_OVRFLO set. */ +#define STYP_OVRFLO 0x8000 + +/********************** LINE NUMBERS **********************/ + +/* 1 line number entry for every "breakpointable" source line in a section. + * Line numbers are grouped on a per function basis; first entry in a function + * grouping will have l_lnno = 0 and in place of physical address will be the + * symbol table index of the function name. + */ +struct external_lineno { + union { + char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/ + char l_paddr[4]; /* (physical) address of line number */ + } l_addr; + char l_lnno[2]; /* line number */ +}; + + +#define LINENO struct external_lineno +#define LINESZ 6 + + +/********************** SYMBOLS **********************/ + +#define E_SYMNMLEN 8 /* # characters in a symbol name */ +#define E_FILNMLEN 14 /* # characters in a file name */ +#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */ + +struct external_syment +{ + union { + char e_name[E_SYMNMLEN]; + struct { + char e_zeroes[4]; + char e_offset[4]; + } e; + } e; + char e_value[4]; + char e_scnum[2]; + char e_type[2]; + char e_sclass[1]; + char e_numaux[1]; +}; + + + +#define N_BTMASK (017) +#define N_TMASK (060) +#define N_BTSHFT (4) +#define N_TSHIFT (2) + + +union external_auxent { + struct { + char x_tagndx[4]; /* str, un, or enum tag indx */ + union { + struct { + char x_lnno[2]; /* declaration line number */ + char x_size[2]; /* str/union/array size */ + } x_lnsz; + char x_fsize[4]; /* size of function */ + } x_misc; + union { + struct { /* if ISFCN, tag, or .bb */ + char x_lnnoptr[4]; /* ptr to fcn line # */ + char x_endndx[4]; /* entry ndx past block end */ + } x_fcn; + struct { /* if ISARY, up to 4 dimen. */ + char x_dimen[E_DIMNUM][2]; + } x_ary; + } x_fcnary; + char x_tvndx[2]; /* tv index */ + } x_sym; + + union { + char x_fname[E_FILNMLEN]; + struct { + char x_zeroes[4]; + char x_offset[4]; + } x_n; + } x_file; + + struct { + char x_scnlen[4]; /* section length */ + char x_nreloc[2]; /* # relocation entries */ + char x_nlinno[2]; /* # line numbers */ + } x_scn; + + struct { + char x_tvfill[4]; /* tv fill value */ + char x_tvlen[2]; /* length of .tv */ + char x_tvran[2][2]; /* tv range */ + } x_tv; /* info about .tv section (in auxent of symbol .tv)) */ + + struct { + unsigned char x_scnlen[4]; + unsigned char x_parmhash[4]; + unsigned char x_snhash[2]; + unsigned char x_smtyp[1]; + unsigned char x_smclas[1]; + unsigned char x_stab[4]; + unsigned char x_snstab[2]; + } x_csect; + +}; + +#define SYMENT struct external_syment +#define SYMESZ 18 +#define AUXENT union external_auxent +#define AUXESZ 18 +#define DBXMASK 0x80 /* for dbx storage mask */ +#define SYMNAME_IN_DEBUG(symptr) ((symptr)->n_sclass & DBXMASK) + + + +/********************** RELOCATION DIRECTIVES **********************/ + + +struct external_reloc { + char r_vaddr[4]; + char r_symndx[4]; + char r_size[1]; + char r_type[1]; +}; + + +#define RELOC struct external_reloc +#define RELSZ 10 + +#define DEFAULT_DATA_SECTION_ALIGNMENT 4 +#define DEFAULT_BSS_SECTION_ALIGNMENT 4 +#define DEFAULT_TEXT_SECTION_ALIGNMENT 4 +/* For new sections we havn't heard of before */ +#define DEFAULT_SECTION_ALIGNMENT 4 diff --git a/arch/powerpc/boot/stdio.c b/arch/powerpc/boot/stdio.c new file mode 100644 index 00000000000..b5aa522f8b7 --- /dev/null +++ b/arch/powerpc/boot/stdio.c @@ -0,0 +1,325 @@ +/* + * Copyright (C) Paul Mackerras 1997. + * + * 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 +#include +#include "string.h" +#include "stdio.h" +#include "prom.h" + +size_t strnlen(const char * s, size_t count) +{ + const char *sc; + + for (sc = s; count-- && *sc != '\0'; ++sc) + /* nothing */; + return sc - s; +} + +extern unsigned int __div64_32(unsigned long long *dividend, + unsigned int divisor); + +/* The unnecessary pointer compare is there + * to check for type safety (n must be 64bit) + */ +# define do_div(n,base) ({ \ + unsigned int __base = (base); \ + unsigned int __rem; \ + (void)(((typeof((n)) *)0) == ((unsigned long long *)0)); \ + if (((n) >> 32) == 0) { \ + __rem = (unsigned int)(n) % __base; \ + (n) = (unsigned int)(n) / __base; \ + } else \ + __rem = __div64_32(&(n), __base); \ + __rem; \ + }) + +static int skip_atoi(const char **s) +{ + int i, c; + + for (i = 0; '0' <= (c = **s) && c <= '9'; ++*s) + i = i*10 + c - '0'; + return i; +} + +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define PLUS 4 /* show plus */ +#define SPACE 8 /* space if plus */ +#define LEFT 16 /* left justified */ +#define SPECIAL 32 /* 0x */ +#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ + +static char * number(char * str, unsigned long long num, int base, int size, int precision, int type) +{ + char c,sign,tmp[66]; + const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; + int i; + + if (type & LARGE) + digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + if (type & LEFT) + type &= ~ZEROPAD; + if (base < 2 || base > 36) + return 0; + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) { + if ((signed long long)num < 0) { + sign = '-'; + num = - (signed long long)num; + size--; + } else if (type & PLUS) { + sign = '+'; + size--; + } else if (type & SPACE) { + sign = ' '; + size--; + } + } + if (type & SPECIAL) { + if (base == 16) + size -= 2; + else if (base == 8) + size--; + } + i = 0; + if (num == 0) + tmp[i++]='0'; + else while (num != 0) { + tmp[i++] = digits[do_div(num, base)]; + } + if (i > precision) + precision = i; + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + *str++ = ' '; + if (sign) + *str++ = sign; + if (type & SPECIAL) { + if (base==8) + *str++ = '0'; + else if (base==16) { + *str++ = '0'; + *str++ = digits[33]; + } + } + if (!(type & LEFT)) + while (size-- > 0) + *str++ = c; + while (i < precision--) + *str++ = '0'; + while (i-- > 0) + *str++ = tmp[i]; + while (size-- > 0) + *str++ = ' '; + return str; +} + +int vsprintf(char *buf, const char *fmt, va_list args) +{ + int len; + unsigned long long num; + int i, base; + char * str; + const char *s; + + int flags; /* flags to number() */ + + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + number of chars for from string */ + int qualifier; /* 'h', 'l', or 'L' for integer fields */ + /* 'z' support added 23/7/1999 S.H. */ + /* 'z' changed to 'Z' --davidm 1/25/99 */ + + + for (str=buf ; *fmt ; ++fmt) { + if (*fmt != '%') { + *str++ = *fmt; + continue; + } + + /* process flags */ + flags = 0; + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case '-': flags |= LEFT; goto repeat; + case '+': flags |= PLUS; goto repeat; + case ' ': flags |= SPACE; goto repeat; + case '#': flags |= SPECIAL; goto repeat; + case '0': flags |= ZEROPAD; goto repeat; + } + + /* get field width */ + field_width = -1; + if ('0' <= *fmt && *fmt <= '9') + field_width = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + field_width = va_arg(args, int); + if (field_width < 0) { + field_width = -field_width; + flags |= LEFT; + } + } + + /* get the precision */ + precision = -1; + if (*fmt == '.') { + ++fmt; + if ('0' <= *fmt && *fmt <= '9') + precision = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + precision = va_arg(args, int); + } + if (precision < 0) + precision = 0; + } + + /* get the conversion qualifier */ + qualifier = -1; + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') { + qualifier = *fmt; + ++fmt; + } + + /* default base */ + base = 10; + + switch (*fmt) { + case 'c': + if (!(flags & LEFT)) + while (--field_width > 0) + *str++ = ' '; + *str++ = (unsigned char) va_arg(args, int); + while (--field_width > 0) + *str++ = ' '; + continue; + + case 's': + s = va_arg(args, char *); + if (!s) + s = ""; + + len = strnlen(s, precision); + + if (!(flags & LEFT)) + while (len < field_width--) + *str++ = ' '; + for (i = 0; i < len; ++i) + *str++ = *s++; + while (len < field_width--) + *str++ = ' '; + continue; + + case 'p': + if (field_width == -1) { + field_width = 2*sizeof(void *); + flags |= ZEROPAD; + } + str = number(str, + (unsigned long) va_arg(args, void *), 16, + field_width, precision, flags); + continue; + + + case 'n': + if (qualifier == 'l') { + long * ip = va_arg(args, long *); + *ip = (str - buf); + } else if (qualifier == 'Z') { + size_t * ip = va_arg(args, size_t *); + *ip = (str - buf); + } else { + int * ip = va_arg(args, int *); + *ip = (str - buf); + } + continue; + + case '%': + *str++ = '%'; + continue; + + /* integer number formats - set up the flags and "break" */ + case 'o': + base = 8; + break; + + case 'X': + flags |= LARGE; + case 'x': + base = 16; + break; + + case 'd': + case 'i': + flags |= SIGN; + case 'u': + break; + + default: + *str++ = '%'; + if (*fmt) + *str++ = *fmt; + else + --fmt; + continue; + } + if (qualifier == 'l') { + num = va_arg(args, unsigned long); + if (flags & SIGN) + num = (signed long) num; + } else if (qualifier == 'Z') { + num = va_arg(args, size_t); + } else if (qualifier == 'h') { + num = (unsigned short) va_arg(args, int); + if (flags & SIGN) + num = (signed short) num; + } else { + num = va_arg(args, unsigned int); + if (flags & SIGN) + num = (signed int) num; + } + str = number(str, num, base, field_width, precision, flags); + } + *str = '\0'; + return str-buf; +} + +int sprintf(char * buf, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i=vsprintf(buf,fmt,args); + va_end(args); + return i; +} + +static char sprint_buf[1024]; + +int +printf(const char *fmt, ...) +{ + va_list args; + int n; + + va_start(args, fmt); + n = vsprintf(sprint_buf, fmt, args); + va_end(args); + write(stdout, sprint_buf, n); + return n; +} diff --git a/arch/powerpc/boot/stdio.h b/arch/powerpc/boot/stdio.h index 24bd3a8dee9..eb9e16c87ae 100644 --- a/arch/powerpc/boot/stdio.h +++ b/arch/powerpc/boot/stdio.h @@ -7,10 +7,4 @@ extern int sprintf(char *buf, const char *fmt, ...); extern int vsprintf(char *buf, const char *fmt, va_list args); -extern int putc(int c, void *f); -extern int putchar(int c); -extern int getchar(void); - -extern int fputs(char *str, void *f); - #endif /* _PPC_BOOT_STDIO_H_ */ diff --git a/arch/powerpc/boot/zImage.coff.lds b/arch/powerpc/boot/zImage.coff.lds new file mode 100644 index 00000000000..6016251a1a2 --- /dev/null +++ b/arch/powerpc/boot/zImage.coff.lds @@ -0,0 +1,46 @@ +OUTPUT_ARCH(powerpc:common) +ENTRY(_start) +SECTIONS +{ + . = (5*1024*1024); + _start = .; + .text : + { + *(.text) + *(.fixup) + } + _etext = .; + . = ALIGN(4096); + .data : + { + *(.rodata*) + *(.data*) + *(.sdata*) + __got2_start = .; + *(.got2) + __got2_end = .; + + _vmlinux_start = .; + *(.kernel:vmlinux.strip) + _vmlinux_end = .; + + _initrd_start = .; + *(.kernel:initrd) + _initrd_end = .; + } + + . = ALIGN(4096); + _edata = .; + __bss_start = .; + .bss : + { + *(.sbss) + *(.bss) + } + _end = . ; + + /DISCARD/ : + { + *(.comment) + } +} -- GitLab From b4e7de0f3575f4862f04921c5bd0cb5680cc8d71 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 14 Jan 2006 15:06:51 +1100 Subject: [PATCH 169/465] powerpc: Avoid unaligned loads and stores in boot memcpy code The 601 processor will generate an alignment exception for accesses which cross a page boundary. In the boot wrapper code, OF is still handling all exceptions, and it doesn't have an alignment exception handler that emulates the instruction and continues. This changes the memcpy and memmove routines in the boot wrapper to avoid doing unaligned accesses. If the source and destination are misaligned with respect to each other, we just copy one byte at a time. Signed-off-by: Paul Mackerras --- arch/powerpc/boot/string.S | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/boot/string.S b/arch/powerpc/boot/string.S index b1eeaed7db1..ac3d43b6a32 100644 --- a/arch/powerpc/boot/string.S +++ b/arch/powerpc/boot/string.S @@ -107,10 +107,12 @@ memcpy: rlwinm. r7,r5,32-3,3,31 /* r7 = r5 >> 3 */ addi r6,r3,-4 addi r4,r4,-4 - beq 2f /* if less than 8 bytes to do */ + beq 3f /* if less than 8 bytes to do */ andi. r0,r6,3 /* get dest word aligned */ mtctr r7 bne 5f + andi. r0,r4,3 /* check src word aligned too */ + bne 3f 1: lwz r7,4(r4) lwzu r8,8(r4) stw r7,4(r6) @@ -132,6 +134,11 @@ memcpy: bdnz 4b blr 5: subfic r0,r0,4 + cmpw cr1,r0,r5 + add r7,r0,r4 + andi. r7,r7,3 /* will source be word-aligned too? */ + ble cr1,3b + bne 3b /* do byte-by-byte if not */ mtctr r0 6: lbz r7,4(r4) addi r4,r4,1 @@ -149,10 +156,12 @@ backwards_memcpy: rlwinm. r7,r5,32-3,3,31 /* r7 = r5 >> 3 */ add r6,r3,r5 add r4,r4,r5 - beq 2f + beq 3f andi. r0,r6,3 mtctr r7 bne 5f + andi. r0,r4,3 + bne 3f 1: lwz r7,-4(r4) lwzu r8,-8(r4) stw r7,-4(r6) @@ -171,7 +180,12 @@ backwards_memcpy: stbu r0,-1(r6) bdnz 4b blr -5: mtctr r0 +5: cmpw cr1,r0,r5 + subf r7,r0,r4 + andi. r7,r7,3 + ble cr1,3b + bne 3b + mtctr r0 6: lbzu r7,-1(r4) stbu r7,-1(r6) bdnz 6b -- GitLab From d5f079000b20887bfbc84d772a27709c5665e652 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 14 Jan 2006 15:08:50 +1100 Subject: [PATCH 170/465] [PATCH] powerpc: Recognize /chaos bridge on old pmacs as PCI The first generation of PCI powermacs had a host bridge called /chaos which was for all intents and purposes a PCI host bridge, but has a device_type of "vci" in the device tree (presumably it's not really PCI at the hardware level or something). The OF parsing stuff in arch/powerpc/kernel/prom_parse.c currently doesn't recognize it as a PCI bridge, which means that controlfb.c can't get its device addresses. This makes prom_parse.c recognize a device_type of "vci" as indicating a PCI host bridge. With this, controlfb works again. Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom_parse.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c index 309ae1d5fa7..a8099c80615 100644 --- a/arch/powerpc/kernel/prom_parse.c +++ b/arch/powerpc/kernel/prom_parse.c @@ -113,7 +113,8 @@ static unsigned int of_bus_default_get_flags(u32 *addr) static int of_bus_pci_match(struct device_node *np) { - return !strcmp(np->type, "pci"); + /* "vci" is for the /chaos bridge on 1st-gen PCI powermacs */ + return !strcmp(np->type, "pci") || !strcmp(np->type, "vci"); } static void of_bus_pci_count_cells(struct device_node *np, -- GitLab From 3dd01a831133e3260b9c77a09c234b012e9507da Mon Sep 17 00:00:00 2001 From: Vojtech Pavlik Date: Sat, 14 Jan 2006 00:24:06 -0500 Subject: [PATCH 171/465] Input: i8042 - add Sony Vaio FSC-115b to MUX blacklist Signed-off-by: Vojtech Pavlik Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042-x86ia64io.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 2d2f9fb3ade..a4c6f352272 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -173,6 +173,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"), }, }, + { + .ident = "Sony Vaio FS-115b", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FS115B"), + }, + }, { } }; -- GitLab From 940824b0ac6661ff4f3b36e7bce17f681d0cbc23 Mon Sep 17 00:00:00 2001 From: Vojtech Pavlik Date: Sat, 14 Jan 2006 00:25:39 -0500 Subject: [PATCH 172/465] Input: HID - add support for Cherry Cymotion keyboard The Cherry Cymotion is a special Linux keyboard made by Cherry, with only one little problem: it doesn't work with Linux. This patch (originally by hexten.net, cleaned up by me) makes it work including all the special keys. Signed-off-by: Vojtech Pavlik Signed-off-by: Dmitry Torokhov --- drivers/usb/input/hid-core.c | 22 ++++++++++++++++++++++ drivers/usb/input/hid-input.c | 8 ++++++++ drivers/usb/input/hid.h | 1 + 3 files changed, 31 insertions(+) diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 5f52979af1c..1a2d20303ed 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -1450,6 +1450,9 @@ void hid_init_reports(struct hid_device *hid) #define USB_VENDOR_ID_APPLE 0x05ac #define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304 +#define USB_VENDOR_ID_CHERRY 0x046a +#define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 + /* * Alphabetically sorted blacklist by quirk type. */ @@ -1580,6 +1583,8 @@ static const struct hid_blacklist { { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD }, { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, + { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION }, + { 0, 0 } }; @@ -1626,6 +1631,20 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma); } +/* + * Cherry Cymotion keyboard have an invalid HID report descriptor, + * that needs fixing before we can parse it. + */ + +static void hid_fixup_cymotion_descriptor(char *rdesc, int rsize) +{ + if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) { + info("Fixing up Cherry Cymotion report descriptor"); + rdesc[11] = rdesc[16] = 0xff; + rdesc[12] = rdesc[17] = 0x03; + } +} + static struct hid_device *usb_hid_configure(struct usb_interface *intf) { struct usb_host_interface *interface = intf->cur_altsetting; @@ -1673,6 +1692,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) return NULL; } + if ((quirks & HID_QUIRK_CYMOTION)) + hid_fixup_cymotion_descriptor(rdesc, rsize); + #ifdef DEBUG_DATA printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n); for (n = 0; n < rsize; n++) diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c index 192a03b2897..9e5a80bbd16 100644 --- a/drivers/usb/input/hid-input.c +++ b/drivers/usb/input/hid-input.c @@ -289,11 +289,19 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case 0x226: map_key_clear(KEY_STOP); break; case 0x227: map_key_clear(KEY_REFRESH); break; case 0x22a: map_key_clear(KEY_BOOKMARKS); break; + case 0x233: map_key_clear(KEY_SCROLLUP); break; + case 0x234: map_key_clear(KEY_SCROLLDOWN); break; case 0x238: map_rel(REL_HWHEEL); break; case 0x279: map_key_clear(KEY_REDO); break; case 0x289: map_key_clear(KEY_REPLY); break; case 0x28b: map_key_clear(KEY_FORWARDMAIL); break; case 0x28c: map_key_clear(KEY_SEND); break; + + /* Reported on a Cherry Cymotion keyboard */ + case 0x301: map_key_clear(KEY_PROG1); break; + case 0x302: map_key_clear(KEY_PROG2); break; + case 0x303: map_key_clear(KEY_PROG3); break; + default: goto ignore; } break; diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h index ee48a227610..335316c7233 100644 --- a/drivers/usb/input/hid.h +++ b/drivers/usb/input/hid.h @@ -246,6 +246,7 @@ struct hid_item { #define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x100 #define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x200 #define HID_QUIRK_2WHEEL_POWERMOUSE 0x400 +#define HID_QUIRK_CYMOTION 0x800 /* * This is the global environment of the parser. This information is -- GitLab From b65d0d1bacfdbb4a134a7ebd16f280d5d42241cb Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 14 Jan 2006 00:26:15 -0500 Subject: [PATCH 173/465] Input: HID - fix an oops in PID initialization code Signed-off-by: Dmitry Torokhov --- drivers/usb/input/pid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/input/pid.c b/drivers/usb/input/pid.c index 19e015d171a..d9d9f656b8c 100644 --- a/drivers/usb/input/pid.c +++ b/drivers/usb/input/pid.c @@ -259,7 +259,7 @@ static int hid_pid_upload_effect(struct input_dev *dev, int hid_pid_init(struct hid_device *hid) { struct hid_ff_pid *private; - struct hid_input *hidinput = list_entry(&hid->inputs, struct hid_input, list); + struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); struct input_dev *input_dev = hidinput->input; private = hid->ff_private = kzalloc(sizeof(struct hid_ff_pid), GFP_KERNEL); -- GitLab From f0d5c6f419d3a10443f66d6835855837eae4ac4b Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 14 Jan 2006 00:27:37 -0500 Subject: [PATCH 174/465] Input: psmouse - attempt to re-synchronize mouse every 5 seconds This should help driver to deal vith KVMs that reset mice when switching between boxes. Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/alps.c | 38 ++++ drivers/input/mouse/logips2pp.c | 2 +- drivers/input/mouse/psmouse-base.c | 316 +++++++++++++++++++++++------ drivers/input/mouse/psmouse.h | 9 +- drivers/input/mouse/synaptics.c | 2 + 5 files changed, 301 insertions(+), 66 deletions(-) diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 24474335dfd..2141501e9f2 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -348,6 +348,40 @@ static int alps_tap_mode(struct psmouse *psmouse, int enable) return 0; } +/* + * alps_poll() - poll the touchpad for current motion packet. + * Used in resync. + */ +static int alps_poll(struct psmouse *psmouse) +{ + struct alps_data *priv = psmouse->private; + unsigned char buf[6]; + int poll_failed; + + if (priv->i->flags & ALPS_PASS) + alps_passthrough_mode(psmouse, 1); + + poll_failed = ps2_command(&psmouse->ps2dev, buf, + PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0; + + if (priv->i->flags & ALPS_PASS) + alps_passthrough_mode(psmouse, 0); + + if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0) + return -1; + + if ((psmouse->badbyte & 0xc8) == 0x08) { +/* + * Poll the track stick ... + */ + if (ps2_command(&psmouse->ps2dev, buf, PSMOUSE_CMD_POLL | (3 << 8))) + return -1; + } + + memcpy(psmouse->packet, buf, sizeof(buf)); + return 0; +} + static int alps_reconnect(struct psmouse *psmouse) { struct alps_data *priv = psmouse->private; @@ -451,10 +485,14 @@ int alps_init(struct psmouse *psmouse) input_register_device(priv->dev2); psmouse->protocol_handler = alps_process_byte; + psmouse->poll = alps_poll; psmouse->disconnect = alps_disconnect; psmouse->reconnect = alps_reconnect; psmouse->pktsize = 6; + /* We are having trouble resyncing ALPS touchpads so disable it for now */ + psmouse->resync_time = 0; + return 0; init_fail: diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c index 025a71de540..c88520d3d13 100644 --- a/drivers/input/mouse/logips2pp.c +++ b/drivers/input/mouse/logips2pp.c @@ -117,7 +117,7 @@ static int ps2pp_cmd(struct psmouse *psmouse, unsigned char *param, unsigned cha if (psmouse_sliced_command(psmouse, command)) return -1; - if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_POLL)) + if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_POLL | 0x0300)) return -1; return 0; diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 4d5ecc04c5b..7665fd9ce55 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -54,10 +54,14 @@ static unsigned int psmouse_smartscroll = 1; module_param_named(smartscroll, psmouse_smartscroll, bool, 0644); MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."); -static unsigned int psmouse_resetafter; +static unsigned int psmouse_resetafter = 5; module_param_named(resetafter, psmouse_resetafter, uint, 0644); MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never)."); +static unsigned int psmouse_resync_time = 5; +module_param_named(resync_time, psmouse_resync_time, uint, 0644); +MODULE_PARM_DESC(resync_time, "How long can mouse stay idle before forcing resync (in seconds, 0 = never)."); + PSMOUSE_DEFINE_ATTR(protocol, S_IWUSR | S_IRUGO, NULL, psmouse_attr_show_protocol, psmouse_attr_set_protocol); @@ -70,12 +74,16 @@ PSMOUSE_DEFINE_ATTR(resolution, S_IWUSR | S_IRUGO, PSMOUSE_DEFINE_ATTR(resetafter, S_IWUSR | S_IRUGO, (void *) offsetof(struct psmouse, resetafter), psmouse_show_int_attr, psmouse_set_int_attr); +PSMOUSE_DEFINE_ATTR(resync_time, S_IWUSR | S_IRUGO, + (void *) offsetof(struct psmouse, resync_time), + psmouse_show_int_attr, psmouse_set_int_attr); static struct attribute *psmouse_attributes[] = { &psmouse_attr_protocol.dattr.attr, &psmouse_attr_rate.dattr.attr, &psmouse_attr_resolution.dattr.attr, &psmouse_attr_resetafter.dattr.attr, + &psmouse_attr_resync_time.dattr.attr, NULL }; @@ -98,6 +106,8 @@ __obsolete_setup("psmouse_rate="); */ static DECLARE_MUTEX(psmouse_sem); +static struct workqueue_struct *kpsmoused_wq; + struct psmouse_protocol { enum psmouse_type type; char *name; @@ -178,15 +188,79 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse, struct pt_reg } /* - * psmouse_interrupt() handles incoming characters, either gathering them into - * packets or passing them to the command routine as command output. + * __psmouse_set_state() sets new psmouse state and resets all flags. + */ + +static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) +{ + psmouse->state = new_state; + psmouse->pktcnt = psmouse->out_of_sync = 0; + psmouse->ps2dev.flags = 0; + psmouse->last = jiffies; +} + + +/* + * psmouse_set_state() sets new psmouse state and resets all flags and + * counters while holding serio lock so fighting with interrupt handler + * is not a concern. + */ + +static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) +{ + serio_pause_rx(psmouse->ps2dev.serio); + __psmouse_set_state(psmouse, new_state); + serio_continue_rx(psmouse->ps2dev.serio); +} + +/* + * psmouse_handle_byte() processes one byte of the input data stream + * by calling corresponding protocol handler. + */ + +static int psmouse_handle_byte(struct psmouse *psmouse, struct pt_regs *regs) +{ + psmouse_ret_t rc = psmouse->protocol_handler(psmouse, regs); + + switch (rc) { + case PSMOUSE_BAD_DATA: + if (psmouse->state == PSMOUSE_ACTIVATED) { + printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n", + psmouse->name, psmouse->phys, psmouse->pktcnt); + if (++psmouse->out_of_sync == psmouse->resetafter) { + __psmouse_set_state(psmouse, PSMOUSE_IGNORE); + printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); + serio_reconnect(psmouse->ps2dev.serio); + return -1; + } + } + psmouse->pktcnt = 0; + break; + + case PSMOUSE_FULL_PACKET: + psmouse->pktcnt = 0; + if (psmouse->out_of_sync) { + psmouse->out_of_sync = 0; + printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n", + psmouse->name, psmouse->phys); + } + break; + + case PSMOUSE_GOOD_DATA: + break; + } + return 0; +} + +/* + * psmouse_interrupt() handles incoming characters, either passing them + * for normal processing or gathering them as command response. */ static irqreturn_t psmouse_interrupt(struct serio *serio, unsigned char data, unsigned int flags, struct pt_regs *regs) { struct psmouse *psmouse = serio_get_drvdata(serio); - psmouse_ret_t rc; if (psmouse->state == PSMOUSE_IGNORE) goto out; @@ -208,67 +282,58 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, if (ps2_handle_response(&psmouse->ps2dev, data)) goto out; - if (psmouse->state == PSMOUSE_INITIALIZING) + if (psmouse->state <= PSMOUSE_RESYNCING) goto out; if (psmouse->state == PSMOUSE_ACTIVATED && psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) { - printk(KERN_WARNING "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n", + printk(KERN_INFO "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n", psmouse->name, psmouse->phys, psmouse->pktcnt); - psmouse->pktcnt = 0; + psmouse->badbyte = psmouse->packet[0]; + __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); + queue_work(kpsmoused_wq, &psmouse->resync_work); + goto out; } - psmouse->last = jiffies; psmouse->packet[psmouse->pktcnt++] = data; - - if (psmouse->packet[0] == PSMOUSE_RET_BAT) { +/* + * Check if this is a new device announcement (0xAA 0x00) + */ + if (unlikely(psmouse->packet[0] == PSMOUSE_RET_BAT && psmouse->pktcnt <= 2)) { if (psmouse->pktcnt == 1) goto out; - if (psmouse->pktcnt == 2) { - if (psmouse->packet[1] == PSMOUSE_RET_ID) { - psmouse->state = PSMOUSE_IGNORE; - serio_reconnect(serio); - goto out; - } - if (psmouse->type == PSMOUSE_SYNAPTICS) { - /* neither 0xAA nor 0x00 are valid first bytes - * for a packet in absolute mode - */ - psmouse->pktcnt = 0; - goto out; - } + if (psmouse->packet[1] == PSMOUSE_RET_ID) { + __psmouse_set_state(psmouse, PSMOUSE_IGNORE); + serio_reconnect(serio); + goto out; } - } - - rc = psmouse->protocol_handler(psmouse, regs); +/* + * Not a new device, try processing first byte normally + */ + psmouse->pktcnt = 1; + if (psmouse_handle_byte(psmouse, regs)) + goto out; - switch (rc) { - case PSMOUSE_BAD_DATA: - printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n", - psmouse->name, psmouse->phys, psmouse->pktcnt); - psmouse->pktcnt = 0; + psmouse->packet[psmouse->pktcnt++] = data; + } - if (++psmouse->out_of_sync == psmouse->resetafter) { - psmouse->state = PSMOUSE_IGNORE; - printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); - serio_reconnect(psmouse->ps2dev.serio); - } - break; +/* + * See if we need to force resync because mouse was idle for too long + */ + if (psmouse->state == PSMOUSE_ACTIVATED && + psmouse->pktcnt == 1 && psmouse->resync_time && + time_after(jiffies, psmouse->last + psmouse->resync_time * HZ)) { + psmouse->badbyte = psmouse->packet[0]; + __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); + queue_work(kpsmoused_wq, &psmouse->resync_work); + goto out; + } - case PSMOUSE_FULL_PACKET: - psmouse->pktcnt = 0; - if (psmouse->out_of_sync) { - psmouse->out_of_sync = 0; - printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n", - psmouse->name, psmouse->phys); - } - break; + psmouse->last = jiffies; + psmouse_handle_byte(psmouse, regs); - case PSMOUSE_GOOD_DATA: - break; - } -out: + out: return IRQ_HANDLED; } @@ -751,21 +816,6 @@ static void psmouse_initialize(struct psmouse *psmouse) } } -/* - * psmouse_set_state() sets new psmouse state and resets all flags and - * counters while holding serio lock so fighting with interrupt handler - * is not a concern. - */ - -static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) -{ - serio_pause_rx(psmouse->ps2dev.serio); - psmouse->state = new_state; - psmouse->pktcnt = psmouse->out_of_sync = 0; - psmouse->ps2dev.flags = 0; - serio_continue_rx(psmouse->ps2dev.serio); -} - /* * psmouse_activate() enables the mouse so that we get motion reports from it. */ @@ -794,6 +844,111 @@ static void psmouse_deactivate(struct psmouse *psmouse) psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); } +/* + * psmouse_poll() - default poll hanlder. Everyone except for ALPS uses it. + */ + +static int psmouse_poll(struct psmouse *psmouse) +{ + return ps2_command(&psmouse->ps2dev, psmouse->packet, + PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)); +} + + +/* + * psmouse_resync() attempts to re-validate current protocol. + */ + +static void psmouse_resync(void *p) +{ + struct psmouse *psmouse = p, *parent = NULL; + struct serio *serio = psmouse->ps2dev.serio; + psmouse_ret_t rc = PSMOUSE_GOOD_DATA; + int failed = 0, enabled = 0; + int i; + + down(&psmouse_sem); + + if (psmouse->state != PSMOUSE_RESYNCING) + goto out; + + if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { + parent = serio_get_drvdata(serio->parent); + psmouse_deactivate(parent); + } + +/* + * Some mice don't ACK commands sent while they are in the middle of + * transmitting motion packet. To avoid delay we use ps2_sendbyte() + * instead of ps2_command() which would wait for 200ms for an ACK + * that may never come. + * As an additional quirk ALPS touchpads may not only forget to ACK + * disable command but will stop reporting taps, so if we see that + * mouse at least once ACKs disable we will do full reconnect if ACK + * is missing. + */ + psmouse->num_resyncs++; + + if (ps2_sendbyte(&psmouse->ps2dev, PSMOUSE_CMD_DISABLE, 20)) { + if (psmouse->num_resyncs < 3 || psmouse->acks_disable_command) + failed = 1; + } else + psmouse->acks_disable_command = 1; + +/* + * Poll the mouse. If it was reset the packet will be shorter than + * psmouse->pktsize and ps2_command will fail. We do not expect and + * do not handle scenario when mouse "upgrades" its protocol while + * disconnected since it would require additional delay. If we ever + * see a mouse that does it we'll adjust the code. + */ + if (!failed) { + if (psmouse->poll(psmouse)) + failed = 1; + else { + psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); + for (i = 0; i < psmouse->pktsize; i++) { + psmouse->pktcnt++; + rc = psmouse->protocol_handler(psmouse, NULL); + if (rc != PSMOUSE_GOOD_DATA) + break; + } + if (rc != PSMOUSE_FULL_PACKET) + failed = 1; + psmouse_set_state(psmouse, PSMOUSE_RESYNCING); + } + } +/* + * Now try to enable mouse. We try to do that even if poll failed and also + * repeat our attempts 5 times, otherwise we may be left out with disabled + * mouse. + */ + for (i = 0; i < 5; i++) { + if (!ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { + enabled = 1; + break; + } + msleep(200); + } + + if (!enabled) { + printk(KERN_WARNING "psmouse.c: failed to re-enable mouse on %s\n", + psmouse->ps2dev.serio->phys); + failed = 1; + } + + if (failed) { + psmouse_set_state(psmouse, PSMOUSE_IGNORE); + printk(KERN_INFO "psmouse.c: resync failed, issuing reconnect request\n"); + serio_reconnect(serio); + } else + psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); + + if (parent) + psmouse_activate(parent); + out: + up(&psmouse_sem); +} /* * psmouse_cleanup() resets the mouse into power-on state. @@ -822,6 +977,11 @@ static void psmouse_disconnect(struct serio *serio) psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); + /* make sure we don't have a resync in progress */ + up(&psmouse_sem); + flush_workqueue(kpsmoused_wq); + down(&psmouse_sem); + if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { parent = serio_get_drvdata(serio->parent); psmouse_deactivate(parent); @@ -859,6 +1019,7 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_proto psmouse->set_rate = psmouse_set_rate; psmouse->set_resolution = psmouse_set_resolution; + psmouse->poll = psmouse_poll; psmouse->protocol_handler = psmouse_process_byte; psmouse->pktsize = 3; @@ -874,6 +1035,23 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_proto else psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1); + /* + * If mouse's packet size is 3 there is no point in polling the + * device in hopes to detect protocol reset - we won't get less + * than 3 bytes response anyhow. + */ + if (psmouse->pktsize == 3) + psmouse->resync_time = 0; + + /* + * Some smart KVMs fake response to POLL command returning just + * 3 bytes and messing up our resync logic, so if initial poll + * fails we won't try polling the device anymore. Hopefully + * such KVM will maintain initially selected protocol. + */ + if (psmouse->resync_time && psmouse->poll(psmouse)) + psmouse->resync_time = 0; + sprintf(psmouse->devname, "%s %s %s", psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name); @@ -914,6 +1092,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) goto out; ps2_init(&psmouse->ps2dev, serio); + INIT_WORK(&psmouse->resync_work, psmouse_resync, psmouse); psmouse->dev = input_dev; sprintf(psmouse->phys, "%s/input0", serio->phys); @@ -934,6 +1113,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) psmouse->rate = psmouse_rate; psmouse->resolution = psmouse_resolution; psmouse->resetafter = psmouse_resetafter; + psmouse->resync_time = parent ? 0 : psmouse_resync_time; psmouse->smartscroll = psmouse_smartscroll; psmouse_switch_protocol(psmouse, NULL); @@ -1278,13 +1458,21 @@ static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp) static int __init psmouse_init(void) { + kpsmoused_wq = create_singlethread_workqueue("kpsmoused"); + if (!kpsmoused_wq) { + printk(KERN_ERR "psmouse: failed to create kpsmoused workqueue\n"); + return -ENOMEM; + } + serio_register_driver(&psmouse_drv); + return 0; } static void __exit psmouse_exit(void) { serio_unregister_driver(&psmouse_drv); + destroy_workqueue(kpsmoused_wq); } module_init(psmouse_init); diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index 7c4192bd127..4d9107fba6a 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h @@ -7,7 +7,7 @@ #define PSMOUSE_CMD_GETINFO 0x03e9 #define PSMOUSE_CMD_SETSTREAM 0x00ea #define PSMOUSE_CMD_SETPOLL 0x00f0 -#define PSMOUSE_CMD_POLL 0x03eb +#define PSMOUSE_CMD_POLL 0x00eb /* caller sets number of bytes to receive */ #define PSMOUSE_CMD_GETID 0x02f2 #define PSMOUSE_CMD_SETRATE 0x10f3 #define PSMOUSE_CMD_ENABLE 0x00f4 @@ -23,6 +23,7 @@ enum psmouse_state { PSMOUSE_IGNORE, PSMOUSE_INITIALIZING, + PSMOUSE_RESYNCING, PSMOUSE_CMD_MODE, PSMOUSE_ACTIVATED, }; @@ -38,15 +39,19 @@ struct psmouse { void *private; struct input_dev *dev; struct ps2dev ps2dev; + struct work_struct resync_work; char *vendor; char *name; unsigned char packet[8]; + unsigned char badbyte; unsigned char pktcnt; unsigned char pktsize; unsigned char type; + unsigned char acks_disable_command; unsigned int model; unsigned long last; unsigned long out_of_sync; + unsigned long num_resyncs; enum psmouse_state state; char devname[64]; char phys[32]; @@ -54,6 +59,7 @@ struct psmouse { unsigned int rate; unsigned int resolution; unsigned int resetafter; + unsigned int resync_time; unsigned int smartscroll; /* Logitech only */ psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs); @@ -62,6 +68,7 @@ struct psmouse { int (*reconnect)(struct psmouse *psmouse); void (*disconnect)(struct psmouse *psmouse); + int (*poll)(struct psmouse *psmouse); void (*pt_activate)(struct psmouse *psmouse); void (*pt_deactivate)(struct psmouse *psmouse); diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 97cdfd6acac..2051bec2c39 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -652,6 +652,8 @@ int synaptics_init(struct psmouse *psmouse) psmouse->disconnect = synaptics_disconnect; psmouse->reconnect = synaptics_reconnect; psmouse->pktsize = 6; + /* Synaptics can usually stay in sync without extra help */ + psmouse->resync_time = 0; if (SYN_CAP_PASS_THROUGH(priv->capabilities)) synaptics_pt_create(psmouse); -- GitLab From 5fce9d7bc5f485358263cf3d895e90c974449e1f Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 14 Jan 2006 00:27:51 -0500 Subject: [PATCH 175/465] Input: HID - add more simulation usages Signed-off-by: Dmitry Torokhov --- drivers/usb/input/hid-input.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c index 9e5a80bbd16..36a08c04c46 100644 --- a/drivers/usb/input/hid-input.c +++ b/drivers/usb/input/hid-input.c @@ -135,8 +135,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case HID_UP_SIMULATION: switch (usage->hid & 0xffff) { - case 0xba: map_abs(ABS_RUDDER); break; + case 0xba: map_abs(ABS_RUDDER); break; case 0xbb: map_abs(ABS_THROTTLE); break; + case 0xc4: map_abs(ABS_GAS); break; + case 0xc5: map_abs(ABS_BRAKE); break; + case 0xc8: map_abs(ABS_WHEEL); break; default: goto ignore; } break; -- GitLab From 1e27ffd4d7d39783c5196daa2584cca5785d1f95 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 14 Jan 2006 00:28:04 -0500 Subject: [PATCH 176/465] Input: wacom - fix compile on PowerPC Rename G4 (new Graphire4) to WACOM_G4 to avoid clashes on PowerPC Signed-off-by: Dmitry Torokhov --- drivers/usb/input/wacom.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c index 48df4cfd5a4..d3e15df9e81 100644 --- a/drivers/usb/input/wacom.c +++ b/drivers/usb/input/wacom.c @@ -95,7 +95,7 @@ MODULE_LICENSE(DRIVER_LICENSE); enum { PENPARTNER = 0, GRAPHIRE, - G4, + WACOM_G4, PL, INTUOS, INTUOS3, @@ -373,7 +373,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) case 2: /* Mouse with wheel */ input_report_key(dev, BTN_MIDDLE, data[1] & 0x04); - if (wacom->features->type == G4) { + if (wacom->features->type == WACOM_G4) { rw = data[7] & 0x04 ? -(data[7] & 0x03) : (data[7] & 0x03); input_report_rel(dev, REL_WHEEL, rw); } else @@ -385,7 +385,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) id = CURSOR_DEVICE_ID; input_report_key(dev, BTN_LEFT, data[1] & 0x01); input_report_key(dev, BTN_RIGHT, data[1] & 0x02); - if (wacom->features->type == G4) + if (wacom->features->type == WACOM_G4) input_report_abs(dev, ABS_DISTANCE, data[6]); else input_report_abs(dev, ABS_DISTANCE, data[7]); @@ -410,7 +410,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) input_sync(dev); /* send pad data */ - if (wacom->features->type == G4) { + if (wacom->features->type == WACOM_G4) { /* fist time sending pad data */ if (wacom->tool[1] != BTN_TOOL_FINGER) { wacom->id[1] = 0; @@ -713,8 +713,8 @@ static struct wacom_features wacom_features[] = { { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, GRAPHIRE, wacom_graphire_irq }, { "Wacom Graphire3", 8, 10208, 7424, 511, 32, GRAPHIRE, wacom_graphire_irq }, { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, GRAPHIRE, wacom_graphire_irq }, - { "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 32, G4, wacom_graphire_irq }, - { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 32, G4, wacom_graphire_irq }, + { "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 32, WACOM_G4, wacom_graphire_irq }, + { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 32, WACOM_G4, wacom_graphire_irq }, { "Wacom Volito", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, { "Wacom PenStation2", 8, 3250, 2320, 255, 32, GRAPHIRE, wacom_graphire_irq }, { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, @@ -859,7 +859,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0); switch (wacom->features->type) { - case G4: + case WACOM_G4: input_dev->evbit[0] |= BIT(EV_MSC); input_dev->mscbit[0] |= BIT(MSC_SERIAL); input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); -- GitLab From eab9edd27f7ceaad6b57085817d63287bda15190 Mon Sep 17 00:00:00 2001 From: Michael Hanselmann Date: Sat, 14 Jan 2006 10:08:06 -0500 Subject: [PATCH 177/465] Input: HID - add support for fn key on Apple PowerBooks This patch implements support for the fn key on Apple PowerBooks using USB based keyboards and makes them behave like their ADB counterparts. Signed-off-by: Michael Hanselmann Acked-by: Rene Nussbaumer Acked-by: Johannes Berg Acked-by: Benjamin Herrenschmidt Acked-by: Vojtech Pavlik Signed-off-by: Dmitry Torokhov --- drivers/usb/input/Kconfig | 10 ++ drivers/usb/input/hid-core.c | 8 ++ drivers/usb/input/hid-input.c | 166 +++++++++++++++++++++++++++++++++- drivers/usb/input/hid.h | 31 ++++--- 4 files changed, 201 insertions(+), 14 deletions(-) diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig index 509dd0a04c5..5246b35301d 100644 --- a/drivers/usb/input/Kconfig +++ b/drivers/usb/input/Kconfig @@ -37,6 +37,16 @@ config USB_HIDINPUT If unsure, say Y. +config USB_HIDINPUT_POWERBOOK + bool "Enable support for iBook/PowerBook special keys" + default n + depends on USB_HIDINPUT + help + Say Y here if you want support for the special keys (Fn, Numlock) on + Apple iBooks and PowerBooks. + + If unsure, say N. + config HID_FF bool "Force feedback support (EXPERIMENTAL)" depends on USB_HIDINPUT && EXPERIMENTAL diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 1a2d20303ed..a91e72c4141 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -1585,6 +1585,14 @@ static const struct hid_blacklist { { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION }, + { USB_VENDOR_ID_APPLE, 0x020E, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, 0x020F, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, 0x0214, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, 0x0215, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, 0x0216, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN }, + { 0, 0 } }; diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c index 36a08c04c46..cb0d80f4925 100644 --- a/drivers/usb/input/hid-input.c +++ b/drivers/usb/input/hid-input.c @@ -73,6 +73,160 @@ static const struct { #define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0) #define map_ff_effect(c) do { set_bit(c, input->ffbit); } while (0) +#ifdef CONFIG_USB_HIDINPUT_POWERBOOK + +struct hidinput_key_translation { + u16 from; + u16 to; + u8 flags; +}; + +#define POWERBOOK_FLAG_FKEY 0x01 + +static struct hidinput_key_translation powerbook_fn_keys[] = { + { KEY_BACKSPACE, KEY_DELETE }, + { KEY_F1, KEY_BRIGHTNESSDOWN, POWERBOOK_FLAG_FKEY }, + { KEY_F2, KEY_BRIGHTNESSUP, POWERBOOK_FLAG_FKEY }, + { KEY_F3, KEY_MUTE, POWERBOOK_FLAG_FKEY }, + { KEY_F4, KEY_VOLUMEDOWN, POWERBOOK_FLAG_FKEY }, + { KEY_F5, KEY_VOLUMEUP, POWERBOOK_FLAG_FKEY }, + { KEY_F6, KEY_NUMLOCK, POWERBOOK_FLAG_FKEY }, + { KEY_F7, KEY_SWITCHVIDEOMODE, POWERBOOK_FLAG_FKEY }, + { KEY_F8, KEY_KBDILLUMTOGGLE, POWERBOOK_FLAG_FKEY }, + { KEY_F9, KEY_KBDILLUMDOWN, POWERBOOK_FLAG_FKEY }, + { KEY_F10, KEY_KBDILLUMUP, POWERBOOK_FLAG_FKEY }, + { KEY_UP, KEY_PAGEUP }, + { KEY_DOWN, KEY_PAGEDOWN }, + { KEY_LEFT, KEY_HOME }, + { KEY_RIGHT, KEY_END }, + { } +}; + +static struct hidinput_key_translation powerbook_numlock_keys[] = { + { KEY_J, KEY_KP1 }, + { KEY_K, KEY_KP2 }, + { KEY_L, KEY_KP3 }, + { KEY_U, KEY_KP4 }, + { KEY_I, KEY_KP5 }, + { KEY_O, KEY_KP6 }, + { KEY_7, KEY_KP7 }, + { KEY_8, KEY_KP8 }, + { KEY_9, KEY_KP9 }, + { KEY_M, KEY_KP0 }, + { KEY_DOT, KEY_KPDOT }, + { KEY_SLASH, KEY_KPPLUS }, + { KEY_SEMICOLON, KEY_KPMINUS }, + { KEY_P, KEY_KPASTERISK }, + { KEY_MINUS, KEY_KPEQUAL }, + { KEY_0, KEY_KPSLASH }, + { KEY_F6, KEY_NUMLOCK }, + { KEY_KPENTER, KEY_KPENTER }, + { KEY_BACKSPACE, KEY_BACKSPACE }, + { } +}; + +static int usbhid_pb_fnmode = 1; +module_param_named(pb_fnmode, usbhid_pb_fnmode, int, 0644); +MODULE_PARM_DESC(pb_fnmode, + "Mode of fn key on PowerBooks (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)"); + +static struct hidinput_key_translation *find_translation(struct hidinput_key_translation *table, u16 from) +{ + struct hidinput_key_translation *trans; + + /* Look for the translation */ + for (trans = table; trans->from; trans++) + if (trans->from == from) + return trans; + + return NULL; +} + +static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input, + struct hid_usage *usage, __s32 value) +{ + struct hidinput_key_translation *trans; + + if (usage->code == KEY_FN) { + if (value) hid->quirks |= HID_QUIRK_POWERBOOK_FN_ON; + else hid->quirks &= ~HID_QUIRK_POWERBOOK_FN_ON; + + input_event(input, usage->type, usage->code, value); + + return 1; + } + + if (usbhid_pb_fnmode) { + int do_translate; + + trans = find_translation(powerbook_fn_keys, usage->code); + if (trans) { + if (test_bit(usage->code, hid->pb_pressed_fn)) + do_translate = 1; + else if (trans->flags & POWERBOOK_FLAG_FKEY) + do_translate = + (usbhid_pb_fnmode == 2 && (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)) || + (usbhid_pb_fnmode == 1 && !(hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)); + else + do_translate = (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON); + + if (do_translate) { + if (value) + set_bit(usage->code, hid->pb_pressed_fn); + else + clear_bit(usage->code, hid->pb_pressed_fn); + + input_event(input, usage->type, trans->to, value); + + return 1; + } + } + + if (test_bit(usage->code, hid->pb_pressed_numlock) || + test_bit(LED_NUML, input->led)) { + trans = find_translation(powerbook_numlock_keys, usage->code); + + if (trans) { + if (value) + set_bit(usage->code, hid->pb_pressed_numlock); + else + clear_bit(usage->code, hid->pb_pressed_numlock); + + input_event(input, usage->type, trans->to, value); + } + + return 1; + } + } + + return 0; +} + +static void hidinput_pb_setup(struct input_dev *input) +{ + struct hidinput_key_translation *trans; + + set_bit(KEY_NUMLOCK, input->keybit); + + /* Enable all needed keys */ + for (trans = powerbook_fn_keys; trans->from; trans++) + set_bit(trans->to, input->keybit); + + for (trans = powerbook_numlock_keys; trans->from; trans++) + set_bit(trans->to, input->keybit); +} +#else +static inline int hidinput_pb_event(struct hid_device *hid, struct input_dev *input, + struct hid_usage *usage, __s32 value) +{ + return 0; +} + +static inline void hidinput_pb_setup(struct input_dev *input) +{ +} +#endif + static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, struct hid_usage *usage) { @@ -336,7 +490,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel set_bit(EV_REP, input->evbit); switch(usage->hid & HID_USAGE) { - case 0x003: map_key_clear(KEY_FN); break; + case 0x003: + /* The fn key on Apple PowerBooks */ + map_key_clear(KEY_FN); + hidinput_pb_setup(input); + break; + default: goto ignore; } break; @@ -493,6 +652,9 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct return; } + if ((hid->quirks & HID_QUIRK_POWERBOOK_HAS_FN) && hidinput_pb_event(hid, input, usage, value)) + return; + if (usage->hat_min < usage->hat_max || usage->hat_dir) { int hat_dir = usage->hat_dir; if (!hat_dir) @@ -535,7 +697,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct return; } - if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */ + if ((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */ return; input_event(input, usage->type, usage->code, value); diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h index 335316c7233..8b0d4346ce9 100644 --- a/drivers/usb/input/hid.h +++ b/drivers/usb/input/hid.h @@ -235,18 +235,20 @@ struct hid_item { * HID device quirks. */ -#define HID_QUIRK_INVERT 0x001 -#define HID_QUIRK_NOTOUCH 0x002 -#define HID_QUIRK_IGNORE 0x004 -#define HID_QUIRK_NOGET 0x008 -#define HID_QUIRK_HIDDEV 0x010 -#define HID_QUIRK_BADPAD 0x020 -#define HID_QUIRK_MULTI_INPUT 0x040 -#define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x080 -#define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x100 -#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x200 -#define HID_QUIRK_2WHEEL_POWERMOUSE 0x400 -#define HID_QUIRK_CYMOTION 0x800 +#define HID_QUIRK_INVERT 0x00000001 +#define HID_QUIRK_NOTOUCH 0x00000002 +#define HID_QUIRK_IGNORE 0x00000004 +#define HID_QUIRK_NOGET 0x00000008 +#define HID_QUIRK_HIDDEV 0x00000010 +#define HID_QUIRK_BADPAD 0x00000020 +#define HID_QUIRK_MULTI_INPUT 0x00000040 +#define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x00000080 +#define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x00000100 +#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x00000200 +#define HID_QUIRK_2WHEEL_POWERMOUSE 0x00000400 +#define HID_QUIRK_CYMOTION 0x00000800 +#define HID_QUIRK_POWERBOOK_HAS_FN 0x00001000 +#define HID_QUIRK_POWERBOOK_FN_ON 0x00002000 /* * This is the global environment of the parser. This information is @@ -432,6 +434,11 @@ struct hid_device { /* device report descriptor */ void (*ff_exit)(struct hid_device*); /* Called by hid_exit_ff(hid) */ int (*ff_event)(struct hid_device *hid, struct input_dev *input, unsigned int type, unsigned int code, int value); + +#ifdef CONFIG_USB_HIDINPUT_POWERBOOK + unsigned long pb_pressed_fn[NBITS(KEY_MAX)]; + unsigned long pb_pressed_numlock[NBITS(KEY_MAX)]; +#endif }; #define HID_GLOBAL_STACK_SIZE 4 -- GitLab From da2b1cd61903c8e9796e76be2d606584f26a78e5 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sat, 14 Jan 2006 16:18:07 +0000 Subject: [PATCH 178/465] [ARM] 3101/1: ARM EABI: slab memory must be 64-bit aligned Patch from Nicolas Pitre Although ARM is still using 32-bit pointers, version 5 and later versions of the ARM architecture introduced the ldrd and strd instructions to move 64-bit data which must be 64-bit aligned in memory, and the EABI includes new constraints on structure data alignment to allow for the compiler to use those instructions. This means that any slab allocation must start on a 64-bit boundary which is not equivalent to BYTES_PER_WORD, especially on those architecture versions that implements the ldrd/strd instructions. Overriding the default alignment disables some slab debug features. If those debug features are really needed then the kernel will have to be compiled for version 4 of the ARM architecture. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- include/asm-arm/page.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/asm-arm/page.h b/include/asm-arm/page.h index 4da1d532cbe..416320d9541 100644 --- a/include/asm-arm/page.h +++ b/include/asm-arm/page.h @@ -170,6 +170,13 @@ extern pmd_t *top_pmd; #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) +/* + * With EABI on ARMv5 and above we must have 64-bit aligned slab pointers. + */ +#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) +#define ARCH_SLAB_MINALIGN 8 +#endif + #endif /* __KERNEL__ */ #include -- GitLab From 2dede2d8e925f4c2cb4e136b14df127685e15dd3 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sat, 14 Jan 2006 16:18:08 +0000 Subject: [PATCH 179/465] [ARM] 3102/1: ARM EABI: stack pointer must be 64-bit aligned after a CPU exception Patch from Nicolas Pitre The ARM EABI says that the stack pointer has to be 64-bit aligned for reasons already mentioned in patch #3101 when calling C functions. We therefore must verify and adjust sp accordingly when taking an exception from kernel mode since sp might not necessarily be 64-bit aligned if the exception occurs in the middle of a kernel function. If the exception occurs while in user mode then no sp fixup is needed as long as sizeof(struct pt_regs) as well as any additional syscall data stack space remain multiples of 8. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/kernel/entry-armv.S | 17 +++++++++++++++++ arch/arm/kernel/entry-header.S | 1 + include/asm-arm/ptrace.h | 8 +++++--- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index fb8e7f4c4b3..874e6bb7940 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -105,14 +105,24 @@ common_invalid: /* * SVC mode handlers */ + +#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) +#define SPFIX(code...) code +#else +#define SPFIX(code...) +#endif + .macro svc_entry sub sp, sp, #S_FRAME_SIZE + SPFIX( tst sp, #4 ) + SPFIX( bicne sp, sp, #4 ) stmib sp, {r1 - r12} ldmia r0, {r1 - r3} add r5, sp, #S_SP @ here for interlock avoidance mov r4, #-1 @ "" "" "" "" add r0, sp, #S_FRAME_SIZE @ "" "" "" "" + SPFIX( addne r0, r0, #4 ) str r1, [sp] @ save the "real" r0 copied @ from the exception stack @@ -303,7 +313,14 @@ __pabt_svc: /* * User mode handlers + * + * EABI note: sp_svc is always 64-bit aligned here, so should S_FRAME_SIZE */ + +#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) && (S_FRAME_SIZE & 7) +#error "sizeof(struct pt_regs) must be a multiple of 8" +#endif + .macro usr_entry sub sp, sp, #S_FRAME_SIZE stmib sp, {r1 - r12} diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S index 648cfff9313..55c99cdab7d 100644 --- a/arch/arm/kernel/entry-header.S +++ b/arch/arm/kernel/entry-header.S @@ -19,6 +19,7 @@ @ @ Most of the stack format comes from struct pt_regs, but with @ the addition of 8 bytes for storing syscall args 5 and 6. +@ This _must_ remain a multiple of 8 for EABI. @ #define S_OFF 8 diff --git a/include/asm-arm/ptrace.h b/include/asm-arm/ptrace.h index 4377e22b7e1..f40948d5444 100644 --- a/include/asm-arm/ptrace.h +++ b/include/asm-arm/ptrace.h @@ -60,9 +60,11 @@ #ifndef __ASSEMBLY__ -/* this struct defines the way the registers are stored on the - stack during a system call. */ - +/* + * This struct defines the way the registers are stored on the + * stack during a system call. Note that sizeof(struct pt_regs) + * has to be a multiple of 8. + */ struct pt_regs { long uregs[18]; }; -- GitLab From 499b2ea11ff00c624d63af23516404fa2156639a Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sat, 14 Jan 2006 16:18:09 +0000 Subject: [PATCH 180/465] [ARM] 3103/1: ARM EABI: stack pointer must be 64-bit aligned (part 2) Patch from Nicolas Pitre We must make sure that assembly code that modifies the stack pointer before calling a C function does it so it remains 64-bit aligned. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/kernel/semaphore.c | 17 +++++++++-------- arch/arm/lib/lib1funcs.S | 4 ++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/arch/arm/kernel/semaphore.c b/arch/arm/kernel/semaphore.c index 4c31f292305..981fe5c6ccb 100644 --- a/arch/arm/kernel/semaphore.c +++ b/arch/arm/kernel/semaphore.c @@ -177,41 +177,42 @@ int __down_trylock(struct semaphore * sem) * ip contains the semaphore pointer on entry. Save the C-clobbered * registers (r0 to r3 and lr), but not ip, as we use it as a return * value in some cases.. + * To remain AAPCS compliant (64-bit stack align) we save r4 as well. */ asm(" .section .sched.text,\"ax\",%progbits \n\ .align 5 \n\ .globl __down_failed \n\ __down_failed: \n\ - stmfd sp!, {r0 - r3, lr} \n\ + stmfd sp!, {r0 - r4, lr} \n\ mov r0, ip \n\ bl __down \n\ - ldmfd sp!, {r0 - r3, pc} \n\ + ldmfd sp!, {r0 - r4, pc} \n\ \n\ .align 5 \n\ .globl __down_interruptible_failed \n\ __down_interruptible_failed: \n\ - stmfd sp!, {r0 - r3, lr} \n\ + stmfd sp!, {r0 - r4, lr} \n\ mov r0, ip \n\ bl __down_interruptible \n\ mov ip, r0 \n\ - ldmfd sp!, {r0 - r3, pc} \n\ + ldmfd sp!, {r0 - r4, pc} \n\ \n\ .align 5 \n\ .globl __down_trylock_failed \n\ __down_trylock_failed: \n\ - stmfd sp!, {r0 - r3, lr} \n\ + stmfd sp!, {r0 - r4, lr} \n\ mov r0, ip \n\ bl __down_trylock \n\ mov ip, r0 \n\ - ldmfd sp!, {r0 - r3, pc} \n\ + ldmfd sp!, {r0 - r4, pc} \n\ \n\ .align 5 \n\ .globl __up_wakeup \n\ __up_wakeup: \n\ - stmfd sp!, {r0 - r3, lr} \n\ + stmfd sp!, {r0 - r4, lr} \n\ mov r0, ip \n\ bl __up \n\ - ldmfd sp!, {r0 - r3, pc} \n\ + ldmfd sp!, {r0 - r4, pc} \n\ "); EXPORT_SYMBOL(__down_failed); diff --git a/arch/arm/lib/lib1funcs.S b/arch/arm/lib/lib1funcs.S index 59026029d01..4964e5bafa0 100644 --- a/arch/arm/lib/lib1funcs.S +++ b/arch/arm/lib/lib1funcs.S @@ -306,9 +306,9 @@ ENTRY(__modsi3) Ldiv0: - str lr, [sp, #-4]! + str lr, [sp, #-8]! bl __div0 mov r0, #0 @ About as wrong as it could be. - ldr pc, [sp], #4 + ldr pc, [sp], #8 -- GitLab From ba95e4e4a0a8a3c6aba363d45f78d5f2e2d111eb Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sat, 14 Jan 2006 16:18:29 +0000 Subject: [PATCH 181/465] [ARM] 3104/1: ARM EABI: new helper function names Patch from Nicolas Pitre The ARM EABI defines new names for GCC helper functions. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/kernel/armksyms.c | 22 ++++++++++++++++++++++ arch/arm/lib/ashldi3.S | 1 + arch/arm/lib/ashrdi3.S | 1 + arch/arm/lib/lib1funcs.S | 23 +++++++++++++++++++++++ arch/arm/lib/lshrdi3.S | 1 + arch/arm/lib/muldi3.S | 1 + arch/arm/lib/ucmpdi2.S | 14 ++++++++++++++ 7 files changed, 63 insertions(+) diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index 9997098009a..1574941ebfe 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -35,6 +35,16 @@ extern void __udivsi3(void); extern void __umodsi3(void); extern void __do_div64(void); +extern void __aeabi_idiv(void); +extern void __aeabi_idivmod(void); +extern void __aeabi_lasr(void); +extern void __aeabi_llsl(void); +extern void __aeabi_llsr(void); +extern void __aeabi_lmul(void); +extern void __aeabi_uidiv(void); +extern void __aeabi_uidivmod(void); +extern void __aeabi_ulcmp(void); + extern void fpundefinstr(void); extern void fp_enter(void); @@ -141,6 +151,18 @@ EXPORT_SYMBOL(__udivsi3); EXPORT_SYMBOL(__umodsi3); EXPORT_SYMBOL(__do_div64); +#ifdef CONFIG_AEABI +EXPORT_SYMBOL(__aeabi_idiv); +EXPORT_SYMBOL(__aeabi_idivmod); +EXPORT_SYMBOL(__aeabi_lasr); +EXPORT_SYMBOL(__aeabi_llsl); +EXPORT_SYMBOL(__aeabi_llsr); +EXPORT_SYMBOL(__aeabi_lmul); +EXPORT_SYMBOL(__aeabi_uidiv); +EXPORT_SYMBOL(__aeabi_uidivmod); +EXPORT_SYMBOL(__aeabi_ulcmp); +#endif + /* bitops */ EXPORT_SYMBOL(_set_bit_le); EXPORT_SYMBOL(_test_and_set_bit_le); diff --git a/arch/arm/lib/ashldi3.S b/arch/arm/lib/ashldi3.S index 561e20717b3..55e57a1c2e6 100644 --- a/arch/arm/lib/ashldi3.S +++ b/arch/arm/lib/ashldi3.S @@ -37,6 +37,7 @@ Boston, MA 02110-1301, USA. */ #endif ENTRY(__ashldi3) +ENTRY(__aeabi_llsl) subs r3, r2, #32 rsb ip, r2, #32 diff --git a/arch/arm/lib/ashrdi3.S b/arch/arm/lib/ashrdi3.S index 86fb2a90c30..0b31398f89b 100644 --- a/arch/arm/lib/ashrdi3.S +++ b/arch/arm/lib/ashrdi3.S @@ -37,6 +37,7 @@ Boston, MA 02110-1301, USA. */ #endif ENTRY(__ashrdi3) +ENTRY(__aeabi_lasr) subs r3, r2, #32 rsb ip, r2, #32 diff --git a/arch/arm/lib/lib1funcs.S b/arch/arm/lib/lib1funcs.S index 4964e5bafa0..4e492f4b3f0 100644 --- a/arch/arm/lib/lib1funcs.S +++ b/arch/arm/lib/lib1funcs.S @@ -206,6 +206,7 @@ Boston, MA 02111-1307, USA. */ ENTRY(__udivsi3) +ENTRY(__aeabi_uidiv) subs r2, r1, #1 moveq pc, lr @@ -246,6 +247,7 @@ ENTRY(__umodsi3) ENTRY(__divsi3) +ENTRY(__aeabi_idiv) cmp r1, #0 eor ip, r0, r1 @ save the sign of the result. @@ -303,6 +305,27 @@ ENTRY(__modsi3) rsbmi r0, r0, #0 mov pc, lr +#ifdef CONFIG_AEABI + +ENTRY(__aeabi_uidivmod) + + stmfd sp!, {r0, r1, ip, lr} + bl __aeabi_uidiv + ldmfd sp!, {r1, r2, ip, lr} + mul r3, r0, r2 + sub r1, r1, r3 + mov pc, lr + +ENTRY(__aeabi_idivmod) + + stmfd sp!, {r0, r1, ip, lr} + bl __aeabi_idiv + ldmfd sp!, {r1, r2, ip, lr} + mul r3, r0, r2 + sub r1, r1, r3 + mov pc, lr + +#endif Ldiv0: diff --git a/arch/arm/lib/lshrdi3.S b/arch/arm/lib/lshrdi3.S index 46c2ed19ec9..a86dbdd59cc 100644 --- a/arch/arm/lib/lshrdi3.S +++ b/arch/arm/lib/lshrdi3.S @@ -37,6 +37,7 @@ Boston, MA 02110-1301, USA. */ #endif ENTRY(__lshrdi3) +ENTRY(__aeabi_llsr) subs r3, r2, #32 rsb ip, r2, #32 diff --git a/arch/arm/lib/muldi3.S b/arch/arm/lib/muldi3.S index c7fbdf00531..72d594184b8 100644 --- a/arch/arm/lib/muldi3.S +++ b/arch/arm/lib/muldi3.S @@ -25,6 +25,7 @@ #endif ENTRY(__muldi3) +ENTRY(__aeabi_lmul) mul xh, yl, xh mla xh, xl, yh, xh diff --git a/arch/arm/lib/ucmpdi2.S b/arch/arm/lib/ucmpdi2.S index 112630f93e5..d847a62834c 100644 --- a/arch/arm/lib/ucmpdi2.S +++ b/arch/arm/lib/ucmpdi2.S @@ -10,6 +10,7 @@ * published by the Free Software Foundation. */ +#include #include #ifdef __ARMEB__ @@ -33,3 +34,16 @@ ENTRY(__ucmpdi2) movhi r0, #2 mov pc, lr +#ifdef CONFIG_AEABI + +ENTRY(__aeabi_ulcmp) + + cmp xh, yh + cmpeq xl, yl + movlo r0, #-1 + moveq r0, #0 + movhi r0, #1 + mov pc, lr + +#endif + -- GitLab From 3f2829a31573e3e502b874c8d69a765f7a778793 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sat, 14 Jan 2006 16:31:29 +0000 Subject: [PATCH 182/465] [ARM] 3105/4: ARM EABI: new syscall entry convention Patch from Nicolas Pitre For a while we wanted to change the way syscalls were called on ARM. Instead of encoding the syscall number in the swi instruction which requires reading back the instruction from memory to extract that number and polluting the data cache, it was decided that simply storing the syscall number into r7 would be more efficient. Since this represents an ABI change then making that change at the same time as EABI support is the right thing to do. It is now expected that EABI user space binaries put the syscall number into r7 and use "swi 0" to call the kernel. Syscall register argument are also expected to have "EABI arrangement" i.e. 64-bit arguments should be put in a pair of registers from an even register number. Example with long ftruncate64(unsigned int fd, loff_t length): legacy ABI: - put fd into r0 - put length into r1-r2 - use "swi #(0x900000 + 194)" to call the kernel new ARM EABI: - put fd into r0 - put length into r2-r3 (skipping over r1) - put 194 into r7 - use "swi 0" to call the kernel Note that it is important to use 0 for the swi argument as backward compatibility with legacy ABI user space relies on this. The syscall macros in asm-arm/unistd.h were also updated to support both ABIs and implement the right call method automatically. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/kernel/entry-common.S | 35 +++++++++++++++---------- arch/arm/kernel/traps.c | 2 +- include/asm-arm/unistd.h | 48 ++++++++++++++++++---------------- 3 files changed, 48 insertions(+), 37 deletions(-) diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index e2b42997ad3..34826bcceb7 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -98,20 +98,14 @@ ENTRY(ret_from_fork) run on an ARM7 and we can save a couple of instructions. --pb */ #ifdef CONFIG_CPU_ARM710 - .macro arm710_bug_check, instr, temp - and \temp, \instr, #0x0f000000 @ check for SWI - teq \temp, #0x0f000000 - bne .Larm700bug - .endm - -.Larm700bug: +#define A710(code...) code +.Larm710bug: ldmia sp, {r0 - lr}^ @ Get calling r0 - lr mov r0, r0 add sp, sp, #S_FRAME_SIZE subs pc, lr, #4 #else - .macro arm710_bug_check, instr, temp - .endm +#define A710(code...) #endif .align 5 @@ -129,14 +123,24 @@ ENTRY(vector_swi) /* * Get the system call number. */ -#ifdef CONFIG_ARM_THUMB +#if defined(CONFIG_AEABI) + + @ syscall number is in scno (r7) already. + + A710( ldr ip, [lr, #-4] @ get SWI instruction ) + A710( and ip, ip, #0x0f000000 @ check for SWI ) + A710( teq ip, #0x0f000000 ) + A710( bne .Larm710bug ) +#elif defined(CONFIG_ARM_THUMB) tst r8, #PSR_T_BIT @ this is SPSR from save_user_regs addne scno, r7, #__NR_SYSCALL_BASE @ put OS number in ldreq scno, [lr, #-4] #else ldr scno, [lr, #-4] @ get SWI instruction + A710( and ip, scno, #0x0f000000 @ check for SWI ) + A710( teq ip, #0x0f000000 ) + A710( bne .Larm710bug ) #endif - arm710_bug_check scno, ip #ifdef CONFIG_ALIGNMENT_TRAP ldr ip, __cr_alignment @@ -145,18 +149,19 @@ ENTRY(vector_swi) #endif enable_irq - stmdb sp!, {r4, r5} @ push fifth and sixth args - get_thread_info tsk ldr ip, [tsk, #TI_FLAGS] @ check for syscall tracing +#ifndef CONFIG_AEABI bic scno, scno, #0xff000000 @ mask off SWI op-code eor scno, scno, #__NR_SYSCALL_BASE @ check OS number +#endif adr tbl, sys_call_table @ load syscall table pointer + stmdb sp!, {r4, r5} @ push fifth and sixth args tst ip, #_TIF_SYSCALL_TRACE @ are we tracing syscalls? bne __sys_trace - adr lr, ret_fast_syscall @ return address cmp scno, #NR_syscalls @ check upper syscall limit + adr lr, ret_fast_syscall @ return address ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine add r1, sp, #S_OFF @@ -207,6 +212,7 @@ ENTRY(sys_call_table) @ r8 = syscall table .type sys_syscall, #function sys_syscall: +#ifndef CONFIG_AEABI eor scno, r0, #__NR_SYSCALL_BASE cmp scno, #__NR_syscall - __NR_SYSCALL_BASE cmpne scno, #NR_syscalls @ check range @@ -216,6 +222,7 @@ sys_syscall: movlo r2, r3 movlo r3, r4 ldrlo pc, [tbl, scno, lsl #2] +#endif b sys_ni_syscall sys_fork_wrapper: diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 93cfd3ffcc7..10235b01582 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -404,7 +404,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) struct thread_info *thread = current_thread_info(); siginfo_t info; - if ((no >> 16) != 0x9f) + if ((no >> 16) != (__ARM_NR_BASE>> 16)) return bad_syscall(no, regs); switch (no & 0xffff) { diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h index d626e70fade..c9e087fe7e1 100644 --- a/include/asm-arm/unistd.h +++ b/include/asm-arm/unistd.h @@ -15,10 +15,12 @@ #include -#if defined(__thumb__) +#define __NR_OABI_SYSCALL_BASE 0x900000 + +#if defined(__thumb__) || defined(__ARM_EABI__) #define __NR_SYSCALL_BASE 0 #else -#define __NR_SYSCALL_BASE 0x900000 +#define __NR_SYSCALL_BASE __NR_OABI_SYSCALL_BASE #endif /* @@ -373,13 +375,13 @@ #define __sys1(x) __sys2(x) #ifndef __syscall -#if defined(__thumb__) -#define __syscall(name) \ - "push {r7}\n\t" \ - "mov r7, #" __sys1(__NR_##name) "\n\t" \ - "swi 0\n\t" \ - "pop {r7}" +#if defined(__thumb__) || defined(__ARM_EABI__) +#define __SYS_REG(name) register long __sysreg __asm__("r7") = __NR_##name; +#define __SYS_REG_LIST(regs...) "r" (__sysreg) , ##regs +#define __syscall(name) "swi\t0" #else +#define __SYS_REG(name) +#define __SYS_REG_LIST(regs...) regs #define __syscall(name) "swi\t" __sys1(__NR_##name) "" #endif #endif @@ -395,33 +397,34 @@ do { \ #define _syscall0(type,name) \ type name(void) { \ + __SYS_REG(name) \ register long __res_r0 __asm__("r0"); \ long __res; \ __asm__ __volatile__ ( \ __syscall(name) \ : "=r" (__res_r0) \ - : \ - : "lr"); \ + : __SYS_REG_LIST() ); \ __res = __res_r0; \ __syscall_return(type,__res); \ } #define _syscall1(type,name,type1,arg1) \ type name(type1 arg1) { \ + __SYS_REG(name) \ register long __r0 __asm__("r0") = (long)arg1; \ register long __res_r0 __asm__("r0"); \ long __res; \ __asm__ __volatile__ ( \ __syscall(name) \ : "=r" (__res_r0) \ - : "r" (__r0) \ - : "lr"); \ + : __SYS_REG_LIST( "0" (__r0) ) ); \ __res = __res_r0; \ __syscall_return(type,__res); \ } #define _syscall2(type,name,type1,arg1,type2,arg2) \ type name(type1 arg1,type2 arg2) { \ + __SYS_REG(name) \ register long __r0 __asm__("r0") = (long)arg1; \ register long __r1 __asm__("r1") = (long)arg2; \ register long __res_r0 __asm__("r0"); \ @@ -429,8 +432,7 @@ type name(type1 arg1,type2 arg2) { \ __asm__ __volatile__ ( \ __syscall(name) \ : "=r" (__res_r0) \ - : "r" (__r0),"r" (__r1) \ - : "lr"); \ + : __SYS_REG_LIST( "0" (__r0), "r" (__r1) ) ); \ __res = __res_r0; \ __syscall_return(type,__res); \ } @@ -438,6 +440,7 @@ type name(type1 arg1,type2 arg2) { \ #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ type name(type1 arg1,type2 arg2,type3 arg3) { \ + __SYS_REG(name) \ register long __r0 __asm__("r0") = (long)arg1; \ register long __r1 __asm__("r1") = (long)arg2; \ register long __r2 __asm__("r2") = (long)arg3; \ @@ -446,8 +449,7 @@ type name(type1 arg1,type2 arg2,type3 arg3) { \ __asm__ __volatile__ ( \ __syscall(name) \ : "=r" (__res_r0) \ - : "r" (__r0),"r" (__r1),"r" (__r2) \ - : "lr"); \ + : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2) ) ); \ __res = __res_r0; \ __syscall_return(type,__res); \ } @@ -455,6 +457,7 @@ type name(type1 arg1,type2 arg2,type3 arg3) { \ #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4)\ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ + __SYS_REG(name) \ register long __r0 __asm__("r0") = (long)arg1; \ register long __r1 __asm__("r1") = (long)arg2; \ register long __r2 __asm__("r2") = (long)arg3; \ @@ -464,8 +467,7 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ __asm__ __volatile__ ( \ __syscall(name) \ : "=r" (__res_r0) \ - : "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3) \ - : "lr"); \ + : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), "r" (__r3) ) ); \ __res = __res_r0; \ __syscall_return(type,__res); \ } @@ -473,6 +475,7 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \ + __SYS_REG(name) \ register long __r0 __asm__("r0") = (long)arg1; \ register long __r1 __asm__("r1") = (long)arg2; \ register long __r2 __asm__("r2") = (long)arg3; \ @@ -483,14 +486,15 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \ __asm__ __volatile__ ( \ __syscall(name) \ : "=r" (__res_r0) \ - : "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3),"r" (__r4) \ - : "lr"); \ + : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), \ + "r" (__r3), "r" (__r4) ) ); \ __res = __res_r0; \ __syscall_return(type,__res); \ } #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) { \ + __SYS_REG(name) \ register long __r0 __asm__("r0") = (long)arg1; \ register long __r1 __asm__("r1") = (long)arg2; \ register long __r2 __asm__("r2") = (long)arg3; \ @@ -502,8 +506,8 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6 __asm__ __volatile__ ( \ __syscall(name) \ : "=r" (__res_r0) \ - : "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3), "r" (__r4),"r" (__r5) \ - : "lr"); \ + : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), \ + "r" (__r3), "r" (__r4), "r" (__r5) ) ); \ __res = __res_r0; \ __syscall_return(type,__res); \ } -- GitLab From c155fc95befc95f4a9d6497f5fadec22f4bc3a24 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sat, 14 Jan 2006 16:32:12 +0000 Subject: [PATCH 183/465] [ARM] 3106/2: ARM EABI: some syscall adjustments Patch from Nicolas Pitre Fix a few syscalls for EABI requirements. They were sys_pread64 and sys_pwrite64 where the last argument is now entirely pushed on stack, but since commit 567bd98017d9c9f2ac1c148ddc78c062e8abd398 they don't require any fixup. Remains only the stat64 structure. Non EABI kernels are unaffected. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- include/asm-arm/stat.h | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/include/asm-arm/stat.h b/include/asm-arm/stat.h index ec4e2c2e3b4..42c0c13999d 100644 --- a/include/asm-arm/stat.h +++ b/include/asm-arm/stat.h @@ -70,14 +70,7 @@ struct stat64 { long long st_size; unsigned long st_blksize; - -#if defined(__ARMEB__) - unsigned long __pad4; /* Future possible st_blocks hi bits */ - unsigned long st_blocks; /* Number 512-byte blocks allocated. */ -#else /* Must be little */ - unsigned long st_blocks; /* Number 512-byte blocks allocated. */ - unsigned long __pad4; /* Future possible st_blocks hi bits */ -#endif + unsigned long long st_blocks; /* Number 512-byte blocks allocated. */ unsigned long st_atime; unsigned long st_atime_nsec; @@ -89,6 +82,6 @@ struct stat64 { unsigned long st_ctime_nsec; unsigned long long st_ino; -} __attribute__((packed)); +}; #endif -- GitLab From 704bdda03827db8a551e82b312037d63ba3c22ff Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sat, 14 Jan 2006 16:33:50 +0000 Subject: [PATCH 184/465] [ARM] 3107/3: ARM EABI: last bits to configure it Patch from Nicolas Pitre This adds the configuration option, and disables any FPA floating point emulators which are not EABI compatible. It also disables Acorn RISC OS/Arthur binary support when CONFIG_EABI=y since it is incompatible with an EABI kernel. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/Kconfig | 19 ++++++++++++++++++- arch/arm/Makefile | 7 ++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c4d585e2de7..ead6172692d 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -401,6 +401,21 @@ config NO_IDLE_HZ Currently at least OMAP, PXA2xx and SA11x0 platforms are known to have accurate timekeeping with dynamic tick. +config AEABI + bool "Use the ARM EABI to compile the kernel" + help + This option allows for the kernel to be compiled using the latest + ARM ABI (aka EABI). This is only useful if you are using a user + space environment that is also compiled with EABI. + + Since there are major incompatibilities between the legacy ABI and + EABI, especially with regard to structure member alignment, this + option also changes the kernel syscall calling convention to + disambiguate both ABIs and allow for backward compatibility support + (selected with CONFIG_OABI_COMPAT). + + To use this you need GCC version 4.0.0 or later. + config ARCH_DISCONTIGMEM_ENABLE bool default (ARCH_LH7A40X && !LH7A40X_CONTIGMEM) @@ -587,6 +602,7 @@ comment "At least one emulation must be selected" config FPE_NWFPE bool "NWFPE math emulation" + depends on !AEABI ---help--- Say Y to include the NWFPE floating point emulator in the kernel. This is necessary to run most binaries. Linux does not currently @@ -610,7 +626,7 @@ config FPE_NWFPE_XP config FPE_FASTFPE bool "FastFPE math emulation (EXPERIMENTAL)" - depends on !CPU_32v3 && EXPERIMENTAL + depends on !AEABI && !CPU_32v3 && EXPERIMENTAL ---help--- Say Y here to include the FAST floating point emulator in the kernel. This is an experimental much faster emulator which now also has full @@ -642,6 +658,7 @@ source "fs/Kconfig.binfmt" config ARTHUR tristate "RISC OS personality" + depends on !AEABI help Say Y here to include the kernel code necessary if you want to run Acorn RISC OS/Arthur binaries under Linux. This code is still very diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 1fa2a101158..fbfc14a56b9 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -56,8 +56,13 @@ tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100 tune-$(CONFIG_CPU_XSCALE) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale tune-$(CONFIG_CPU_V6) :=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm) -# Need -Uarm for gcc < 3.x +ifeq ($(CONFIG_AEABI),y) +CFLAGS_ABI :=-mabi=aapcs -mno-thumb-interwork +else CFLAGS_ABI :=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) $(call cc-option,-mno-thumb-interwork,) +endif + +# Need -Uarm for gcc < 3.x CFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm AFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) -msoft-float -- GitLab From 713c481519f19df9e6d90f257e7da0336b057592 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sat, 14 Jan 2006 16:35:03 +0000 Subject: [PATCH 185/465] [ARM] 3108/2: old ABI compat: statfs64 and fstatfs64 Patch from Nicolas Pitre struct statfs64 has extra padding with EABI growing its size from 84 to 88. This struct is now __attribute__((packed,aligned(4))) with a small assembly wrapper to force the sz argument to 84 if it is 88 to avoid copying the extra padding over user space memory unexpecting it. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/kernel/calls.S | 4 ++-- arch/arm/kernel/entry-common.S | 10 +++++++++ include/asm-arm/statfs.h | 38 +++++++++++++++++++++++++++++++++- 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index 55076a75e5b..8c0bf04814b 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S @@ -280,8 +280,8 @@ __syscall_start: .long sys_clock_gettime .long sys_clock_getres /* 265 */ .long sys_clock_nanosleep - .long sys_statfs64 - .long sys_fstatfs64 + .long sys_statfs64_wrapper + .long sys_fstatfs64_wrapper .long sys_tgkill .long sys_utimes /* 270 */ .long sys_arm_fadvise64_64 diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 34826bcceb7..ee63ee78d84 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -262,6 +262,16 @@ sys_sigaltstack_wrapper: ldr r2, [sp, #S_OFF + S_SP] b do_sigaltstack +sys_statfs64_wrapper: + teq r1, #88 + moveq r1, #84 + b sys_statfs64 + +sys_fstatfs64_wrapper: + teq r1, #88 + moveq r1, #84 + b sys_fstatfs64 + /* * Note: off_4k (r5) is always units of 4K. If we can't do the requested * offset, we return EINVAL. diff --git a/include/asm-arm/statfs.h b/include/asm-arm/statfs.h index e81f82783b8..a02e6a8c3d7 100644 --- a/include/asm-arm/statfs.h +++ b/include/asm-arm/statfs.h @@ -1,6 +1,42 @@ #ifndef _ASMARM_STATFS_H #define _ASMARM_STATFS_H -#include +#ifndef __KERNEL_STRICT_NAMES +# include +typedef __kernel_fsid_t fsid_t; +#endif + +struct statfs { + __u32 f_type; + __u32 f_bsize; + __u32 f_blocks; + __u32 f_bfree; + __u32 f_bavail; + __u32 f_files; + __u32 f_ffree; + __kernel_fsid_t f_fsid; + __u32 f_namelen; + __u32 f_frsize; + __u32 f_spare[5]; +}; + +/* + * With EABI there is 4 bytes of padding added to this structure. + * Let's pack it so the padding goes away to simplify dual ABI support. + * Note that user space does NOT have to pack this structure. + */ +struct statfs64 { + __u32 f_type; + __u32 f_bsize; + __u64 f_blocks; + __u64 f_bfree; + __u64 f_bavail; + __u64 f_files; + __u64 f_ffree; + __kernel_fsid_t f_fsid; + __u32 f_namelen; + __u32 f_frsize; + __u32 f_spare[5]; +} __attribute__ ((packed,aligned(4))); #endif -- GitLab From 687ad0191488a067b3b3cc94f670cc21f93811e1 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sat, 14 Jan 2006 16:35:31 +0000 Subject: [PATCH 186/465] [ARM] 3109/1: old ABI compat: syscall wrappers for ABI impedance matching Patch from Nicolas Pitre The difference between EABI and the legacy ABI may affect either structure member alignment and/or argument register selection. The patch has the details. Included are wrappers for the following syscalls: sys_stat64 sys_lstat64 sys_fstat64 sys_fcntl64 sys_epoll_ctl sys_epoll_wait sys_ipc sys_semop sys_semtimedop sys_pread64 sys_pwrite64 sys_truncate64 sys_ftruncate64 sys_readahead Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/kernel/Makefile | 1 + arch/arm/kernel/entry-common.S | 32 +++ arch/arm/kernel/sys_oabi-compat.c | 339 ++++++++++++++++++++++++++++++ 3 files changed, 372 insertions(+) create mode 100644 arch/arm/kernel/sys_oabi-compat.c diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index de94b0f3ee2..2ce0e3a27a4 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_ARTHUR) += arthur.o obj-$(CONFIG_ISA_DMA) += dma-isa.o obj-$(CONFIG_PCI) += bios32.o obj-$(CONFIG_SMP) += smp.o +obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o obj-$(CONFIG_IWMMXT) += iwmmxt.o AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index ee63ee78d84..59ce1bcec42 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -288,3 +288,35 @@ sys_mmap2: str r5, [sp, #4] b do_mmap2 #endif + +#ifdef CONFIG_OABI_COMPAT +/* + * These are syscalls with argument register differences + */ + +sys_oabi_pread64: + stmia sp, {r3, r4} + b sys_pread64 + +sys_oabi_pwrite64: + stmia sp, {r3, r4} + b sys_pwrite64 + +sys_oabi_truncate64: + mov r3, r2 + mov r2, r1 + b sys_truncate64 + +sys_oabi_ftruncate64: + mov r3, r2 + mov r2, r1 + b sys_ftruncate64 + +sys_oabi_readahead: + str r3, [sp] + mov r3, r2 + mov r2, r1 + b sys_readahead + +#endif + diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c new file mode 100644 index 00000000000..eafa8e5284a --- /dev/null +++ b/arch/arm/kernel/sys_oabi-compat.c @@ -0,0 +1,339 @@ +/* + * arch/arm/kernel/sys_oabi-compat.c + * + * Compatibility wrappers for syscalls that are used from + * old ABI user space binaries with an EABI kernel. + * + * Author: Nicolas Pitre + * Created: Oct 7, 2005 + * Copyright: MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * The legacy ABI and the new ARM EABI have different rules making some + * syscalls incompatible especially with structure arguments. + * Most notably, Eabi says 64-bit members should be 64-bit aligned instead of + * simply word aligned. EABI also pads structures to the size of the largest + * member it contains instead of the invariant 32-bit. + * + * The following syscalls are affected: + * + * sys_stat64: + * sys_lstat64: + * sys_fstat64: + * + * struct stat64 has different sizes and some members are shifted + * Compatibility wrappers are needed for them and provided below. + * + * sys_fcntl64: + * + * struct flock64 has different sizes and some members are shifted + * A compatibility wrapper is needed and provided below. + * + * sys_statfs64: + * sys_fstatfs64: + * + * struct statfs64 has extra padding with EABI growing its size from + * 84 to 88. This struct is now __attribute__((packed,aligned(4))) + * with a small assembly wrapper to force the sz argument to 84 if it is 88 + * to avoid copying the extra padding over user space unexpecting it. + * + * sys_newuname: + * + * struct new_utsname has no padding with EABI. No problem there. + * + * sys_epoll_ctl: + * sys_epoll_wait: + * + * struct epoll_event has its second member shifted also affecting the + * structure size. Compatibility wrappers are needed and provided below. + * + * sys_ipc: + * sys_semop: + * sys_semtimedop: + * + * struct sembuf loses its padding with EABI. Since arrays of them are + * used they have to be copyed to remove the padding. Compatibility wrappers + * provided below. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct oldabi_stat64 { + unsigned long long st_dev; + unsigned int __pad1; + unsigned long __st_ino; + unsigned int st_mode; + unsigned int st_nlink; + + unsigned long st_uid; + unsigned long st_gid; + + unsigned long long st_rdev; + unsigned int __pad2; + + long long st_size; + unsigned long st_blksize; + unsigned long long st_blocks; + + unsigned long st_atime; + unsigned long st_atime_nsec; + + unsigned long st_mtime; + unsigned long st_mtime_nsec; + + unsigned long st_ctime; + unsigned long st_ctime_nsec; + + unsigned long long st_ino; +} __attribute__ ((packed,aligned(4))); + +static long cp_oldabi_stat64(struct kstat *stat, + struct oldabi_stat64 __user *statbuf) +{ + struct oldabi_stat64 tmp; + + tmp.st_dev = huge_encode_dev(stat->dev); + tmp.__pad1 = 0; + tmp.__st_ino = stat->ino; + tmp.st_mode = stat->mode; + tmp.st_nlink = stat->nlink; + tmp.st_uid = stat->uid; + tmp.st_gid = stat->gid; + tmp.st_rdev = huge_encode_dev(stat->rdev); + tmp.st_size = stat->size; + tmp.st_blocks = stat->blocks; + tmp.__pad2 = 0; + tmp.st_blksize = stat->blksize; + tmp.st_atime = stat->atime.tv_sec; + tmp.st_atime_nsec = stat->atime.tv_nsec; + tmp.st_mtime = stat->mtime.tv_sec; + tmp.st_mtime_nsec = stat->mtime.tv_nsec; + tmp.st_ctime = stat->ctime.tv_sec; + tmp.st_ctime_nsec = stat->ctime.tv_nsec; + tmp.st_ino = stat->ino; + return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; +} + +asmlinkage long sys_oabi_stat64(char __user * filename, + struct oldabi_stat64 __user * statbuf) +{ + struct kstat stat; + int error = vfs_stat(filename, &stat); + if (!error) + error = cp_oldabi_stat64(&stat, statbuf); + return error; +} + +asmlinkage long sys_oabi_lstat64(char __user * filename, + struct oldabi_stat64 __user * statbuf) +{ + struct kstat stat; + int error = vfs_lstat(filename, &stat); + if (!error) + error = cp_oldabi_stat64(&stat, statbuf); + return error; +} + +asmlinkage long sys_oabi_fstat64(unsigned long fd, + struct oldabi_stat64 __user * statbuf) +{ + struct kstat stat; + int error = vfs_fstat(fd, &stat); + if (!error) + error = cp_oldabi_stat64(&stat, statbuf); + return error; +} + +struct oabi_flock64 { + short l_type; + short l_whence; + loff_t l_start; + loff_t l_len; + pid_t l_pid; +} __attribute__ ((packed,aligned(4))); + +asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd, + unsigned long arg) +{ + struct oabi_flock64 user; + struct flock64 kernel; + mm_segment_t fs = USER_DS; /* initialized to kill a warning */ + unsigned long local_arg = arg; + int ret; + + switch (cmd) { + case F_GETLK64: + case F_SETLK64: + case F_SETLKW64: + if (copy_from_user(&user, (struct oabi_flock64 __user *)arg, + sizeof(user))) + return -EFAULT; + kernel.l_type = user.l_type; + kernel.l_whence = user.l_whence; + kernel.l_start = user.l_start; + kernel.l_len = user.l_len; + kernel.l_pid = user.l_pid; + local_arg = (unsigned long)&kernel; + fs = get_fs(); + set_fs(KERNEL_DS); + } + + ret = sys_fcntl64(fd, cmd, local_arg); + + switch (cmd) { + case F_GETLK64: + if (!ret) { + user.l_type = kernel.l_type; + user.l_whence = kernel.l_whence; + user.l_start = kernel.l_start; + user.l_len = kernel.l_len; + user.l_pid = kernel.l_pid; + if (copy_to_user((struct oabi_flock64 __user *)arg, + &user, sizeof(user))) + ret = -EFAULT; + } + case F_SETLK64: + case F_SETLKW64: + set_fs(fs); + } + + return ret; +} + +struct oabi_epoll_event { + __u32 events; + __u64 data; +} __attribute__ ((packed,aligned(4))); + +asmlinkage long sys_oabi_epoll_ctl(int epfd, int op, int fd, + struct oabi_epoll_event __user *event) +{ + struct oabi_epoll_event user; + struct epoll_event kernel; + mm_segment_t fs; + long ret; + + if (op == EPOLL_CTL_DEL) + return sys_epoll_ctl(epfd, op, fd, NULL); + if (copy_from_user(&user, event, sizeof(user))) + return -EFAULT; + kernel.events = user.events; + kernel.data = user.data; + fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_epoll_ctl(epfd, op, fd, &kernel); + set_fs(fs); + return ret; +} + +asmlinkage long sys_oabi_epoll_wait(int epfd, + struct oabi_epoll_event __user *events, + int maxevents, int timeout) +{ + struct epoll_event *kbuf; + mm_segment_t fs; + long ret, err, i; + + if (maxevents <= 0 || maxevents > (INT_MAX/sizeof(struct epoll_event))) + return -EINVAL; + kbuf = kmalloc(sizeof(*kbuf) * maxevents, GFP_KERNEL); + if (!kbuf) + return -ENOMEM; + fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_epoll_wait(epfd, kbuf, maxevents, timeout); + set_fs(fs); + err = 0; + for (i = 0; i < ret; i++) { + __put_user_error(kbuf[i].events, &events->events, err); + __put_user_error(kbuf[i].data, &events->data, err); + events++; + } + kfree(kbuf); + return err ? -EFAULT : ret; +} + +struct oabi_sembuf { + unsigned short sem_num; + short sem_op; + short sem_flg; + unsigned short __pad; +}; + +asmlinkage long sys_oabi_semtimedop(int semid, + struct oabi_sembuf __user *tsops, + unsigned nsops, + const struct timespec __user *timeout) +{ + struct sembuf *sops; + struct timespec local_timeout; + long err; + int i; + + if (nsops < 1) + return -EINVAL; + sops = kmalloc(sizeof(*sops) * nsops, GFP_KERNEL); + if (!sops) + return -ENOMEM; + err = 0; + for (i = 0; i < nsops; i++) { + __get_user_error(sops[i].sem_num, &tsops->sem_num, err); + __get_user_error(sops[i].sem_op, &tsops->sem_op, err); + __get_user_error(sops[i].sem_flg, &tsops->sem_flg, err); + tsops++; + } + if (timeout) { + /* copy this as well before changing domain protection */ + err |= copy_from_user(&local_timeout, timeout, sizeof(*timeout)); + timeout = &local_timeout; + } + if (err) { + err = -EFAULT; + } else { + mm_segment_t fs = get_fs(); + set_fs(KERNEL_DS); + err = sys_semtimedop(semid, sops, nsops, timeout); + set_fs(fs); + } + kfree(sops); + return err; +} + +asmlinkage long sys_oabi_semop(int semid, struct oabi_sembuf __user *tsops, + unsigned nsops) +{ + return sys_oabi_semtimedop(semid, tsops, nsops, NULL); +} + +extern asmlinkage int sys_ipc(uint call, int first, int second, int third, + void __user *ptr, long fifth); + +asmlinkage int sys_oabi_ipc(uint call, int first, int second, int third, + void __user *ptr, long fifth) +{ + switch (call & 0xffff) { + case SEMOP: + return sys_oabi_semtimedop(first, + (struct oabi_sembuf __user *)ptr, + second, NULL); + case SEMTIMEDOP: + return sys_oabi_semtimedop(first, + (struct oabi_sembuf __user *)ptr, + second, + (const struct timespec __user *)fifth); + default: + return sys_ipc(call, first, second, third, ptr, fifth); + } +} -- GitLab From dd35afc22b76766e827c9e67ebc4b7bf6e31ecab Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sat, 14 Jan 2006 16:36:12 +0000 Subject: [PATCH 187/465] [ARM] 3110/5: old ABI compat: multi-ABI syscall entry support Patch from Nicolas Pitre This patch adds the required code to support both user space ABIs at the same time. A second syscall table is created to include legacy ABI syscalls that need an ABI compat wrapper. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/kernel/calls.S | 55 ++++++++++++------------ arch/arm/kernel/entry-common.S | 78 +++++++++++++++++++++++++++++++--- arch/arm/kernel/sys_arm.c | 2 + include/asm-arm/unistd.h | 17 +++++--- 4 files changed, 110 insertions(+), 42 deletions(-) diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index 8c0bf04814b..75e6f9a9471 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S @@ -13,7 +13,7 @@ #define NR_syscalls 328 #else -__syscall_start: +100: /* 0 */ .long sys_restart_syscall .long sys_exit .long sys_fork_wrapper @@ -27,7 +27,7 @@ __syscall_start: /* 10 */ .long sys_unlink .long sys_execve_wrapper .long sys_chdir - .long sys_time /* used by libc4 */ + .long OBSOLETE(sys_time) /* used by libc4 */ .long sys_mknod /* 15 */ .long sys_chmod .long sys_lchown16 @@ -36,15 +36,15 @@ __syscall_start: .long sys_lseek /* 20 */ .long sys_getpid .long sys_mount - .long sys_oldumount /* used by libc4 */ + .long OBSOLETE(sys_oldumount) /* used by libc4 */ .long sys_setuid16 .long sys_getuid16 -/* 25 */ .long sys_stime +/* 25 */ .long OBSOLETE(sys_stime) .long sys_ptrace - .long sys_alarm /* used by libc4 */ + .long OBSOLETE(sys_alarm) /* used by libc4 */ .long sys_ni_syscall /* was sys_fstat */ .long sys_pause -/* 30 */ .long sys_utime /* used by libc4 */ +/* 30 */ .long OBSOLETE(sys_utime) /* used by libc4 */ .long sys_ni_syscall /* was sys_stty */ .long sys_ni_syscall /* was sys_getty */ .long sys_access @@ -90,21 +90,21 @@ __syscall_start: .long sys_sigpending .long sys_sethostname /* 75 */ .long sys_setrlimit - .long sys_old_getrlimit /* used by libc4 */ + .long OBSOLETE(sys_old_getrlimit) /* used by libc4 */ .long sys_getrusage .long sys_gettimeofday .long sys_settimeofday /* 80 */ .long sys_getgroups16 .long sys_setgroups16 - .long old_select /* used by libc4 */ + .long OBSOLETE(old_select) /* used by libc4 */ .long sys_symlink .long sys_ni_syscall /* was sys_lstat */ /* 85 */ .long sys_readlink .long sys_uselib .long sys_swapon .long sys_reboot - .long old_readdir /* used by libc4 */ -/* 90 */ .long old_mmap /* used by libc4 */ + .long OBSOLETE(old_readdir) /* used by libc4 */ +/* 90 */ .long OBSOLETE(old_mmap) /* used by libc4 */ .long sys_munmap .long sys_truncate .long sys_ftruncate @@ -116,7 +116,7 @@ __syscall_start: .long sys_statfs /* 100 */ .long sys_fstatfs .long sys_ni_syscall - .long sys_socketcall + .long OBSOLETE(sys_socketcall) .long sys_syslog .long sys_setitimer /* 105 */ .long sys_getitimer @@ -127,11 +127,11 @@ __syscall_start: /* 110 */ .long sys_ni_syscall /* was sys_iopl */ .long sys_vhangup .long sys_ni_syscall - .long sys_syscall /* call a syscall */ + .long OBSOLETE(sys_syscall) /* call a syscall */ .long sys_wait4 /* 115 */ .long sys_swapoff .long sys_sysinfo - .long sys_ipc + .long OBSOLETE(ABI(sys_ipc, sys_oabi_ipc)) .long sys_fsync .long sys_sigreturn_wrapper /* 120 */ .long sys_clone_wrapper @@ -194,8 +194,8 @@ __syscall_start: .long sys_rt_sigtimedwait .long sys_rt_sigqueueinfo .long sys_rt_sigsuspend_wrapper -/* 180 */ .long sys_pread64 - .long sys_pwrite64 +/* 180 */ .long ABI(sys_pread64, sys_oabi_pread64) + .long ABI(sys_pwrite64, sys_oabi_pwrite64) .long sys_chown16 .long sys_getcwd .long sys_capget @@ -207,11 +207,11 @@ __syscall_start: /* 190 */ .long sys_vfork_wrapper .long sys_getrlimit .long sys_mmap2 - .long sys_truncate64 - .long sys_ftruncate64 -/* 195 */ .long sys_stat64 - .long sys_lstat64 - .long sys_fstat64 + .long ABI(sys_truncate64, sys_oabi_truncate64) + .long ABI(sys_ftruncate64, sys_oabi_ftruncate64) +/* 195 */ .long ABI(sys_stat64, sys_oabi_stat64) + .long ABI(sys_lstat64, sys_oabi_lstat64) + .long ABI(sys_fstat64, sys_oabi_fstat64) .long sys_lchown .long sys_getuid /* 200 */ .long sys_getgid @@ -235,11 +235,11 @@ __syscall_start: .long sys_pivot_root .long sys_mincore /* 220 */ .long sys_madvise - .long sys_fcntl64 + .long ABI(sys_fcntl64, sys_oabi_fcntl64) .long sys_ni_syscall /* TUX */ .long sys_ni_syscall .long sys_gettid -/* 225 */ .long sys_readahead +/* 225 */ .long ABI(sys_readahead, sys_oabi_readahead) .long sys_setxattr .long sys_lsetxattr .long sys_fsetxattr @@ -265,8 +265,8 @@ __syscall_start: .long sys_exit_group .long sys_lookup_dcookie /* 250 */ .long sys_epoll_create - .long sys_epoll_ctl - .long sys_epoll_wait + .long ABI(sys_epoll_ctl, sys_oabi_epoll_ctl) + .long ABI(sys_epoll_wait, sys_oabi_epoll_wait) .long sys_remap_file_pages .long sys_ni_syscall /* sys_set_thread_area */ /* 255 */ .long sys_ni_syscall /* sys_get_thread_area */ @@ -312,7 +312,7 @@ __syscall_start: /* 295 */ .long sys_getsockopt .long sys_sendmsg .long sys_recvmsg - .long sys_semop + .long ABI(sys_semop, sys_oabi_semop) .long sys_semget /* 300 */ .long sys_semctl .long sys_msgsnd @@ -326,7 +326,7 @@ __syscall_start: .long sys_add_key /* 310 */ .long sys_request_key .long sys_keyctl - .long sys_semtimedop + .long ABI(sys_semtimedop, sys_oabi_semtimedop) /* vserver */ .long sys_ni_syscall .long sys_ioprio_set /* 315 */ .long sys_ioprio_get @@ -336,9 +336,8 @@ __syscall_start: .long sys_mbind /* 320 */ .long sys_get_mempolicy .long sys_set_mempolicy -__syscall_end: - .rept NR_syscalls - (__syscall_end - __syscall_start) / 4 + .rept NR_syscalls - (. - 100b) / 4 .long sys_ni_syscall .endr #endif diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 59ce1bcec42..8826d9803ae 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -123,23 +123,49 @@ ENTRY(vector_swi) /* * Get the system call number. */ -#if defined(CONFIG_AEABI) - @ syscall number is in scno (r7) already. +#if defined(CONFIG_OABI_COMPAT) + /* + * If we have CONFIG_OABI_COMPAT then we need to look at the swi + * value to determine if it is an EABI or an old ABI call. + */ +#ifdef CONFIG_ARM_THUMB + tst r8, #PSR_T_BIT + movne r10, #0 @ no thumb OABI emulation + ldreq r10, [lr, #-4] @ get SWI instruction +#else + ldr r10, [lr, #-4] @ get SWI instruction + A710( and ip, r10, #0x0f000000 @ check for SWI ) + A710( teq ip, #0x0f000000 ) + A710( bne .Larm710bug ) +#endif + +#elif defined(CONFIG_AEABI) + + /* + * Pure EABI user space always put syscall number into scno (r7). + */ A710( ldr ip, [lr, #-4] @ get SWI instruction ) A710( and ip, ip, #0x0f000000 @ check for SWI ) A710( teq ip, #0x0f000000 ) A710( bne .Larm710bug ) + #elif defined(CONFIG_ARM_THUMB) + + /* Legacy ABI only, possibly thumb mode. */ tst r8, #PSR_T_BIT @ this is SPSR from save_user_regs addne scno, r7, #__NR_SYSCALL_BASE @ put OS number in ldreq scno, [lr, #-4] + #else + + /* Legacy ABI only. */ ldr scno, [lr, #-4] @ get SWI instruction A710( and ip, scno, #0x0f000000 @ check for SWI ) A710( teq ip, #0x0f000000 ) A710( bne .Larm710bug ) + #endif #ifdef CONFIG_ALIGNMENT_TRAP @@ -150,12 +176,24 @@ ENTRY(vector_swi) enable_irq get_thread_info tsk + adr tbl, sys_call_table @ load syscall table pointer ldr ip, [tsk, #TI_FLAGS] @ check for syscall tracing -#ifndef CONFIG_AEABI + +#if defined(CONFIG_OABI_COMPAT) + /* + * If the swi argument is zero, this is an EABI call and we do nothing. + * + * If this is an old ABI call, get the syscall number into scno and + * get the old ABI syscall table address. + */ + bics r10, r10, #0xff000000 + eorne scno, r10, #__NR_OABI_SYSCALL_BASE + ldrne tbl, =sys_oabi_call_table +#elif !defined(CONFIG_AEABI) bic scno, scno, #0xff000000 @ mask off SWI op-code eor scno, scno, #__NR_SYSCALL_BASE @ check OS number #endif - adr tbl, sys_call_table @ load syscall table pointer + stmdb sp!, {r4, r5} @ push fifth and sixth args tst ip, #_TIF_SYSCALL_TRACE @ are we tracing syscalls? bne __sys_trace @@ -199,11 +237,25 @@ __sys_trace_return: .type __cr_alignment, #object __cr_alignment: .word cr_alignment +#endif + .ltorg + +/* + * This is the syscall table declaration for native ABI syscalls. + * With EABI a couple syscalls are obsolete and defined as sys_ni_syscall. + */ +#define ABI(native, compat) native +#ifdef CONFIG_AEABI +#define OBSOLETE(syscall) sys_ni_syscall +#else +#define OBSOLETE(syscall) syscall #endif .type sys_call_table, #object ENTRY(sys_call_table) #include "calls.S" +#undef ABI +#undef OBSOLETE /*============================================================================ * Special system call wrappers @@ -212,8 +264,7 @@ ENTRY(sys_call_table) @ r8 = syscall table .type sys_syscall, #function sys_syscall: -#ifndef CONFIG_AEABI - eor scno, r0, #__NR_SYSCALL_BASE + eor scno, r0, #__NR_OABI_SYSCALL_BASE cmp scno, #__NR_syscall - __NR_SYSCALL_BASE cmpne scno, #NR_syscalls @ check range stmloia sp, {r5, r6} @ shuffle args @@ -222,7 +273,6 @@ sys_syscall: movlo r2, r3 movlo r3, r4 ldrlo pc, [tbl, scno, lsl #2] -#endif b sys_ni_syscall sys_fork_wrapper: @@ -290,6 +340,7 @@ sys_mmap2: #endif #ifdef CONFIG_OABI_COMPAT + /* * These are syscalls with argument register differences */ @@ -318,5 +369,18 @@ sys_oabi_readahead: mov r2, r1 b sys_readahead +/* + * Let's declare a second syscall table for old ABI binaries + * using the compatibility syscall entries. + */ +#define ABI(native, compat) compat +#define OBSOLETE(syscall) syscall + + .type sys_oabi_call_table, #object +ENTRY(sys_oabi_call_table) +#include "calls.S" +#undef ABI +#undef OBSOLETE + #endif diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c index ea569ba482b..a491de2d902 100644 --- a/arch/arm/kernel/sys_arm.c +++ b/arch/arm/kernel/sys_arm.c @@ -147,6 +147,7 @@ asmlinkage int old_select(struct sel_arg_struct __user *arg) return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); } +#if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT) /* * sys_ipc() is the de-multiplexer for the SysV IPC calls.. * @@ -226,6 +227,7 @@ asmlinkage int sys_ipc(uint call, int first, int second, int third, return -ENOSYS; } } +#endif /* Fork a new task - this creates a new program thread. * This is called indirectly via a small wrapper diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h index c9e087fe7e1..77430d6178a 100644 --- a/include/asm-arm/unistd.h +++ b/include/asm-arm/unistd.h @@ -514,22 +514,25 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6 #ifdef __KERNEL__ #define __ARCH_WANT_IPC_PARSE_VERSION -#define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_STAT64 -#define __ARCH_WANT_SYS_ALARM #define __ARCH_WANT_SYS_GETHOSTNAME #define __ARCH_WANT_SYS_PAUSE -#define __ARCH_WANT_SYS_TIME -#define __ARCH_WANT_SYS_UTIME -#define __ARCH_WANT_SYS_SOCKETCALL #define __ARCH_WANT_SYS_GETPGRP #define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE -#define __ARCH_WANT_SYS_OLD_GETRLIMIT -#define __ARCH_WANT_SYS_OLDUMOUNT #define __ARCH_WANT_SYS_SIGPENDING #define __ARCH_WANT_SYS_SIGPROCMASK #define __ARCH_WANT_SYS_RT_SIGACTION + +#if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT) +#define __ARCH_WANT_SYS_TIME +#define __ARCH_WANT_SYS_OLDUMOUNT +#define __ARCH_WANT_SYS_ALARM +#define __ARCH_WANT_SYS_UTIME +#define __ARCH_WANT_SYS_OLD_GETRLIMIT +#define __ARCH_WANT_OLD_READDIR +#define __ARCH_WANT_SYS_SOCKETCALL +#endif #endif #ifdef __KERNEL_SYSCALLS__ -- GitLab From 8993a44cede418940a4921de5dc24d52a9fe8767 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sat, 14 Jan 2006 16:36:50 +0000 Subject: [PATCH 188/465] [ARM] 3111/2: old ABI compat: adjust NWFPE to be operational within an EABI kernel Patch from Nicolas Pitre We need NWFPE if we want to support execution of legacy binaries with an EABI kernel. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/Kconfig | 4 ++-- arch/arm/nwfpe/fpa11.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index ead6172692d..cb66b5745fa 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -602,7 +602,7 @@ comment "At least one emulation must be selected" config FPE_NWFPE bool "NWFPE math emulation" - depends on !AEABI + depends on !AEABI || OABI_COMPAT ---help--- Say Y to include the NWFPE floating point emulator in the kernel. This is necessary to run most binaries. Linux does not currently @@ -626,7 +626,7 @@ config FPE_NWFPE_XP config FPE_FASTFPE bool "FastFPE math emulation (EXPERIMENTAL)" - depends on !AEABI && !CPU_32v3 && EXPERIMENTAL + depends on (!AEABI || OABI_COMPAT) && !CPU_32v3 && EXPERIMENTAL ---help--- Say Y here to include the FAST floating point emulator in the kernel. This is an experimental much faster emulator which now also has full diff --git a/arch/arm/nwfpe/fpa11.h b/arch/arm/nwfpe/fpa11.h index da4c616b6c4..28cd79a451d 100644 --- a/arch/arm/nwfpe/fpa11.h +++ b/arch/arm/nwfpe/fpa11.h @@ -62,7 +62,7 @@ typedef union tagFPREG { #else u32 padding[3]; #endif -} FPREG; +} __attribute__ ((packed,aligned(4))) FPREG; /* * FPA11 device model. @@ -89,7 +89,7 @@ typedef struct tagFPA11 { so we can use it to detect whether this instance of the emulator needs to be initialised. */ -} FPA11; +} __attribute__ ((packed,aligned(4))) FPA11; extern int8 SetRoundingMode(const unsigned int); extern int8 SetRoundingPrecision(const unsigned int); -- GitLab From 6c90c872017773cde70a51432cb28f253451b967 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sat, 14 Jan 2006 16:37:15 +0000 Subject: [PATCH 189/465] [ARM] 3112/1: old ABI compat: config option to turn it on Patch from Nicolas Pitre Enjoy ! Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/Kconfig | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index cb66b5745fa..006f09218ae 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -416,6 +416,23 @@ config AEABI To use this you need GCC version 4.0.0 or later. +config OABI_COMPAT + bool "Allow old ABI binaries to run with this kernel" + depends on AEABI + default y + help + This option preserves the old syscall interface along with the + new (ARM EABI) one. It also provides a compatibility layer to + intercept syscalls that have structure arguments which layout + in memory differs between the legacy ABI and the new ARM EABI + (only for non "thumb" binaries). This option adds a tiny + overhead to all syscalls and produces a slightly larger kernel. + If you know you'll be using only pure EABI user space then you + can say N here. If this option is not selected and you attempt + to execute a legacy ABI binary then the result will be + UNPREDICTABLE (in fact it can be predicted that it won't work + at all). If in doubt say Y. + config ARCH_DISCONTIGMEM_ENABLE bool default (ARCH_LH7A40X && !LH7A40X_CONTIGMEM) -- GitLab From d4054239929479907f20b9d68c905589125ad343 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 4 Jan 2006 13:45:20 +0100 Subject: [PATCH 190/465] [SCSI] sas: fix removal of devices behind expanders We need to iterate over all children when removing and expander, else stale objects will be around after host removal. This fixes the oops Eric Moore saw when removing and reloading mptsas. Also don't try the scsi_remove_target call unless operating on an end device. The current unconditional call is harmless but confusing. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_sas.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 357b52f5f99..e950435a11d 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -687,7 +687,17 @@ sas_rphy_delete(struct sas_rphy *rphy) struct Scsi_Host *shost = dev_to_shost(parent->dev.parent); struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); - scsi_remove_target(dev); + switch (rphy->identify.device_type) { + case SAS_END_DEVICE: + scsi_remove_target(dev); + break; + case SAS_EDGE_EXPANDER_DEVICE: + case SAS_FANOUT_EXPANDER_DEVICE: + device_for_each_child(dev, NULL, do_sas_phy_delete); + break; + default: + break; + } transport_remove_device(dev); device_del(dev); -- GitLab From 776b23a0363d99ca402edc1aba1db8099b747b33 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 6 Jan 2006 18:34:07 +0100 Subject: [PATCH 191/465] [SCSI] always handle REQ_BLOCK_PC requests in common code LLDDs should never see REQ_BLOCK_PC requests, we can handle them just fine in the core code. There is a small behaviour change in that some check in sr's rw_intr are bypassed, but I consider the old behaviour a bug. Mike found this cleanup opportunity and provdided early patches, so all the credit goes to him, even if I redid the patches from scratch beause that was easier than forward-porting the old patches. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 16 +++++++-------- drivers/scsi/sd.c | 42 +++++----------------------------------- drivers/scsi/sr.c | 21 -------------------- drivers/scsi/st.c | 25 ------------------------ include/scsi/scsi_cmnd.h | 1 - 5 files changed, 13 insertions(+), 92 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 00c9bf383e2..3574ba935af 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1212,7 +1212,7 @@ static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk, return -EOPNOTSUPP; } -static void scsi_generic_done(struct scsi_cmnd *cmd) +static void scsi_blk_pc_done(struct scsi_cmnd *cmd) { BUG_ON(!blk_pc_request(cmd->request)); /* @@ -1224,7 +1224,7 @@ static void scsi_generic_done(struct scsi_cmnd *cmd) scsi_io_completion(cmd, cmd->bufflen, 0); } -void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd) +static void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd) { struct request *req = cmd->request; @@ -1241,8 +1241,8 @@ void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd) cmd->transfersize = req->data_len; cmd->allowed = req->retries; cmd->timeout_per_command = req->timeout; + cmd->done = scsi_blk_pc_done; } -EXPORT_SYMBOL_GPL(scsi_setup_blk_pc_cmnd); static int scsi_prep_fn(struct request_queue *q, struct request *req) { @@ -1339,7 +1339,6 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) * happening now. */ if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) { - struct scsi_driver *drv; int ret; /* @@ -1371,16 +1370,17 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) /* * Initialize the actual SCSI command for this request. */ - if (req->rq_disk) { + if (req->flags & REQ_BLOCK_PC) { + scsi_setup_blk_pc_cmnd(cmd); + } else if (req->rq_disk) { + struct scsi_driver *drv; + drv = *(struct scsi_driver **)req->rq_disk->private_data; if (unlikely(!drv->init_command(cmd))) { scsi_release_buffers(cmd); scsi_put_command(cmd); goto kill; } - } else { - scsi_setup_blk_pc_cmnd(cmd); - cmd->done = scsi_generic_done; } } diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index fbd8e1bbad3..930db398d10 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -232,34 +232,12 @@ static void scsi_disk_put(struct scsi_disk *sdkp) **/ static int sd_init_command(struct scsi_cmnd * SCpnt) { - unsigned int this_count, timeout; - struct gendisk *disk; - sector_t block; struct scsi_device *sdp = SCpnt->device; struct request *rq = SCpnt->request; - - timeout = sdp->timeout; - - /* - * SG_IO from block layer already setup, just copy cdb basically - */ - if (blk_pc_request(rq)) { - scsi_setup_blk_pc_cmnd(SCpnt); - if (rq->timeout) - timeout = rq->timeout; - - goto queue; - } - - /* - * we only do REQ_CMD and REQ_BLOCK_PC - */ - if (!blk_fs_request(rq)) - return 0; - - disk = rq->rq_disk; - block = rq->sector; - this_count = SCpnt->request_bufflen >> 9; + struct gendisk *disk = rq->rq_disk; + sector_t block = rq->sector; + unsigned int this_count = SCpnt->request_bufflen >> 9; + unsigned int timeout = sdp->timeout; SCSI_LOG_HLQUEUE(1, printk("sd_init_command: disk=%s, block=%llu, " "count=%d\n", disk->disk_name, @@ -402,8 +380,6 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) SCpnt->transfersize = sdp->sector_size; SCpnt->underflow = this_count << 9; SCpnt->allowed = SD_MAX_RETRIES; - -queue: SCpnt->timeout_per_command = timeout; /* @@ -837,15 +813,7 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt) relatively rare error condition, no care is taken to avoid unnecessary additional work such as memcpy's that could be avoided. */ - - /* - * If SG_IO from block layer then set good_bytes to stop retries; - * else if errors, check them, and if necessary prepare for - * (partial) retries. - */ - if (blk_pc_request(SCpnt->request)) - good_bytes = this_count; - else if (driver_byte(result) != 0 && + if (driver_byte(result) != 0 && sense_valid && !sense_deferred) { switch (sshdr.sense_key) { case MEDIUM_ERROR: diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 18a3b756c63..dd8050392d0 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -238,8 +238,6 @@ static void rw_intr(struct scsi_cmnd * SCpnt) case ILLEGAL_REQUEST: if (!(SCpnt->sense_buffer[0] & 0x90)) break; - if (!blk_fs_request(SCpnt->request)) - break; error_sector = (SCpnt->sense_buffer[3] << 24) | (SCpnt->sense_buffer[4] << 16) | (SCpnt->sense_buffer[5] << 8) | @@ -317,23 +315,6 @@ static int sr_init_command(struct scsi_cmnd * SCpnt) return 0; } - /* - * these are already setup, just copy cdb basically - */ - if (SCpnt->request->flags & REQ_BLOCK_PC) { - scsi_setup_blk_pc_cmnd(SCpnt); - - if (SCpnt->timeout_per_command) - timeout = SCpnt->timeout_per_command; - - goto queue; - } - - if (!(SCpnt->request->flags & REQ_CMD)) { - blk_dump_rq_flags(SCpnt->request, "sr unsup command"); - return 0; - } - /* * we do lazy blocksize switching (when reading XA sectors, * see CDROMREADMODE2 ioctl) @@ -422,8 +403,6 @@ static int sr_init_command(struct scsi_cmnd * SCpnt) */ SCpnt->transfersize = cd->device->sector_size; SCpnt->underflow = this_count << 9; - -queue: SCpnt->allowed = MAX_RETRIES; SCpnt->timeout_per_command = timeout; diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 6e4a36af58c..13b1d3aac26 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -194,7 +194,6 @@ static int sgl_unmap_user_pages(struct scatterlist *, const unsigned int, int); static int st_probe(struct device *); static int st_remove(struct device *); -static int st_init_command(struct scsi_cmnd *); static void do_create_driverfs_files(void); static void do_remove_driverfs_files(void); @@ -207,7 +206,6 @@ static struct scsi_driver st_template = { .probe = st_probe, .remove = st_remove, }, - .init_command = st_init_command, }; static int st_compression(struct scsi_tape *, int); @@ -4181,29 +4179,6 @@ static void scsi_tape_release(struct kref *kref) return; } -static void st_intr(struct scsi_cmnd *SCpnt) -{ - /* - * The caller should be checking the request's errors - * value. - */ - scsi_io_completion(SCpnt, SCpnt->bufflen, 0); -} - -/* - * st_init_command: only called via the scsi_cmd_ioctl (block SG_IO) - * interface for REQ_BLOCK_PC commands. - */ -static int st_init_command(struct scsi_cmnd *SCpnt) -{ - if (!(SCpnt->request->flags & REQ_BLOCK_PC)) - return 0; - - scsi_setup_blk_pc_cmnd(SCpnt); - SCpnt->done = st_intr; - return 1; -} - static int __init init_st(void) { validate_options(); diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 41cfc29be89..7529f4388bb 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -151,6 +151,5 @@ extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t); extern void scsi_put_command(struct scsi_cmnd *); extern void scsi_io_completion(struct scsi_cmnd *, unsigned int, unsigned int); extern void scsi_finish_command(struct scsi_cmnd *cmd); -extern void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd); #endif /* _SCSI_SCSI_CMND_H */ -- GitLab From a09c6311217e8fb079c967427d009fe23f2e420e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 11 Jan 2006 14:28:06 +0100 Subject: [PATCH 192/465] [SCSI] sr: split sr_audio_ioctl into specific helpers split each ioctl handled in sr_audio_ioctl into a function of it's own. This cleans the code up nicely, and allows various places in sr_ioctl to call these helpers directly instead of going through the multiplexer. Signed-off-by: Christoph Hellwig Acked-by: Jens Axboe Signed-off-by: James Bottomley --- drivers/scsi/sr_ioctl.c | 202 ++++++++++++++++++++++------------------ 1 file changed, 111 insertions(+), 91 deletions(-) diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c index 6e45ac3c43c..5d02ff4db6c 100644 --- a/drivers/scsi/sr_ioctl.c +++ b/drivers/scsi/sr_ioctl.c @@ -31,6 +31,79 @@ static int xa_test = 0; module_param(xa_test, int, S_IRUGO | S_IWUSR); +/* primitive to determine whether we need to have GFP_DMA set based on + * the status of the unchecked_isa_dma flag in the host structure */ +#define SR_GFP_DMA(cd) (((cd)->device->host->unchecked_isa_dma) ? GFP_DMA : 0) + + +static int sr_read_tochdr(struct cdrom_device_info *cdi, + struct cdrom_tochdr *tochdr) +{ + struct scsi_cd *cd = cdi->handle; + struct packet_command cgc; + int result; + unsigned char *buffer; + + buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd)); + if (!buffer) + return -ENOMEM; + + memset(&cgc, 0, sizeof(struct packet_command)); + cgc.timeout = IOCTL_TIMEOUT; + cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP; + cgc.cmd[8] = 12; /* LSB of length */ + cgc.buffer = buffer; + cgc.buflen = 12; + cgc.quiet = 1; + cgc.data_direction = DMA_FROM_DEVICE; + + result = sr_do_ioctl(cd, &cgc); + + tochdr->cdth_trk0 = buffer[2]; + tochdr->cdth_trk1 = buffer[3]; + + kfree(buffer); + return result; +} + +static int sr_read_tocentry(struct cdrom_device_info *cdi, + struct cdrom_tocentry *tocentry) +{ + struct scsi_cd *cd = cdi->handle; + struct packet_command cgc; + int result; + unsigned char *buffer; + + buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd)); + if (!buffer) + return -ENOMEM; + + memset(&cgc, 0, sizeof(struct packet_command)); + cgc.timeout = IOCTL_TIMEOUT; + cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP; + cgc.cmd[1] |= (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0; + cgc.cmd[6] = tocentry->cdte_track; + cgc.cmd[8] = 12; /* LSB of length */ + cgc.buffer = buffer; + cgc.buflen = 12; + cgc.data_direction = DMA_FROM_DEVICE; + + result = sr_do_ioctl(cd, &cgc); + + tocentry->cdte_ctrl = buffer[5] & 0xf; + tocentry->cdte_adr = buffer[5] >> 4; + tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04) ? 1 : 0; + if (tocentry->cdte_format == CDROM_MSF) { + tocentry->cdte_addr.msf.minute = buffer[9]; + tocentry->cdte_addr.msf.second = buffer[10]; + tocentry->cdte_addr.msf.frame = buffer[11]; + } else + tocentry->cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8) + + buffer[10]) << 8) + buffer[11]; + + kfree(buffer); + return result; +} #define IOCTL_RETRIES 3 @@ -45,7 +118,8 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti struct packet_command cgc; int ntracks, ret; - if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCHDR, &tochdr))) + ret = sr_read_tochdr(cdi, &tochdr); + if (ret) return ret; ntracks = tochdr.cdth_trk1 - tochdr.cdth_trk0 + 1; @@ -60,9 +134,11 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti trk1_te.cdte_track = ti->cdti_trk1; trk1_te.cdte_format = CDROM_MSF; - if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &trk0_te))) + ret = sr_read_tocentry(cdi, &trk0_te); + if (ret) return ret; - if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &trk1_te))) + ret = sr_read_tocentry(cdi, &trk1_te); + if (ret) return ret; memset(&cgc, 0, sizeof(struct packet_command)); @@ -78,6 +154,30 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti return sr_do_ioctl(cdi->handle, &cgc); } +static int sr_play_trkind(struct cdrom_device_info *cdi, + struct cdrom_ti *ti) + +{ + struct scsi_cd *cd = cdi->handle; + struct packet_command cgc; + int result; + + memset(&cgc, 0, sizeof(struct packet_command)); + cgc.timeout = IOCTL_TIMEOUT; + cgc.cmd[0] = GPCMD_PLAYAUDIO_TI; + cgc.cmd[4] = ti->cdti_trk0; + cgc.cmd[5] = ti->cdti_ind0; + cgc.cmd[7] = ti->cdti_trk1; + cgc.cmd[8] = ti->cdti_ind1; + cgc.data_direction = DMA_NONE; + + result = sr_do_ioctl(cd, &cgc); + if (result == -EDRIVE_CANT_DO_THIS) + result = sr_fake_playtrkind(cdi, ti); + + return result; +} + /* We do our own retries because we want to know what the specific error code is. Normally the UNIT_ATTENTION code will automatically clear after one error */ @@ -229,13 +329,14 @@ int sr_disk_status(struct cdrom_device_info *cdi) int i, rc, have_datatracks = 0; /* look for data tracks */ - if (0 != (rc = sr_audio_ioctl(cdi, CDROMREADTOCHDR, &toc_h))) + rc = sr_read_tochdr(cdi, &toc_h); + if (rc) return (rc == -ENOMEDIUM) ? CDS_NO_DISC : CDS_NO_INFO; for (i = toc_h.cdth_trk0; i <= toc_h.cdth_trk1; i++) { toc_e.cdte_track = i; toc_e.cdte_format = CDROM_LBA; - if (sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &toc_e)) + if (sr_read_tocentry(cdi, &toc_e)) return CDS_NO_INFO; if (toc_e.cdte_ctrl & CDROM_DATA_TRACK) { have_datatracks = 1; @@ -262,10 +363,6 @@ int sr_get_last_session(struct cdrom_device_info *cdi, return 0; } -/* primitive to determine whether we need to have GFP_DMA set based on - * the status of the unchecked_isa_dma flag in the host structure */ -#define SR_GFP_DMA(cd) (((cd)->device->host->unchecked_isa_dma) ? GFP_DMA : 0) - int sr_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn) { Scsi_CD *cd = cdi->handle; @@ -329,93 +426,16 @@ int sr_select_speed(struct cdrom_device_info *cdi, int speed) int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg) { - Scsi_CD *cd = cdi->handle; - struct packet_command cgc; - int result; - unsigned char *buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd)); - - if (!buffer) - return -ENOMEM; - - memset(&cgc, 0, sizeof(struct packet_command)); - cgc.timeout = IOCTL_TIMEOUT; - switch (cmd) { case CDROMREADTOCHDR: - { - struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg; - - cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP; - cgc.cmd[8] = 12; /* LSB of length */ - cgc.buffer = buffer; - cgc.buflen = 12; - cgc.quiet = 1; - cgc.data_direction = DMA_FROM_DEVICE; - - result = sr_do_ioctl(cd, &cgc); - - tochdr->cdth_trk0 = buffer[2]; - tochdr->cdth_trk1 = buffer[3]; - - break; - } - + return sr_read_tochdr(cdi, arg); case CDROMREADTOCENTRY: - { - struct cdrom_tocentry *tocentry = (struct cdrom_tocentry *) arg; - - cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP; - cgc.cmd[1] |= (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0; - cgc.cmd[6] = tocentry->cdte_track; - cgc.cmd[8] = 12; /* LSB of length */ - cgc.buffer = buffer; - cgc.buflen = 12; - cgc.data_direction = DMA_FROM_DEVICE; - - result = sr_do_ioctl(cd, &cgc); - - tocentry->cdte_ctrl = buffer[5] & 0xf; - tocentry->cdte_adr = buffer[5] >> 4; - tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04) ? 1 : 0; - if (tocentry->cdte_format == CDROM_MSF) { - tocentry->cdte_addr.msf.minute = buffer[9]; - tocentry->cdte_addr.msf.second = buffer[10]; - tocentry->cdte_addr.msf.frame = buffer[11]; - } else - tocentry->cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8) - + buffer[10]) << 8) + buffer[11]; - - break; - } - - case CDROMPLAYTRKIND: { - struct cdrom_ti* ti = (struct cdrom_ti*)arg; - - cgc.cmd[0] = GPCMD_PLAYAUDIO_TI; - cgc.cmd[4] = ti->cdti_trk0; - cgc.cmd[5] = ti->cdti_ind0; - cgc.cmd[7] = ti->cdti_trk1; - cgc.cmd[8] = ti->cdti_ind1; - cgc.data_direction = DMA_NONE; - - result = sr_do_ioctl(cd, &cgc); - if (result == -EDRIVE_CANT_DO_THIS) - result = sr_fake_playtrkind(cdi, ti); - - break; - } - + return sr_read_tocentry(cdi, arg); + case CDROMPLAYTRKIND: + return sr_play_trkind(cdi, arg); default: - result = -EINVAL; + return -EINVAL; } - -#if 0 - if (result) - printk("DEBUG: sr_audio: result for ioctl %x: %x\n", cmd, result); -#endif - - kfree(buffer); - return result; } /* ----------------------------------------------------------------------- -- GitLab From 6b7281d0a0f8f99d39808088a036459f6f7906a6 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Fri, 13 Jan 2006 02:16:54 +0100 Subject: [PATCH 193/465] [SCSI] fc transport: add permanent_port_name fc_host attribute Add fc_host attribute permanent_port_name which is used to show the port name of the primary port - the port that initially logged into the fabric. For a virtual port (registered via the primary port with FDISC command) it is useful to know not only its (virtual) port name but also the permanent port name. Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_fc.c | 4 ++++ include/scsi/scsi_transport_fc.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 685b997306c..625f4a664d0 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -295,6 +295,7 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev, */ fc_host_node_name(shost) = -1; fc_host_port_name(shost) = -1; + fc_host_permanent_port_name(shost) = -1; fc_host_supported_classes(shost) = FC_COS_UNSPECIFIED; memset(fc_host_supported_fc4s(shost), 0, sizeof(fc_host_supported_fc4s(shost))); @@ -795,6 +796,8 @@ static FC_CLASS_DEVICE_ATTR(host, supported_speeds, S_IRUGO, fc_private_host_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long); fc_private_host_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long); +fc_private_host_rd_attr_cast(permanent_port_name, "0x%llx\n", 20, + unsigned long long); fc_private_host_rd_attr(symbolic_name, "%s\n", (FC_SYMBOLIC_NAME_SIZE +1)); fc_private_host_rd_attr(maxframe_size, "%u bytes\n", 20); fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1)); @@ -1160,6 +1163,7 @@ fc_attach_transport(struct fc_function_template *ft) count=0; SETUP_HOST_ATTRIBUTE_RD(node_name); SETUP_HOST_ATTRIBUTE_RD(port_name); + SETUP_HOST_ATTRIBUTE_RD(permanent_port_name); SETUP_HOST_ATTRIBUTE_RD(supported_classes); SETUP_HOST_ATTRIBUTE_RD(supported_fc4s); SETUP_HOST_ATTRIBUTE_RD(symbolic_name); diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index 394f14a5b7c..cf3fec8be1e 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h @@ -303,6 +303,7 @@ struct fc_host_attrs { /* Fixed Attributes */ u64 node_name; u64 port_name; + u64 permanent_port_name; u32 supported_classes; u8 supported_fc4s[FC_FC4_LIST_SIZE]; char symbolic_name[FC_SYMBOLIC_NAME_SIZE]; @@ -338,6 +339,8 @@ struct fc_host_attrs { (((struct fc_host_attrs *)(x)->shost_data)->node_name) #define fc_host_port_name(x) \ (((struct fc_host_attrs *)(x)->shost_data)->port_name) +#define fc_host_permanent_port_name(x) \ + (((struct fc_host_attrs *)(x)->shost_data)->permanent_port_name) #define fc_host_supported_classes(x) \ (((struct fc_host_attrs *)(x)->shost_data)->supported_classes) #define fc_host_supported_fc4s(x) \ @@ -426,6 +429,7 @@ struct fc_function_template { /* host fixed attributes */ unsigned long show_host_node_name:1; unsigned long show_host_port_name:1; + unsigned long show_host_permanent_port_name:1; unsigned long show_host_supported_classes:1; unsigned long show_host_supported_fc4s:1; unsigned long show_host_symbolic_name:1; -- GitLab From 9eb69aff79264b5f35e41922df20a488c67e9ee2 Mon Sep 17 00:00:00 2001 From: Maxim Shchetynin Date: Thu, 5 Jan 2006 09:56:47 +0100 Subject: [PATCH 194/465] [SCSI] zfcp: handle unsolicited status notification lost Handle unsolicited adapter status that informs about loss of previous unsolicited status notification(s). Signed-off-by: Maxim Shchetynin Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_fsf.c | 35 +++++++++++++++++++++++++++++++++++ drivers/s390/scsi/zfcp_fsf.h | 12 ++++++++++++ 2 files changed, 47 insertions(+) diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 59587951c84..bf859c9982d 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -964,6 +964,40 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) | ZFCP_STATUS_COMMON_ERP_FAILED); break; + case FSF_STATUS_READ_NOTIFICATION_LOST: + ZFCP_LOG_NORMAL("Unsolicited status notification(s) lost: " + "adapter %s%s%s%s%s%s%s%s%s\n", + zfcp_get_busid_by_adapter(adapter), + (status_buffer->status_subtype & + FSF_STATUS_READ_SUB_INCOMING_ELS) ? + ", incoming ELS" : "", + (status_buffer->status_subtype & + FSF_STATUS_READ_SUB_SENSE_DATA) ? + ", sense data" : "", + (status_buffer->status_subtype & + FSF_STATUS_READ_SUB_LINK_STATUS) ? + ", link status change" : "", + (status_buffer->status_subtype & + FSF_STATUS_READ_SUB_PORT_CLOSED) ? + ", port close" : "", + (status_buffer->status_subtype & + FSF_STATUS_READ_SUB_BIT_ERROR_THRESHOLD) ? + ", bit error exception" : "", + (status_buffer->status_subtype & + FSF_STATUS_READ_SUB_ACT_UPDATED) ? + ", ACT update" : "", + (status_buffer->status_subtype & + FSF_STATUS_READ_SUB_ACT_HARDENED) ? + ", ACT hardening" : "", + (status_buffer->status_subtype & + FSF_STATUS_READ_SUB_FEATURE_UPDATE_ALERT) ? + ", adapter feature change" : ""); + + if (status_buffer->status_subtype & + FSF_STATUS_READ_SUB_ACT_UPDATED) + zfcp_erp_adapter_access_changed(adapter); + break; + case FSF_STATUS_READ_CFDC_UPDATED: ZFCP_LOG_NORMAL("CFDC has been updated on the adapter %s\n", zfcp_get_busid_by_adapter(adapter)); @@ -1954,6 +1988,7 @@ zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) erp_action->fsf_req->qtcb->bottom.config.feature_selection = FSF_FEATURE_CFDC | FSF_FEATURE_LUN_SHARING | + FSF_FEATURE_NOTIFICATION_LOST | FSF_FEATURE_UPDATE_ALERT; /* start QDIO request for this FSF request */ diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h index 48719f05595..39475dbcb61 100644 --- a/drivers/s390/scsi/zfcp_fsf.h +++ b/drivers/s390/scsi/zfcp_fsf.h @@ -166,6 +166,7 @@ #define FSF_STATUS_READ_BIT_ERROR_THRESHOLD 0x00000004 #define FSF_STATUS_READ_LINK_DOWN 0x00000005 #define FSF_STATUS_READ_LINK_UP 0x00000006 +#define FSF_STATUS_READ_NOTIFICATION_LOST 0x00000009 #define FSF_STATUS_READ_CFDC_UPDATED 0x0000000A #define FSF_STATUS_READ_CFDC_HARDENED 0x0000000B #define FSF_STATUS_READ_FEATURE_UPDATE_ALERT 0x0000000C @@ -179,6 +180,16 @@ #define FSF_STATUS_READ_SUB_FDISC_FAILED 0x00000001 #define FSF_STATUS_READ_SUB_FIRMWARE_UPDATE 0x00000002 +/* status subtypes for unsolicited status notification lost */ +#define FSF_STATUS_READ_SUB_INCOMING_ELS 0x00000001 +#define FSF_STATUS_READ_SUB_SENSE_DATA 0x00000002 +#define FSF_STATUS_READ_SUB_LINK_STATUS 0x00000004 +#define FSF_STATUS_READ_SUB_PORT_CLOSED 0x00000008 +#define FSF_STATUS_READ_SUB_BIT_ERROR_THRESHOLD 0x00000010 +#define FSF_STATUS_READ_SUB_ACT_UPDATED 0x00000020 +#define FSF_STATUS_READ_SUB_ACT_HARDENED 0x00000040 +#define FSF_STATUS_READ_SUB_FEATURE_UPDATE_ALERT 0x00000080 + /* status subtypes for CFDC */ #define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE 0x00000002 #define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2 0x0000000F @@ -211,6 +222,7 @@ /* channel features */ #define FSF_FEATURE_CFDC 0x00000002 #define FSF_FEATURE_LUN_SHARING 0x00000004 +#define FSF_FEATURE_NOTIFICATION_LOST 0x00000008 #define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010 #define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020 #define FSF_FEATURE_UPDATE_ALERT 0x00000100 -- GitLab From f6cd94b126aa78ebaa21075df3b9577fbf995968 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Thu, 5 Jan 2006 09:59:34 +0100 Subject: [PATCH 195/465] [SCSI] zfcp: transport class adaptations Added host stats, removed superfluous get_starget_ functions, removed some attributes from zfcp specific sysfs tree (e.g. scsi_host_no, scsi_lun, wwnn and d_id). Host stats are given for the physical adapter port not for the virtual adapter. Reset stats is implemented in the device driver. Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_aux.c | 2 + drivers/s390/scsi/zfcp_def.h | 3 + drivers/s390/scsi/zfcp_scsi.c | 185 +++++++++++++++++-------- drivers/s390/scsi/zfcp_sysfs_adapter.c | 4 - drivers/s390/scsi/zfcp_sysfs_port.c | 4 - drivers/s390/scsi/zfcp_sysfs_unit.c | 2 - 6 files changed, 136 insertions(+), 64 deletions(-) diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 5e84c5aa777..167fef39d8a 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -1125,6 +1125,8 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter) zfcp_free_low_mem_buffers(adapter); /* free memory of adapter data structure and queues */ zfcp_qdio_free_queues(adapter); + kfree(adapter->fc_stats); + kfree(adapter->stats_reset_data); ZFCP_LOG_TRACE("freeing adapter structure\n"); kfree(adapter); out: diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index d81b737d68c..3785b3c98a5 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -978,6 +978,9 @@ struct zfcp_adapter { struct zfcp_adapter_mempool pool; /* Adapter memory pools */ struct qdio_initialize qdio_init_data; /* for qdio_establish */ struct device generic_services; /* directory for WKA ports */ + struct fc_host_statistics *fc_stats; + struct fsf_qtcb_bottom_port *stats_reset_data; + unsigned long stats_reset; }; /* diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 66608d13a63..5ca0992e97f 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -49,8 +49,6 @@ static int zfcp_task_management_function(struct zfcp_unit *, u8, static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, scsi_id_t, scsi_lun_t); -static struct zfcp_port *zfcp_port_lookup(struct zfcp_adapter *, int, - scsi_id_t); static struct device_attribute *zfcp_sysfs_sdev_attrs[]; @@ -406,18 +404,6 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id, return retval; } -static struct zfcp_port * -zfcp_port_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id) -{ - struct zfcp_port *port; - - list_for_each_entry(port, &adapter->port_list_head, list) { - if (port->rport && (id == port->rport->scsi_target_id)) - return port; - } - return (struct zfcp_port *) NULL; -} - /** * zfcp_scsi_eh_abort_handler - abort the specified SCSI command * @scpnt: pointer to scsi_cmnd to be aborted @@ -731,61 +717,148 @@ zfcp_fsf_start_scsi_er_timer(struct zfcp_adapter *adapter) /* * Support functions for FC transport class */ -static void -zfcp_get_port_id(struct scsi_target *starget) +static struct fc_host_statistics* +zfcp_init_fc_host_stats(struct zfcp_adapter *adapter) { - struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); - struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0]; - struct zfcp_port *port; - unsigned long flags; + struct fc_host_statistics *fc_stats; - read_lock_irqsave(&zfcp_data.config_lock, flags); - port = zfcp_port_lookup(adapter, starget->channel, starget->id); - if (port) - fc_starget_port_id(starget) = port->d_id; - else - fc_starget_port_id(starget) = -1; - read_unlock_irqrestore(&zfcp_data.config_lock, flags); + if (!adapter->fc_stats) { + fc_stats = kmalloc(sizeof(*fc_stats), GFP_KERNEL); + if (!fc_stats) + return NULL; + adapter->fc_stats = fc_stats; /* freed in adater_dequeue */ + } + memset(adapter->fc_stats, 0, sizeof(*adapter->fc_stats)); + return adapter->fc_stats; } static void -zfcp_get_port_name(struct scsi_target *starget) +zfcp_adjust_fc_host_stats(struct fc_host_statistics *fc_stats, + struct fsf_qtcb_bottom_port *data, + struct fsf_qtcb_bottom_port *old) { - struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); - struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0]; - struct zfcp_port *port; - unsigned long flags; + fc_stats->seconds_since_last_reset = data->seconds_since_last_reset - + old->seconds_since_last_reset; + fc_stats->tx_frames = data->tx_frames - old->tx_frames; + fc_stats->tx_words = data->tx_words - old->tx_words; + fc_stats->rx_frames = data->rx_frames - old->rx_frames; + fc_stats->rx_words = data->rx_words - old->rx_words; + fc_stats->lip_count = data->lip - old->lip; + fc_stats->nos_count = data->nos - old->nos; + fc_stats->error_frames = data->error_frames - old->error_frames; + fc_stats->dumped_frames = data->dumped_frames - old->dumped_frames; + fc_stats->link_failure_count = data->link_failure - old->link_failure; + fc_stats->loss_of_sync_count = data->loss_of_sync - old->loss_of_sync; + fc_stats->loss_of_signal_count = data->loss_of_signal - + old->loss_of_signal; + fc_stats->prim_seq_protocol_err_count = data->psp_error_counts - + old->psp_error_counts; + fc_stats->invalid_tx_word_count = data->invalid_tx_words - + old->invalid_tx_words; + fc_stats->invalid_crc_count = data->invalid_crcs - old->invalid_crcs; + fc_stats->fcp_input_requests = data->input_requests - + old->input_requests; + fc_stats->fcp_output_requests = data->output_requests - + old->output_requests; + fc_stats->fcp_control_requests = data->control_requests - + old->control_requests; + fc_stats->fcp_input_megabytes = data->input_mb - old->input_mb; + fc_stats->fcp_output_megabytes = data->output_mb - old->output_mb; +} - read_lock_irqsave(&zfcp_data.config_lock, flags); - port = zfcp_port_lookup(adapter, starget->channel, starget->id); - if (port) - fc_starget_port_name(starget) = port->wwpn; - else - fc_starget_port_name(starget) = -1; - read_unlock_irqrestore(&zfcp_data.config_lock, flags); +static void +zfcp_set_fc_host_stats(struct fc_host_statistics *fc_stats, + struct fsf_qtcb_bottom_port *data) +{ + fc_stats->seconds_since_last_reset = data->seconds_since_last_reset; + fc_stats->tx_frames = data->tx_frames; + fc_stats->tx_words = data->tx_words; + fc_stats->rx_frames = data->rx_frames; + fc_stats->rx_words = data->rx_words; + fc_stats->lip_count = data->lip; + fc_stats->nos_count = data->nos; + fc_stats->error_frames = data->error_frames; + fc_stats->dumped_frames = data->dumped_frames; + fc_stats->link_failure_count = data->link_failure; + fc_stats->loss_of_sync_count = data->loss_of_sync; + fc_stats->loss_of_signal_count = data->loss_of_signal; + fc_stats->prim_seq_protocol_err_count = data->psp_error_counts; + fc_stats->invalid_tx_word_count = data->invalid_tx_words; + fc_stats->invalid_crc_count = data->invalid_crcs; + fc_stats->fcp_input_requests = data->input_requests; + fc_stats->fcp_output_requests = data->output_requests; + fc_stats->fcp_control_requests = data->control_requests; + fc_stats->fcp_input_megabytes = data->input_mb; + fc_stats->fcp_output_megabytes = data->output_mb; +} + +/** + * zfcp_get_fc_host_stats - provide fc_host_statistics for scsi_transport_fc + * + * assumption: scsi_transport_fc synchronizes calls of + * get_fc_host_stats and reset_fc_host_stats + * (XXX to be checked otherwise introduce locking) + */ +static struct fc_host_statistics * +zfcp_get_fc_host_stats(struct Scsi_Host *shost) +{ + struct zfcp_adapter *adapter; + struct fc_host_statistics *fc_stats; + struct fsf_qtcb_bottom_port *data; + int ret; + + adapter = (struct zfcp_adapter *)shost->hostdata[0]; + fc_stats = zfcp_init_fc_host_stats(adapter); + if (!fc_stats) + return NULL; + + data = kmalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return NULL; + memset(data, 0, sizeof(*data)); + + ret = zfcp_fsf_exchange_port_data(NULL, adapter, data); + if (ret) { + kfree(data); + return NULL; /* XXX return zeroed fc_stats? */ + } + + if (adapter->stats_reset && + ((jiffies/HZ - adapter->stats_reset) < + data->seconds_since_last_reset)) { + zfcp_adjust_fc_host_stats(fc_stats, data, + adapter->stats_reset_data); + } else + zfcp_set_fc_host_stats(fc_stats, data); + + kfree(data); + return fc_stats; } static void -zfcp_get_node_name(struct scsi_target *starget) +zfcp_reset_fc_host_stats(struct Scsi_Host *shost) { - struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); - struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0]; - struct zfcp_port *port; - unsigned long flags; + struct zfcp_adapter *adapter; + struct fsf_qtcb_bottom_port *data, *old_data; + int ret; - read_lock_irqsave(&zfcp_data.config_lock, flags); - port = zfcp_port_lookup(adapter, starget->channel, starget->id); - if (port) - fc_starget_node_name(starget) = port->wwnn; - else - fc_starget_node_name(starget) = -1; - read_unlock_irqrestore(&zfcp_data.config_lock, flags); + adapter = (struct zfcp_adapter *)shost->hostdata[0]; + data = kmalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return; + memset(data, 0, sizeof(*data)); + + ret = zfcp_fsf_exchange_port_data(NULL, adapter, data); + if (ret == 0) { + adapter->stats_reset = jiffies/HZ; + old_data = adapter->stats_reset_data; + adapter->stats_reset_data = data; /* finally freed in + adater_dequeue */ + kfree(old_data); + } } struct fc_function_template zfcp_transport_functions = { - .get_starget_port_id = zfcp_get_port_id, - .get_starget_port_name = zfcp_get_port_name, - .get_starget_node_name = zfcp_get_node_name, .show_starget_port_id = 1, .show_starget_port_name = 1, .show_starget_node_name = 1, @@ -795,6 +868,10 @@ struct fc_function_template zfcp_transport_functions = { .show_host_supported_classes = 1, .show_host_maxframe_size = 1, .show_host_serial_number = 1, + .get_fc_host_stats = zfcp_get_fc_host_stats, + .reset_fc_host_stats = zfcp_reset_fc_host_stats, + /* no functions registered for following dynamic attributes but + directly set by LLDD */ .show_host_speed = 1, .show_host_port_id = 1, }; diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c index 0cd435280e7..c85df9c016a 100644 --- a/drivers/s390/scsi/zfcp_sysfs_adapter.c +++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c @@ -69,12 +69,10 @@ ZFCP_DEFINE_ADAPTER_ATTR(physical_wwpn, "0x%016llx\n", adapter->physical_wwpn); ZFCP_DEFINE_ADAPTER_ATTR(physical_s_id, "0x%06x\n", adapter->physical_s_id); ZFCP_DEFINE_ADAPTER_ATTR(card_version, "0x%04x\n", adapter->hydra_version); ZFCP_DEFINE_ADAPTER_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version); -ZFCP_DEFINE_ADAPTER_ATTR(fc_service_class, "%d\n", adapter->fc_service_class); ZFCP_DEFINE_ADAPTER_ATTR(fc_topology, "%s\n", fc_topologies[adapter->fc_topology]); ZFCP_DEFINE_ADAPTER_ATTR(hardware_version, "0x%08x\n", adapter->hardware_version); -ZFCP_DEFINE_ADAPTER_ATTR(scsi_host_no, "0x%x\n", adapter->scsi_host_no); ZFCP_DEFINE_ADAPTER_ATTR(in_recovery, "%d\n", atomic_test_mask (ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status)); @@ -259,9 +257,7 @@ static struct attribute *zfcp_adapter_attrs[] = { &dev_attr_physical_s_id.attr, &dev_attr_card_version.attr, &dev_attr_lic_version.attr, - &dev_attr_fc_service_class.attr, &dev_attr_fc_topology.attr, - &dev_attr_scsi_host_no.attr, &dev_attr_status.attr, &dev_attr_hardware_version.attr, NULL diff --git a/drivers/s390/scsi/zfcp_sysfs_port.c b/drivers/s390/scsi/zfcp_sysfs_port.c index c55e82d91de..3924eb38805 100644 --- a/drivers/s390/scsi/zfcp_sysfs_port.c +++ b/drivers/s390/scsi/zfcp_sysfs_port.c @@ -65,8 +65,6 @@ static ssize_t zfcp_sysfs_port_##_name##_show(struct device *dev, struct device_ static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_port_##_name##_show, NULL); ZFCP_DEFINE_PORT_ATTR(status, "0x%08x\n", atomic_read(&port->status)); -ZFCP_DEFINE_PORT_ATTR(wwnn, "0x%016llx\n", port->wwnn); -ZFCP_DEFINE_PORT_ATTR(d_id, "0x%06x\n", port->d_id); ZFCP_DEFINE_PORT_ATTR(in_recovery, "%d\n", atomic_test_mask (ZFCP_STATUS_COMMON_ERP_INUSE, &port->status)); ZFCP_DEFINE_PORT_ATTR(access_denied, "%d\n", atomic_test_mask @@ -245,8 +243,6 @@ static struct attribute *zfcp_port_common_attrs[] = { &dev_attr_failed.attr, &dev_attr_in_recovery.attr, &dev_attr_status.attr, - &dev_attr_wwnn.attr, - &dev_attr_d_id.attr, &dev_attr_access_denied.attr, NULL }; diff --git a/drivers/s390/scsi/zfcp_sysfs_unit.c b/drivers/s390/scsi/zfcp_sysfs_unit.c index 0556642c9e1..2f50815f65c 100644 --- a/drivers/s390/scsi/zfcp_sysfs_unit.c +++ b/drivers/s390/scsi/zfcp_sysfs_unit.c @@ -65,7 +65,6 @@ static ssize_t zfcp_sysfs_unit_##_name##_show(struct device *dev, struct device_ static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_unit_##_name##_show, NULL); ZFCP_DEFINE_UNIT_ATTR(status, "0x%08x\n", atomic_read(&unit->status)); -ZFCP_DEFINE_UNIT_ATTR(scsi_lun, "0x%x\n", unit->scsi_lun); ZFCP_DEFINE_UNIT_ATTR(in_recovery, "%d\n", atomic_test_mask (ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status)); ZFCP_DEFINE_UNIT_ATTR(access_denied, "%d\n", atomic_test_mask @@ -138,7 +137,6 @@ static DEVICE_ATTR(failed, S_IWUSR | S_IRUGO, zfcp_sysfs_unit_failed_show, zfcp_sysfs_unit_failed_store); static struct attribute *zfcp_unit_attrs[] = { - &dev_attr_scsi_lun.attr, &dev_attr_failed.attr, &dev_attr_in_recovery.attr, &dev_attr_status.attr, -- GitLab From ad757cdfd2a40c9d5310d00f24427525788341cd Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Fri, 13 Jan 2006 02:26:11 +0100 Subject: [PATCH 196/465] [SCSI] zfcp: transport class adaptations II Replaced zfcp adapter attributes with fc_host attributes: fc_topology by port_type, physical_wwpn by permanent_port_name. Make use of fc_host attribute supported_speeds. Removed zfcp adapter attribute physical_s_id. Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_def.h | 1 - drivers/s390/scsi/zfcp_erp.c | 2 +- drivers/s390/scsi/zfcp_fsf.c | 49 +++++++++++++------------- drivers/s390/scsi/zfcp_fsf.h | 1 - drivers/s390/scsi/zfcp_scsi.c | 3 ++ drivers/s390/scsi/zfcp_sysfs_adapter.c | 11 ------ 6 files changed, 29 insertions(+), 38 deletions(-) diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 3785b3c98a5..9bb511083a2 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -921,7 +921,6 @@ struct zfcp_adapter { u32 physical_s_id; /* local FC port ID */ struct ccw_device *ccw_device; /* S/390 ccw device */ u8 fc_service_class; - u32 fc_topology; /* FC topology */ u32 hydra_version; /* Hydra version */ u32 fsf_lic_version; u32 adapter_features; /* FCP channel features */ diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index ee7314d8c2d..7bdb00b5aeb 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -2613,7 +2613,7 @@ zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action) case ZFCP_ERP_STEP_UNINITIALIZED: case ZFCP_ERP_STEP_PHYS_PORT_CLOSING: case ZFCP_ERP_STEP_PORT_CLOSING: - if (adapter->fc_topology == FSF_TOPO_P2P) { + if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) { if (port->wwpn != adapter->peer_wwpn) { ZFCP_LOG_NORMAL("Failed to open port 0x%016Lx " "on adapter %s.\nPeer WWPN " diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index bf859c9982d..cbfab09899c 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -2043,27 +2043,30 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) fc_host_port_id(shost) = bottom->s_id & ZFCP_DID_MASK; fc_host_speed(shost) = bottom->fc_link_speed; fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3; - adapter->fc_topology = bottom->fc_topology; adapter->hydra_version = bottom->adapter_type; - if (adapter->physical_wwpn == 0) - adapter->physical_wwpn = fc_host_port_name(shost); - if (adapter->physical_s_id == 0) - adapter->physical_s_id = fc_host_port_id(shost); + if (fc_host_permanent_port_name(shost) == -1) + fc_host_permanent_port_name(shost) = + fc_host_port_name(shost); + if (bottom->fc_topology == FSF_TOPO_P2P) { + adapter->peer_d_id = bottom->peer_d_id & ZFCP_DID_MASK; + adapter->peer_wwpn = bottom->plogi_payload.wwpn; + adapter->peer_wwnn = bottom->plogi_payload.wwnn; + fc_host_port_type(shost) = FC_PORTTYPE_PTP; + } else if (bottom->fc_topology == FSF_TOPO_FABRIC) + fc_host_port_type(shost) = FC_PORTTYPE_NPORT; + else if (bottom->fc_topology == FSF_TOPO_AL) + fc_host_port_type(shost) = FC_PORTTYPE_NLPORT; + else + fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN; } else { fc_host_node_name(shost) = 0; fc_host_port_name(shost) = 0; fc_host_port_id(shost) = 0; fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; - adapter->fc_topology = 0; + fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN; adapter->hydra_version = 0; } - if (adapter->fc_topology == FSF_TOPO_P2P) { - adapter->peer_d_id = bottom->peer_d_id & ZFCP_DID_MASK; - adapter->peer_wwpn = bottom->plogi_payload.wwpn; - adapter->peer_wwnn = bottom->plogi_payload.wwnn; - } - if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) { adapter->hardware_version = bottom->hardware_version; memcpy(fc_host_serial_number(shost), bottom->serial_number, @@ -2132,8 +2135,8 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) if (zfcp_fsf_exchange_config_evaluate(fsf_req, 1)) return -EIO; - switch (adapter->fc_topology) { - case FSF_TOPO_P2P: + switch (fc_host_port_type(adapter->scsi_host)) { + case FC_PORTTYPE_PTP: ZFCP_LOG_NORMAL("Point-to-Point fibrechannel " "configuration detected at adapter %s\n" "Peer WWNN 0x%016llx, " @@ -2146,7 +2149,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) debug_text_event(fsf_req->adapter->erp_dbf, 0, "top-p-to-p"); break; - case FSF_TOPO_AL: + case FC_PORTTYPE_NLPORT: ZFCP_LOG_NORMAL("error: Arbitrated loop fibrechannel " "topology detected at adapter %s " "unsupported, shutting down adapter\n", @@ -2155,7 +2158,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) "top-al"); zfcp_erp_adapter_shutdown(adapter, 0); return -EIO; - case FSF_TOPO_FABRIC: + case FC_PORTTYPE_NPORT: ZFCP_LOG_NORMAL("Switched fabric fibrechannel " "network detected at adapter %s.\n", zfcp_get_busid_by_adapter(adapter)); @@ -2168,7 +2171,6 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) "of a type known to the zfcp " "driver, shutting down adapter\n", zfcp_get_busid_by_adapter(adapter)); - adapter->fc_topology = FSF_TOPO_ERROR; debug_text_exception(fsf_req->adapter->erp_dbf, 0, "unknown-topo"); zfcp_erp_adapter_shutdown(adapter, 0); @@ -2328,14 +2330,13 @@ zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req) data = (struct fsf_qtcb_bottom_port*) fsf_req->data; if (data) memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port)); - if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) { - adapter->physical_wwpn = bottom->wwpn; - adapter->physical_s_id = bottom->fc_port_id; - } else { - adapter->physical_wwpn = fc_host_port_name(shost); - adapter->physical_s_id = fc_host_port_id(shost); - } + if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) + fc_host_permanent_port_name(shost) = bottom->wwpn; + else + fc_host_permanent_port_name(shost) = + fc_host_port_name(shost); fc_host_maxframe_size(shost) = bottom->maximum_frame_size; + fc_host_supported_speeds(shost) = bottom->supported_speed; break; case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h index 39475dbcb61..e734415cae6 100644 --- a/drivers/s390/scsi/zfcp_fsf.h +++ b/drivers/s390/scsi/zfcp_fsf.h @@ -199,7 +199,6 @@ #define FSF_TOPO_P2P 0x00000001 #define FSF_TOPO_FABRIC 0x00000002 #define FSF_TOPO_AL 0x00000003 -#define FSF_TOPO_FABRIC_VIRT 0x00000004 /* data direction for FCP commands */ #define FSF_DATADIR_WRITE 0x00000001 diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 5ca0992e97f..3c2cbcccbf5 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -865,13 +865,16 @@ struct fc_function_template zfcp_transport_functions = { .show_rport_supported_classes = 1, .show_host_node_name = 1, .show_host_port_name = 1, + .show_host_permanent_port_name = 1, .show_host_supported_classes = 1, + .show_host_supported_speeds = 1, .show_host_maxframe_size = 1, .show_host_serial_number = 1, .get_fc_host_stats = zfcp_get_fc_host_stats, .reset_fc_host_stats = zfcp_reset_fc_host_stats, /* no functions registered for following dynamic attributes but directly set by LLDD */ + .show_host_port_type = 1, .show_host_speed = 1, .show_host_port_id = 1, }; diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c index c85df9c016a..9f262250043 100644 --- a/drivers/s390/scsi/zfcp_sysfs_adapter.c +++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c @@ -33,14 +33,6 @@ #define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG -static const char fc_topologies[5][25] = { - "", - "point-to-point", - "fabric", - "arbitrated loop", - "fabric (virt. adapter)" -}; - /** * ZFCP_DEFINE_ADAPTER_ATTR * @_name: name of show attribute @@ -69,8 +61,6 @@ ZFCP_DEFINE_ADAPTER_ATTR(physical_wwpn, "0x%016llx\n", adapter->physical_wwpn); ZFCP_DEFINE_ADAPTER_ATTR(physical_s_id, "0x%06x\n", adapter->physical_s_id); ZFCP_DEFINE_ADAPTER_ATTR(card_version, "0x%04x\n", adapter->hydra_version); ZFCP_DEFINE_ADAPTER_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version); -ZFCP_DEFINE_ADAPTER_ATTR(fc_topology, "%s\n", - fc_topologies[adapter->fc_topology]); ZFCP_DEFINE_ADAPTER_ATTR(hardware_version, "0x%08x\n", adapter->hardware_version); ZFCP_DEFINE_ADAPTER_ATTR(in_recovery, "%d\n", atomic_test_mask @@ -257,7 +247,6 @@ static struct attribute *zfcp_adapter_attrs[] = { &dev_attr_physical_s_id.attr, &dev_attr_card_version.attr, &dev_attr_lic_version.attr, - &dev_attr_fc_topology.attr, &dev_attr_status.attr, &dev_attr_hardware_version.attr, NULL -- GitLab From 560c26c8345509619c3575331b99b329b5de1054 Mon Sep 17 00:00:00 2001 From: Jack Hammer Date: Fri, 13 Jan 2006 10:06:50 -0500 Subject: [PATCH 197/465] [SCSI] ips: Mode Sense (Caching Page ) fix To avoid the "sda: got wrong page" message, the ServeRAID driver should be setting flags indicating that the Mode Sense commands are not supported. Signed-off-by: Jack Hammer Signed-off-by: James Bottomley --- drivers/scsi/ips.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index 3882d48a42b..e5e1ca44e1e 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -1319,6 +1319,9 @@ ips_slave_configure(struct scsi_device * SDptr) min = ha->max_cmds - 1; scsi_adjust_queue_depth(SDptr, MSG_ORDERED_TAG, min); } + + SDptr->skip_ms_page_8 = 1; + SDptr->skip_ms_page_3f = 1; return 0; } #endif -- GitLab From 9638d89a75776abc614c29cdeece0cc874ea2a4c Mon Sep 17 00:00:00 2001 From: "Salyzyn, Mark" Date: Thu, 12 Jan 2006 08:31:57 -0500 Subject: [PATCH 198/465] [SCSI] I2O: move pci_request_regions() just behind pci_enable_device() The problem in dpt_i2o could be the pci config space accesses it triggers as it loads, dangerous to do if there is any I/O activity going on in the other driver (probable if a boot driver I guess). I approve this patch to dpt_i2o.c, and am applying it to the Adaptec branch of the driver. Thanks for the investigation Ryoji. --- In linux 2.6.15, data transfer does hang when both dpt_i2o and i2o_block drivers are loaded. It seems that location of pci_request_regions() are wrong. I moved it just behind pci_enable_device() like other drivers, and it becomes fine. Signed-off-by: Ryoji Kamei Signed-off-by: James Bottomley --- drivers/message/i2o/pci.c | 10 +++++----- drivers/scsi/dpt_i2o.c | 10 ++++++---- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c index c5b656cdea7..f23aeea43f6 100644 --- a/drivers/message/i2o/pci.c +++ b/drivers/message/i2o/pci.c @@ -88,11 +88,6 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) struct device *dev = &pdev->dev; int i; - if (pci_request_regions(pdev, OSM_DESCRIPTION)) { - printk(KERN_ERR "%s: device already claimed\n", c->name); - return -ENODEV; - } - for (i = 0; i < 6; i++) { /* Skip I/O spaces */ if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) { @@ -319,6 +314,11 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, return rc; } + if (pci_request_regions(pdev, OSM_DESCRIPTION)) { + printk(KERN_ERR "i2o: device already claimed\n", c->name); + return -ENODEV; + } + if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { printk(KERN_WARNING "i2o: no suitable DMA found for %s\n", pci_name(pdev)); diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index cdeb30b0462..6e6b293dcb2 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -899,6 +899,12 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev if(pci_enable_device(pDev)) { return -EINVAL; } + + if (pci_request_regions(pDev, "dpt_i2o")) { + PERROR("dpti: adpt_config_hba: pci request region failed\n"); + return -EINVAL; + } + pci_set_master(pDev); if (pci_set_dma_mask(pDev, 0xffffffffffffffffULL) && pci_set_dma_mask(pDev, 0xffffffffULL)) @@ -924,10 +930,6 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev raptorFlag = TRUE; } - if (pci_request_regions(pDev, "dpt_i2o")) { - PERROR("dpti: adpt_config_hba: pci request region failed\n"); - return -EINVAL; - } base_addr_virt = ioremap(base_addr0_phys,hba_map0_area_size); if (!base_addr_virt) { pci_release_regions(pDev); -- GitLab From 9a28f49adbe4955af8a1306fd36ddae15136dde7 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 13 Jan 2006 18:04:41 +0100 Subject: [PATCH 199/465] [SCSI] mptsas: support basic hotplug Adds hotplug support for SAS end devices. Unfortunately the fusion firmware doesn't generate similar events for expanders addition/removal so we can't support them yet. Eric has an idea about a clever scheme to find out about expander changes so that'll be added later on. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.h | 1 + drivers/message/fusion/mptsas.c | 338 ++++++++++++++++++++++++++++--- 2 files changed, 308 insertions(+), 31 deletions(-) diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 6c48d1f54ac..af9007d498e 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -612,6 +612,7 @@ typedef struct _MPT_ADAPTER struct list_head list; struct net_device *netdev; struct list_head sas_topology; + struct mutex sas_topology_mutex; MPT_SAS_MGMT sas_mgmt; } MPT_ADAPTER; diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 17e9757e728..b2c682fe634 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -5,7 +5,7 @@ * * Copyright (c) 1999-2005 LSI Logic Corporation * (mailto:mpt_linux_developer@lsil.com) - * Copyright (c) 2005 Dell + * Copyright (c) 2005-2006 Dell */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -86,6 +86,24 @@ static int mptsasInternalCtx = -1; /* Used only for internal commands */ static int mptsasMgmtCtx = -1; +enum mptsas_hotplug_action { + MPTSAS_ADD_DEVICE, + MPTSAS_DEL_DEVICE, +}; + +struct mptsas_hotplug_event { + struct work_struct work; + MPT_ADAPTER *ioc; + enum mptsas_hotplug_action event_type; + u64 sas_address; + u32 channel; + u32 id; + u32 device_info; + u16 handle; + u16 parent_handle; + u8 phy_id; +}; + /* * SAS topology structures * @@ -99,8 +117,8 @@ struct mptsas_devinfo { u8 phy_id; /* phy number of parent device */ u8 port_id; /* sas physical port this device is assoc'd with */ - u8 target; /* logical target id of this device */ - u8 bus; /* logical bus number of this device */ + u8 id; /* logical target id of this device */ + u8 channel; /* logical bus number of this device */ u64 sas_address; /* WWN of this device, SATA is assigned by HBA,expander */ u32 device_info; /* bitfield detailed info about this device */ @@ -114,6 +132,7 @@ struct mptsas_phyinfo { u8 programmed_link_rate; /* programmed max/min phy link rate */ struct mptsas_devinfo identify; /* point to phy device info */ struct mptsas_devinfo attached; /* point to attached device info */ + struct sas_phy *phy; struct sas_rphy *rphy; }; @@ -257,24 +276,27 @@ mptsas_slave_alloc(struct scsi_device *sdev) } rphy = dev_to_rphy(sdev->sdev_target->dev.parent); + mutex_lock(&hd->ioc->sas_topology_mutex); list_for_each_entry(p, &hd->ioc->sas_topology, list) { for (i = 0; i < p->num_phys; i++) { if (p->phy_info[i].attached.sas_address == rphy->identify.sas_address) { vdev->target_id = - p->phy_info[i].attached.target; - vdev->bus_id = p->phy_info[i].attached.bus; + p->phy_info[i].attached.id; + vdev->bus_id = p->phy_info[i].attached.channel; vdev->lun = sdev->lun; goto out; } } } + mutex_unlock(&hd->ioc->sas_topology_mutex); printk("No matching SAS device found!!\n"); kfree(vdev); return -ENODEV; out: + mutex_unlock(&hd->ioc->sas_topology_mutex); vtarget->ioc_id = vdev->ioc_id; vtarget->target_id = vdev->target_id; vtarget->bus_id = vdev->bus_id; @@ -282,6 +304,42 @@ mptsas_slave_alloc(struct scsi_device *sdev) return 0; } +static void +mptsas_slave_destroy(struct scsi_device *sdev) +{ + struct Scsi_Host *host = sdev->host; + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + struct sas_rphy *rphy; + struct mptsas_portinfo *p; + int i; + + /* + * Handle hotplug removal case. + * We need to clear out attached data structure. + */ + rphy = dev_to_rphy(sdev->sdev_target->dev.parent); + + mutex_lock(&hd->ioc->sas_topology_mutex); + list_for_each_entry(p, &hd->ioc->sas_topology, list) { + for (i = 0; i < p->num_phys; i++) { + if (p->phy_info[i].attached.sas_address == + rphy->identify.sas_address) { + memset(&p->phy_info[i].attached, 0, + sizeof(struct mptsas_devinfo)); + p->phy_info[i].rphy = NULL; + goto out; + } + } + } + + out: + mutex_unlock(&hd->ioc->sas_topology_mutex); + /* + * TODO: Issue target reset to flush firmware outstanding commands. + */ + mptscsih_slave_destroy(sdev); +} + static struct scsi_host_template mptsas_driver_template = { .module = THIS_MODULE, .proc_name = "mptsas", @@ -293,7 +351,7 @@ static struct scsi_host_template mptsas_driver_template = { .slave_alloc = mptsas_slave_alloc, .slave_configure = mptscsih_slave_configure, .target_destroy = mptscsih_target_destroy, - .slave_destroy = mptscsih_slave_destroy, + .slave_destroy = mptsas_slave_destroy, .change_queue_depth = mptscsih_change_queue_depth, .eh_abort_handler = mptscsih_abort, .eh_device_reset_handler = mptscsih_dev_reset, @@ -649,8 +707,8 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info, device_info->handle = le16_to_cpu(buffer->DevHandle); device_info->phy_id = buffer->PhyNum; device_info->port_id = buffer->PhysicalPort; - device_info->target = buffer->TargetID; - device_info->bus = buffer->Bus; + device_info->id = buffer->TargetID; + device_info->channel = buffer->Bus; memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64)); device_info->sas_address = le64_to_cpu(sas_address); device_info->device_info = @@ -858,36 +916,36 @@ mptsas_parse_device_info(struct sas_identify *identify, static int mptsas_probe_one_phy(struct device *dev, struct mptsas_phyinfo *phy_info, int index, int local) { - struct sas_phy *port; + struct sas_phy *phy; int error; - port = sas_phy_alloc(dev, index); - if (!port) + phy = sas_phy_alloc(dev, index); + if (!phy) return -ENOMEM; - port->port_identifier = phy_info->port_id; - mptsas_parse_device_info(&port->identify, &phy_info->identify); + phy->port_identifier = phy_info->port_id; + mptsas_parse_device_info(&phy->identify, &phy_info->identify); /* * Set Negotiated link rate. */ switch (phy_info->negotiated_link_rate) { case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED: - port->negotiated_linkrate = SAS_PHY_DISABLED; + phy->negotiated_linkrate = SAS_PHY_DISABLED; break; case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION: - port->negotiated_linkrate = SAS_LINK_RATE_FAILED; + phy->negotiated_linkrate = SAS_LINK_RATE_FAILED; break; case MPI_SAS_IOUNIT0_RATE_1_5: - port->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS; + phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS; break; case MPI_SAS_IOUNIT0_RATE_3_0: - port->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS; + phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS; break; case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE: case MPI_SAS_IOUNIT0_RATE_UNKNOWN: default: - port->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN; + phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN; break; } @@ -896,10 +954,10 @@ static int mptsas_probe_one_phy(struct device *dev, */ switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) { case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5: - port->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS; + phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS; break; case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0: - port->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS; + phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS; break; default: break; @@ -911,10 +969,10 @@ static int mptsas_probe_one_phy(struct device *dev, switch (phy_info->programmed_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) { case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5: - port->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS; + phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS; break; case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0: - port->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS; + phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS; break; default: break; @@ -925,10 +983,10 @@ static int mptsas_probe_one_phy(struct device *dev, */ switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) { case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5: - port->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS; + phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS; break; case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0: - port->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS; + phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS; break; default: break; @@ -940,28 +998,29 @@ static int mptsas_probe_one_phy(struct device *dev, switch (phy_info->programmed_link_rate & MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) { case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5: - port->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS; + phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS; break; case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0: - port->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS; + phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS; break; default: break; } if (local) - port->local_attached = 1; + phy->local_attached = 1; - error = sas_phy_add(port); + error = sas_phy_add(phy); if (error) { - sas_phy_free(port); + sas_phy_free(phy); return error; } + phy_info->phy = phy; if (phy_info->attached.handle) { struct sas_rphy *rphy; - rphy = sas_rphy_alloc(port); + rphy = sas_rphy_alloc(phy); if (!rphy) return 0; /* non-fatal: an rphy can be added later */ @@ -994,7 +1053,10 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index) if (error) goto out_free_port_info; + mutex_lock(&ioc->sas_topology_mutex); list_add_tail(&port_info->list, &ioc->sas_topology); + mutex_unlock(&ioc->sas_topology_mutex); + for (i = 0; i < port_info->num_phys; i++) { mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i], (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER << @@ -1047,7 +1109,10 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index) *handle = port_info->handle; + mutex_lock(&ioc->sas_topology_mutex); list_add_tail(&port_info->list, &ioc->sas_topology); + mutex_unlock(&ioc->sas_topology_mutex); + for (i = 0; i < port_info->num_phys; i++) { struct device *parent; @@ -1079,6 +1144,7 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index) * HBA phys. */ parent = &ioc->sh->shost_gendev; + mutex_lock(&ioc->sas_topology_mutex); list_for_each_entry(p, &ioc->sas_topology, list) { for (j = 0; j < p->num_phys; j++) { if (port_info->phy_info[i].identify.handle == @@ -1086,6 +1152,7 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index) parent = &p->phy_info[j].rphy->dev; } } + mutex_unlock(&ioc->sas_topology_mutex); mptsas_probe_one_phy(parent, &port_info->phy_info[i], *index, 0); @@ -1111,6 +1178,211 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc) ; } +static struct mptsas_phyinfo * +mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id) +{ + struct mptsas_portinfo *port_info; + struct mptsas_devinfo device_info; + struct mptsas_phyinfo *phy_info = NULL; + int i, error; + + /* + * Retrieve the parent sas_address + */ + error = mptsas_sas_device_pg0(ioc, &device_info, + (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << + MPI_SAS_DEVICE_PGAD_FORM_SHIFT), + parent_handle); + if (error) { + printk("mptsas: failed to retrieve device page\n"); + return NULL; + } + + /* + * The phy_info structures are never deallocated during lifetime of + * a host, so the code below is safe without additional refcounting. + */ + mutex_lock(&ioc->sas_topology_mutex); + list_for_each_entry(port_info, &ioc->sas_topology, list) { + for (i = 0; i < port_info->num_phys; i++) { + if (port_info->phy_info[i].identify.sas_address == + device_info.sas_address && + port_info->phy_info[i].phy_id == phy_id) { + phy_info = &port_info->phy_info[i]; + break; + } + } + } + mutex_unlock(&ioc->sas_topology_mutex); + + return phy_info; +} + +static struct mptsas_phyinfo * +mptsas_find_phyinfo_by_handle(MPT_ADAPTER *ioc, u16 handle) +{ + struct mptsas_portinfo *port_info; + struct mptsas_phyinfo *phy_info = NULL; + int i; + + /* + * The phy_info structures are never deallocated during lifetime of + * a host, so the code below is safe without additional refcounting. + */ + mutex_lock(&ioc->sas_topology_mutex); + list_for_each_entry(port_info, &ioc->sas_topology, list) { + for (i = 0; i < port_info->num_phys; i++) { + if (port_info->phy_info[i].attached.handle == handle) { + phy_info = &port_info->phy_info[i]; + break; + } + } + } + mutex_unlock(&ioc->sas_topology_mutex); + + return phy_info; +} + +static void +mptsas_hotplug_work(void *arg) +{ + struct mptsas_hotplug_event *ev = arg; + MPT_ADAPTER *ioc = ev->ioc; + struct mptsas_phyinfo *phy_info; + struct sas_rphy *rphy; + char *ds = NULL; + + if (ev->device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET) + ds = "ssp"; + if (ev->device_info & MPI_SAS_DEVICE_INFO_STP_TARGET) + ds = "stp"; + if (ev->device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE) + ds = "sata"; + + switch (ev->event_type) { + case MPTSAS_DEL_DEVICE: + printk(MYIOC_s_INFO_FMT + "removing %s device, channel %d, id %d, phy %d\n", + ioc->name, ds, ev->channel, ev->id, ev->phy_id); + + phy_info = mptsas_find_phyinfo_by_handle(ioc, ev->handle); + if (!phy_info) { + printk("mptsas: remove event for non-existant PHY.\n"); + break; + } + + if (phy_info->rphy) { + sas_rphy_delete(phy_info->rphy); + phy_info->rphy = NULL; + } + break; + case MPTSAS_ADD_DEVICE: + printk(MYIOC_s_INFO_FMT + "attaching %s device, channel %d, id %d, phy %d\n", + ioc->name, ds, ev->channel, ev->id, ev->phy_id); + + phy_info = mptsas_find_phyinfo_by_parent(ioc, + ev->parent_handle, ev->phy_id); + if (!phy_info) { + printk("mptsas: add event for non-existant PHY.\n"); + break; + } + + if (phy_info->rphy) { + printk("mptsas: trying to add existing device.\n"); + break; + } + + /* fill attached info */ + phy_info->attached.handle = ev->handle; + phy_info->attached.phy_id = ev->phy_id; + phy_info->attached.port_id = phy_info->identify.port_id; + phy_info->attached.id = ev->id; + phy_info->attached.channel = ev->channel; + phy_info->attached.sas_address = ev->sas_address; + phy_info->attached.device_info = ev->device_info; + + rphy = sas_rphy_alloc(phy_info->phy); + if (!rphy) + break; /* non-fatal: an rphy can be added later */ + + mptsas_parse_device_info(&rphy->identify, &phy_info->attached); + if (sas_rphy_add(rphy)) { + sas_rphy_free(rphy); + break; + } + + phy_info->rphy = rphy; + break; + } + + kfree(ev); +} + +static void +mptscsih_send_sas_event(MPT_ADAPTER *ioc, + EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data) +{ + struct mptsas_hotplug_event *ev; + u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo); + __le64 sas_address; + + if ((device_info & + (MPI_SAS_DEVICE_INFO_SSP_TARGET | + MPI_SAS_DEVICE_INFO_STP_TARGET | + MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0) + return; + + if ((sas_event_data->ReasonCode & + (MPI_EVENT_SAS_DEV_STAT_RC_ADDED | + MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING)) == 0) + return; + + ev = kmalloc(sizeof(*ev), GFP_ATOMIC); + if (!ev) { + printk(KERN_WARNING "mptsas: lost hotplug event\n"); + return; + } + + + INIT_WORK(&ev->work, mptsas_hotplug_work, ev); + ev->ioc = ioc; + ev->handle = le16_to_cpu(sas_event_data->DevHandle); + ev->parent_handle = le16_to_cpu(sas_event_data->ParentDevHandle); + ev->channel = sas_event_data->Bus; + ev->id = sas_event_data->TargetID; + ev->phy_id = sas_event_data->PhyNum; + memcpy(&sas_address, &sas_event_data->SASAddress, sizeof(__le64)); + ev->sas_address = le64_to_cpu(sas_address); + ev->device_info = device_info; + + if (sas_event_data->ReasonCode & MPI_EVENT_SAS_DEV_STAT_RC_ADDED) + ev->event_type = MPTSAS_ADD_DEVICE; + else + ev->event_type = MPTSAS_DEL_DEVICE; + + schedule_work(&ev->work); +} + +static int +mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) +{ + u8 event = le32_to_cpu(reply->Event) & 0xFF; + + if (!ioc->sh) + return 1; + + switch (event) { + case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: + mptscsih_send_sas_event(ioc, + (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data); + return 1; /* currently means nothing really */ + + default: + return mptscsih_event_process(ioc, reply); + } +} + static int mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -1203,6 +1475,8 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) sh->unique_id = ioc->id; INIT_LIST_HEAD(&ioc->sas_topology); + mutex_init(&ioc->sas_topology_mutex); + init_MUTEX(&ioc->sas_mgmt.mutex); init_completion(&ioc->sas_mgmt.done); @@ -1339,10 +1613,12 @@ static void __devexit mptsas_remove(struct pci_dev *pdev) sas_remove_host(ioc->sh); + mutex_lock(&ioc->sas_topology_mutex); list_for_each_entry_safe(p, n, &ioc->sas_topology, list) { list_del(&p->list); kfree(p); } + mutex_unlock(&ioc->sas_topology_mutex); mptscsih_remove(pdev); } @@ -1393,7 +1669,7 @@ mptsas_init(void) mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER); mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER); - if (mpt_event_register(mptsasDoneCtx, mptscsih_event_process) == 0) { + if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) { devtprintk((KERN_INFO MYNAM ": Registered for IOC event notifications\n")); } -- GitLab From eeb846cefdd842af479393a7d0fd399a29e42532 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 13 Jan 2006 18:27:11 +0100 Subject: [PATCH 200/465] [SCSI] fusion: convert semaphores to mutexes Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.h | 4 ++-- drivers/message/fusion/mptctl.c | 12 ++++++------ drivers/message/fusion/mptsas.c | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index af9007d498e..74355f2eca0 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -413,7 +413,7 @@ typedef struct _MPT_IOCTL { u8 status; /* current command status */ u8 reset; /* 1 if bus reset allowed */ u8 target; /* target for reset */ - struct semaphore sem_ioc; + struct mutex ioctl_mutex; } MPT_IOCTL; #define MPT_SAS_MGMT_STATUS_RF_VALID 0x02 /* The Reply Frame is VALID */ @@ -421,7 +421,7 @@ typedef struct _MPT_IOCTL { #define MPT_SAS_MGMT_STATUS_TM_FAILED 0x40 /* User TM request failed */ typedef struct _MPT_SAS_MGMT { - struct semaphore mutex; + struct mutex mutex; struct completion done; u8 reply[MPT_DEFAULT_FRAME_SIZE]; /* reply frame data */ u8 status; /* current command status */ diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 7c340240a50..bdf70998798 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -177,10 +177,10 @@ mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock) dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down(%p,%d) called\n", ioc, nonblock)); if (nonblock) { - if (down_trylock(&ioc->ioctl->sem_ioc)) + if (!mutex_trylock(&ioc->ioctl->ioctl_mutex)) rc = -EAGAIN; } else { - if (down_interruptible(&ioc->ioctl->sem_ioc)) + if (mutex_lock_interruptible(&ioc->ioctl->ioctl_mutex)) rc = -ERESTARTSYS; } dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down return %d\n", rc)); @@ -557,7 +557,7 @@ __mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) else ret = -EINVAL; - up(&iocp->ioctl->sem_ioc); + mutex_unlock(&iocp->ioctl->ioctl_mutex); return ret; } @@ -2619,7 +2619,7 @@ compat_mptfwxfer_ioctl(struct file *filp, unsigned int cmd, ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen); - up(&iocp->ioctl->sem_ioc); + mutex_unlock(&iocp->ioctl->ioctl_mutex); return ret; } @@ -2673,7 +2673,7 @@ compat_mpt_command(struct file *filp, unsigned int cmd, */ ret = mptctl_do_mpt_command (karg, &uarg->MF); - up(&iocp->ioctl->sem_ioc); + mutex_unlock(&iocp->ioctl->ioctl_mutex); return ret; } @@ -2743,7 +2743,7 @@ mptctl_probe(struct pci_dev *pdev, const struct pci_device_id *id) memset(mem, 0, sz); ioc->ioctl = (MPT_IOCTL *) mem; ioc->ioctl->ioc = ioc; - sema_init(&ioc->ioctl->sem_ioc, 1); + mutex_init(&ioc->ioctl->ioctl_mutex); return 0; out_fail: diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index b2c682fe634..19fc03ecdf6 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -457,7 +457,7 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset) if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP) return -ENXIO; - if (down_interruptible(&ioc->sas_mgmt.mutex)) + if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex)) goto out; mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc); @@ -508,7 +508,7 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset) error = 0; out_unlock: - up(&ioc->sas_mgmt.mutex); + mutex_unlock(&ioc->sas_mgmt.mutex); out: return error; } @@ -1477,7 +1477,7 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) INIT_LIST_HEAD(&ioc->sas_topology); mutex_init(&ioc->sas_topology_mutex); - init_MUTEX(&ioc->sas_mgmt.mutex); + mutex_init(&ioc->sas_mgmt.mutex); init_completion(&ioc->sas_mgmt.done); /* Verify that we won't exceed the maximum -- GitLab From 1ca00bb7916cb40b8140173c23481e11d92d6f6a Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 13 Jan 2006 18:27:50 +0100 Subject: [PATCH 201/465] [SCSI] fusion: kzalloc / kcalloc conversion Convert kmalloc + memset to kzalloc or kcalloc in fusion. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.c | 3 +-- drivers/message/fusion/mptfc.c | 26 +++++++---------------- drivers/message/fusion/mptlan.c | 14 +++++-------- drivers/message/fusion/mptsas.c | 35 ++++++++++--------------------- drivers/message/fusion/mptscsih.c | 6 ++---- drivers/message/fusion/mptspi.c | 26 +++++++---------------- 6 files changed, 35 insertions(+), 75 deletions(-) diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 537836068c4..80ec89c505d 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -1232,12 +1232,11 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) dprintk((KERN_INFO MYNAM ": Not using 64 bit consistent mask\n")); - ioc = kmalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC); + ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC); if (ioc == NULL) { printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n"); return -ENOMEM; } - memset(ioc, 0, sizeof(MPT_ADAPTER)); ioc->alloc_total = sizeof(MPT_ADAPTER); ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */ ioc->reply_sz = MPT_REPLY_FRAME_SIZE; diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index ba61e182885..5083a556a25 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -148,11 +148,10 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) MPT_SCSI_HOST *hd; MPT_ADAPTER *ioc; unsigned long flags; - int sz, ii; + int ii; int numSGE = 0; int scale; int ioc_cap; - u8 *mem; int error=0; int r; @@ -268,36 +267,27 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) /* SCSI needs scsi_cmnd lookup table! * (with size equal to req_depth*PtrSz!) */ - sz = ioc->req_depth * sizeof(void *); - mem = kmalloc(sz, GFP_ATOMIC); - if (mem == NULL) { + hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC); + if (!hd->ScsiLookup) { error = -ENOMEM; goto out_mptfc_probe; } - memset(mem, 0, sz); - hd->ScsiLookup = (struct scsi_cmnd **) mem; - - dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n", - ioc->name, hd->ScsiLookup, sz)); + dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n", + ioc->name, hd->ScsiLookup)); /* Allocate memory for the device structures. * A non-Null pointer at an offset * indicates a device exists. * max_id = 1 + maximum id (hosts.h) */ - sz = sh->max_id * sizeof(void *); - mem = kmalloc(sz, GFP_ATOMIC); - if (mem == NULL) { + hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC); + if (!hd->Targets) { error = -ENOMEM; goto out_mptfc_probe; } - memset(mem, 0, sz); - hd->Targets = (VirtTarget **) mem; - - dprintk((KERN_INFO - " vdev @ %p, sz=%d\n", hd->Targets, sz)); + dprintk((KERN_INFO " vdev @ %p\n", hd->Targets)); /* Clear the TM flags */ diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c index 014085d8ec8..0b1b72825ae 100644 --- a/drivers/message/fusion/mptlan.c +++ b/drivers/message/fusion/mptlan.c @@ -411,14 +411,12 @@ mpt_lan_open(struct net_device *dev) goto out; priv->mpt_txfidx_tail = -1; - priv->SendCtl = kmalloc(priv->tx_max_out * sizeof(struct BufferControl), + priv->SendCtl = kcalloc(priv->tx_max_out, sizeof(struct BufferControl), GFP_KERNEL); if (priv->SendCtl == NULL) goto out_mpt_txfidx; - for (i = 0; i < priv->tx_max_out; i++) { - memset(&priv->SendCtl[i], 0, sizeof(struct BufferControl)); + for (i = 0; i < priv->tx_max_out; i++) priv->mpt_txfidx[++priv->mpt_txfidx_tail] = i; - } dlprintk((KERN_INFO MYNAM "@lo: Finished initializing SendCtl\n")); @@ -428,15 +426,13 @@ mpt_lan_open(struct net_device *dev) goto out_SendCtl; priv->mpt_rxfidx_tail = -1; - priv->RcvCtl = kmalloc(priv->max_buckets_out * - sizeof(struct BufferControl), + priv->RcvCtl = kcalloc(priv->max_buckets_out, + sizeof(struct BufferControl), GFP_KERNEL); if (priv->RcvCtl == NULL) goto out_mpt_rxfidx; - for (i = 0; i < priv->max_buckets_out; i++) { - memset(&priv->RcvCtl[i], 0, sizeof(struct BufferControl)); + for (i = 0; i < priv->max_buckets_out; i++) priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = i; - } /**/ dlprintk((KERN_INFO MYNAM "/lo: txfidx contains - ")); /**/ for (i = 0; i < priv->tx_max_out; i++) diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 19fc03ecdf6..668a101b89f 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -258,13 +258,12 @@ mptsas_slave_alloc(struct scsi_device *sdev) struct scsi_target *starget; int i; - vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL); + vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL); if (!vdev) { printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", hd->ioc->name, sizeof(VirtDevice)); return -ENOMEM; } - memset(vdev, 0, sizeof(VirtDevice)); vdev->ioc_id = hd->ioc->id; sdev->hostdata = vdev; starget = scsi_target(sdev); @@ -1044,10 +1043,9 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index) u32 handle = 0xFFFF; int error = -ENOMEM, i; - port_info = kmalloc(sizeof(*port_info), GFP_KERNEL); + port_info = kzalloc(sizeof(*port_info), GFP_KERNEL); if (!port_info) goto out; - memset(port_info, 0, sizeof(*port_info)); error = mptsas_sas_io_unit_pg0(ioc, port_info); if (error) @@ -1096,10 +1094,9 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index) struct mptsas_portinfo *port_info, *p; int error = -ENOMEM, i, j; - port_info = kmalloc(sizeof(*port_info), GFP_KERNEL); + port_info = kzalloc(sizeof(*port_info), GFP_KERNEL); if (!port_info) goto out; - memset(port_info, 0, sizeof(*port_info)); error = mptsas_sas_expander_pg0(ioc, port_info, (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE << @@ -1390,11 +1387,10 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) MPT_SCSI_HOST *hd; MPT_ADAPTER *ioc; unsigned long flags; - int sz, ii; + int ii; int numSGE = 0; int scale; int ioc_cap; - u8 *mem; int error=0; int r; @@ -1518,36 +1514,27 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) /* SCSI needs scsi_cmnd lookup table! * (with size equal to req_depth*PtrSz!) */ - sz = ioc->req_depth * sizeof(void *); - mem = kmalloc(sz, GFP_ATOMIC); - if (mem == NULL) { + hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC); + if (!hd->ScsiLookup) { error = -ENOMEM; goto out_mptsas_probe; } - memset(mem, 0, sz); - hd->ScsiLookup = (struct scsi_cmnd **) mem; - - dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n", - ioc->name, hd->ScsiLookup, sz)); + dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n", + ioc->name, hd->ScsiLookup)); /* Allocate memory for the device structures. * A non-Null pointer at an offset * indicates a device exists. * max_id = 1 + maximum id (hosts.h) */ - sz = sh->max_id * sizeof(void *); - mem = kmalloc(sz, GFP_ATOMIC); - if (mem == NULL) { + hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC); + if (!hd->Targets) { error = -ENOMEM; goto out_mptsas_probe; } - memset(mem, 0, sz); - hd->Targets = (VirtTarget **) mem; - - dprintk((KERN_INFO - " vtarget @ %p, sz=%d\n", hd->Targets, sz)); + dprintk((KERN_INFO " vtarget @ %p\n", hd->Targets)); /* Clear the TM flags */ diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 93a16fa3c4b..525d9aea201 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -2162,10 +2162,9 @@ mptscsih_target_alloc(struct scsi_target *starget) { VirtTarget *vtarget; - vtarget = kmalloc(sizeof(VirtTarget), GFP_KERNEL); + vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL); if (!vtarget) return -ENOMEM; - memset(vtarget, 0, sizeof(VirtTarget)); starget->hostdata = vtarget; return 0; } @@ -2185,14 +2184,13 @@ mptscsih_slave_alloc(struct scsi_device *sdev) VirtDevice *vdev; struct scsi_target *starget; - vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL); + vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL); if (!vdev) { printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", hd->ioc->name, sizeof(VirtDevice)); return -ENOMEM; } - memset(vdev, 0, sizeof(VirtDevice)); vdev->ioc_id = hd->ioc->id; vdev->target_id = sdev->id; vdev->bus_id = sdev->channel; diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index ce332a6085e..7dce29277cb 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -158,11 +158,10 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) MPT_SCSI_HOST *hd; MPT_ADAPTER *ioc; unsigned long flags; - int sz, ii; + int ii; int numSGE = 0; int scale; int ioc_cap; - u8 *mem; int error=0; int r; @@ -288,36 +287,27 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) /* SCSI needs scsi_cmnd lookup table! * (with size equal to req_depth*PtrSz!) */ - sz = ioc->req_depth * sizeof(void *); - mem = kmalloc(sz, GFP_ATOMIC); - if (mem == NULL) { + hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC); + if (!hd->ScsiLookup) { error = -ENOMEM; goto out_mptspi_probe; } - memset(mem, 0, sz); - hd->ScsiLookup = (struct scsi_cmnd **) mem; - - dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n", - ioc->name, hd->ScsiLookup, sz)); + dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n", + ioc->name, hd->ScsiLookup)); /* Allocate memory for the device structures. * A non-Null pointer at an offset * indicates a device exists. * max_id = 1 + maximum id (hosts.h) */ - sz = sh->max_id * sizeof(void *); - mem = kmalloc(sz, GFP_ATOMIC); - if (mem == NULL) { + hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC); + if (!hd->Targets) { error = -ENOMEM; goto out_mptspi_probe; } - memset(mem, 0, sz); - hd->Targets = (VirtTarget **) mem; - - dprintk((KERN_INFO - " vdev @ %p, sz=%d\n", hd->Targets, sz)); + dprintk((KERN_INFO " vdev @ %p\n", hd->Targets)); /* Clear the TM flags */ -- GitLab From f20139bee4545b91f30e14e2f528320c7ab36fa6 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Fri, 13 Jan 2006 15:36:25 -0600 Subject: [PATCH 202/465] [SCSI] fix up message/i2o/pci.c There was a use before initialisation of c->name Signed-off-by: James Bottomley --- drivers/message/i2o/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c index f23aeea43f6..d698d7709c3 100644 --- a/drivers/message/i2o/pci.c +++ b/drivers/message/i2o/pci.c @@ -315,7 +315,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, } if (pci_request_regions(pdev, OSM_DESCRIPTION)) { - printk(KERN_ERR "i2o: device already claimed\n", c->name); + printk(KERN_ERR "i2o: device already claimed\n"); return -ENODEV; } -- GitLab From d158d26167a3f6a910ec3e0eda23cc0cd437c689 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Fri, 13 Jan 2006 16:05:44 -0800 Subject: [PATCH 203/465] [SCSI] sem2mutex: scsi_transport_spi.c Convert the SCSI transport class code to use a mutex rather than a semaphore. Signed-off-by: Jes Sorensen Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_spi.c | 10 +++++----- include/scsi/scsi_transport_spi.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 86306d681b6..7ee95eb83dd 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include "scsi_priv.h" #include @@ -48,7 +48,7 @@ /* Private data accessors (keep these out of the header file) */ #define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending) -#define spi_dv_sem(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_sem) +#define spi_dv_mutex(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_mutex) struct spi_internal { struct scsi_transport_template t; @@ -242,7 +242,7 @@ static int spi_setup_transport_attrs(struct transport_container *tc, spi_hold_mcs(starget) = 0; spi_dv_pending(starget) = 0; spi_initial_dv(starget) = 0; - init_MUTEX(&spi_dv_sem(starget)); + mutex_init(&spi_dv_mutex(starget)); return 0; } @@ -915,7 +915,7 @@ spi_dv_device(struct scsi_device *sdev) scsi_target_quiesce(starget); spi_dv_pending(starget) = 1; - down(&spi_dv_sem(starget)); + mutex_lock(&spi_dv_mutex(starget)); starget_printk(KERN_INFO, starget, "Beginning Domain Validation\n"); @@ -923,7 +923,7 @@ spi_dv_device(struct scsi_device *sdev) starget_printk(KERN_INFO, starget, "Ending Domain Validation\n"); - up(&spi_dv_sem(starget)); + mutex_unlock(&spi_dv_mutex(starget)); spi_dv_pending(starget) = 0; scsi_target_resume(starget); diff --git a/include/scsi/scsi_transport_spi.h b/include/scsi/scsi_transport_spi.h index 54a89611e9c..2b5930ba69e 100644 --- a/include/scsi/scsi_transport_spi.h +++ b/include/scsi/scsi_transport_spi.h @@ -54,7 +54,7 @@ struct spi_transport_attrs { unsigned int support_qas; /* supports quick arbitration and selection */ /* Private Fields */ unsigned int dv_pending:1; /* Internal flag */ - struct semaphore dv_sem; /* semaphore to serialise dv */ + struct mutex dv_mutex; /* semaphore to serialise dv */ }; enum spi_signal_type { -- GitLab From 05e8ec17f4d11ba13795e878fc389cb04d1fdadd Mon Sep 17 00:00:00 2001 From: Michael Reed Date: Fri, 13 Jan 2006 14:31:54 -0600 Subject: [PATCH 204/465] [SCSI] mptfusion - fc transport attributes Signed-off-by: Michael Reed Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.c | 33 +- drivers/message/fusion/mptbase.h | 28 +- drivers/message/fusion/mptfc.c | 551 +++++++++++++++++++++++++++++- drivers/message/fusion/mptscsih.c | 28 +- 4 files changed, 613 insertions(+), 27 deletions(-) diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 80ec89c505d..8c26f093fb6 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -148,7 +148,6 @@ static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag); static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag); static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag); static int GetLanConfigPages(MPT_ADAPTER *ioc); -static int GetFcPortPage0(MPT_ADAPTER *ioc, int portnum); static int GetIoUnitPage2(MPT_ADAPTER *ioc); int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum); @@ -1244,6 +1243,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) ioc->pcidev = pdev; ioc->diagPending = 0; spin_lock_init(&ioc->diagLock); + spin_lock_init(&ioc->fc_rescan_work_lock); + spin_lock_init(&ioc->fc_rport_lock); spin_lock_init(&ioc->initializing_hba_lock); /* Initialize the event logging. @@ -1267,6 +1268,10 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) */ INIT_LIST_HEAD(&ioc->configQ); + /* Initialize the fc rport list head. + */ + INIT_LIST_HEAD(&ioc->fc_rports); + /* Find lookup slot. */ INIT_LIST_HEAD(&ioc->list); ioc->id = mpt_ids++; @@ -1879,7 +1884,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) * (FCPortPage0_t stuff) */ for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { - (void) GetFcPortPage0(ioc, ii); + (void) mptbase_GetFcPortPage0(ioc, ii); } if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) && @@ -4198,7 +4203,7 @@ GetLanConfigPages(MPT_ADAPTER *ioc) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* - * GetFcPortPage0 - Fetch FCPort config Page0. + * mptbase_GetFcPortPage0 - Fetch FCPort config Page0. * @ioc: Pointer to MPT_ADAPTER structure * @portnum: IOC Port number * @@ -4208,8 +4213,8 @@ GetLanConfigPages(MPT_ADAPTER *ioc) * -EAGAIN if no msg frames currently available * -EFAULT for non-successful reply or no reply (timeout) */ -static int -GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) +int +mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) { ConfigPageHeader_t hdr; CONFIGPARMS cfg; @@ -4219,6 +4224,8 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) int data_sz; int copy_sz; int rc; + int count = 400; + /* Get FCPort Page 0 header */ hdr.PageVersion = 0; @@ -4242,6 +4249,8 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) rc = -ENOMEM; ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma); if (ppage0_alloc) { + + try_again: memset((u8 *)ppage0_alloc, 0, data_sz); cfg.physAddr = page0_dma; cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; @@ -4273,6 +4282,19 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount); pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators); + /* + * if still doing discovery, + * hang loose a while until finished + */ + if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) { + if (count-- > 0) { + msleep_interruptible(100); + goto try_again; + } + printk(MYIOC_s_INFO_FMT "Firmware discovery not" + " complete.\n", + ioc->name); + } } pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma); @@ -6357,6 +6379,7 @@ EXPORT_SYMBOL(mpt_alloc_fw_memory); EXPORT_SYMBOL(mpt_free_fw_memory); EXPORT_SYMBOL(mptbase_sas_persist_operation); EXPORT_SYMBOL(mpt_alt_ioc_wait); +EXPORT_SYMBOL(mptbase_GetFcPortPage0); /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 74355f2eca0..25f44064b96 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -76,8 +76,8 @@ #define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR #endif -#define MPT_LINUX_VERSION_COMMON "3.03.05" -#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.05" +#define MPT_LINUX_VERSION_COMMON "3.03.06" +#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.06" #define WHAT_MAGIC_STRING "@" "(" "#" ")" #define show_mptmod_ver(s,ver) \ @@ -499,6 +499,22 @@ typedef struct _RaidCfgData { int isRaid; /* bit field, 1 if RAID */ }RaidCfgData; +#define MPT_RPORT_INFO_FLAGS_REGISTERED 0x01 /* rport registered */ +#define MPT_RPORT_INFO_FLAGS_MISSING 0x02 /* missing from DevPage0 scan */ +#define MPT_RPORT_INFO_FLAGS_MAPPED_VDEV 0x04 /* target mapped in vdev */ + +/* + * data allocated for each fc rport device + */ +struct mptfc_rport_info +{ + struct list_head list; + struct fc_rport *rport; + VirtDevice *vdev; + FCDevicePage0_t pg0; + u8 flags; +}; + /* * Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS */ @@ -614,6 +630,13 @@ typedef struct _MPT_ADAPTER struct list_head sas_topology; struct mutex sas_topology_mutex; MPT_SAS_MGMT sas_mgmt; + + struct list_head fc_rports; + spinlock_t fc_rport_lock; /* list and ri flags */ + spinlock_t fc_rescan_work_lock; + int fc_rescan_work_count; + struct work_struct fc_rescan_work; + } MPT_ADAPTER; /* @@ -1000,6 +1023,7 @@ extern void mpt_free_fw_memory(MPT_ADAPTER *ioc); extern int mpt_findImVolumes(MPT_ADAPTER *ioc); extern int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); +extern int mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum); extern int mpt_alt_ioc_wait(MPT_ADAPTER *ioc); /* diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index 5083a556a25..a380fe105a2 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -55,12 +55,14 @@ #include /* notifier code */ #include #include +#include #include #include #include #include #include +#include #include "mptbase.h" #include "mptscsih.h" @@ -79,19 +81,34 @@ static int mpt_pq_filter = 0; module_param(mpt_pq_filter, int, 0); MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)"); +#define MPTFC_DEV_LOSS_TMO (60) +static int mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO; /* reasonable default */ +module_param(mptfc_dev_loss_tmo, int, 0); +MODULE_PARM_DESC(mptfc_dev_loss_tmo, " Initial time the driver programs the " + " transport to wait for an rport to " + " return following a device loss event." + " Default=60."); + static int mptfcDoneCtx = -1; static int mptfcTaskCtx = -1; static int mptfcInternalCtx = -1; /* Used only for internal commands */ +int mptfc_slave_alloc(struct scsi_device *device); +static int mptfc_qcmd(struct scsi_cmnd *SCpnt, + void (*done)(struct scsi_cmnd *)); + +static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout); +static void __devexit mptfc_remove(struct pci_dev *pdev); + static struct scsi_host_template mptfc_driver_template = { .module = THIS_MODULE, .proc_name = "mptfc", .proc_info = mptscsih_proc_info, .name = "MPT FC Host", .info = mptscsih_info, - .queuecommand = mptscsih_qcmd, + .queuecommand = mptfc_qcmd, .target_alloc = mptscsih_target_alloc, - .slave_alloc = mptscsih_slave_alloc, + .slave_alloc = mptfc_slave_alloc, .slave_configure = mptscsih_slave_configure, .target_destroy = mptscsih_target_destroy, .slave_destroy = mptscsih_slave_destroy, @@ -132,15 +149,472 @@ static struct pci_device_id mptfc_pci_table[] = { }; MODULE_DEVICE_TABLE(pci, mptfc_pci_table); -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +static struct scsi_transport_template *mptfc_transport_template = NULL; + +struct fc_function_template mptfc_transport_functions = { + .dd_fcrport_size = 8, + .show_host_node_name = 1, + .show_host_port_name = 1, + .show_host_supported_classes = 1, + .show_host_port_id = 1, + .show_rport_supported_classes = 1, + .show_starget_node_name = 1, + .show_starget_port_name = 1, + .show_starget_port_id = 1, + .set_rport_dev_loss_tmo = mptfc_set_rport_loss_tmo, + .show_rport_dev_loss_tmo = 1, + +}; + +/* FIXME! values controlling firmware RESCAN event + * need to be set low to allow dev_loss_tmo to + * work as expected. Currently, firmware doesn't + * notify driver of RESCAN event until some number + * of seconds elapse. This value can be set via + * lsiutil. + */ +static void +mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) +{ + if (timeout > 0) + rport->dev_loss_tmo = timeout; + else + rport->dev_loss_tmo = mptfc_dev_loss_tmo; +} + +static int +mptfc_FcDevPage0_cmp_func(const void *a, const void *b) +{ + FCDevicePage0_t **aa = (FCDevicePage0_t **)a; + FCDevicePage0_t **bb = (FCDevicePage0_t **)b; + + if ((*aa)->CurrentBus == (*bb)->CurrentBus) { + if ((*aa)->CurrentTargetID == (*bb)->CurrentTargetID) + return 0; + if ((*aa)->CurrentTargetID < (*bb)->CurrentTargetID) + return -1; + return 1; + } + if ((*aa)->CurrentBus < (*bb)->CurrentBus) + return -1; + return 1; +} + +static int +mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port, + void(*func)(MPT_ADAPTER *ioc,int channel, FCDevicePage0_t *arg)) +{ + ConfigPageHeader_t hdr; + CONFIGPARMS cfg; + FCDevicePage0_t *ppage0_alloc, *fc; + dma_addr_t page0_dma; + int data_sz; + int ii; + + FCDevicePage0_t *p0_array=NULL, *p_p0; + FCDevicePage0_t **pp0_array=NULL, **p_pp0; + + int rc = -ENOMEM; + U32 port_id = 0xffffff; + int num_targ = 0; + int max_bus = ioc->facts.MaxBuses; + int max_targ = ioc->facts.MaxDevices; + + if (max_bus == 0 || max_targ == 0) + goto out; + + data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ; + p_p0 = p0_array = kzalloc(data_sz, GFP_KERNEL); + if (!p0_array) + goto out; + + data_sz = sizeof(FCDevicePage0_t *) * max_bus * max_targ; + p_pp0 = pp0_array = kzalloc(data_sz, GFP_KERNEL); + if (!pp0_array) + goto out; + + do { + /* Get FC Device Page 0 header */ + hdr.PageVersion = 0; + hdr.PageLength = 0; + hdr.PageNumber = 0; + hdr.PageType = MPI_CONFIG_PAGETYPE_FC_DEVICE; + cfg.cfghdr.hdr = &hdr; + cfg.physAddr = -1; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + cfg.dir = 0; + cfg.pageAddr = port_id; + cfg.timeout = 0; + + if ((rc = mpt_config(ioc, &cfg)) != 0) + break; + + if (hdr.PageLength <= 0) + break; + + data_sz = hdr.PageLength * 4; + ppage0_alloc = pci_alloc_consistent(ioc->pcidev, data_sz, + &page0_dma); + rc = -ENOMEM; + if (!ppage0_alloc) + break; + + cfg.physAddr = page0_dma; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + + if ((rc = mpt_config(ioc, &cfg)) == 0) { + ppage0_alloc->PortIdentifier = + le32_to_cpu(ppage0_alloc->PortIdentifier); + + ppage0_alloc->WWNN.Low = + le32_to_cpu(ppage0_alloc->WWNN.Low); + + ppage0_alloc->WWNN.High = + le32_to_cpu(ppage0_alloc->WWNN.High); + + ppage0_alloc->WWPN.Low = + le32_to_cpu(ppage0_alloc->WWPN.Low); + + ppage0_alloc->WWPN.High = + le32_to_cpu(ppage0_alloc->WWPN.High); + + ppage0_alloc->BBCredit = + le16_to_cpu(ppage0_alloc->BBCredit); + + ppage0_alloc->MaxRxFrameSize = + le16_to_cpu(ppage0_alloc->MaxRxFrameSize); + + port_id = ppage0_alloc->PortIdentifier; + num_targ++; + *p_p0 = *ppage0_alloc; /* save data */ + *p_pp0++ = p_p0++; /* save addr */ + } + pci_free_consistent(ioc->pcidev, data_sz, + (u8 *) ppage0_alloc, page0_dma); + if (rc != 0) + break; + + } while (port_id <= 0xff0000); + + if (num_targ) { + /* sort array */ + if (num_targ > 1) + sort (pp0_array, num_targ, sizeof(FCDevicePage0_t *), + mptfc_FcDevPage0_cmp_func, NULL); + /* call caller's func for each targ */ + for (ii = 0; ii < num_targ; ii++) { + fc = *(pp0_array+ii); + func(ioc, ioc_port, fc); + } + } + + out: + if (pp0_array) + kfree(pp0_array); + if (p0_array) + kfree(p0_array); + return rc; +} + +static int +mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid) +{ + /* not currently usable */ + if (pg0->Flags & (MPI_FC_DEVICE_PAGE0_FLAGS_PLOGI_INVALID | + MPI_FC_DEVICE_PAGE0_FLAGS_PRLI_INVALID)) + return -1; + + if (!(pg0->Flags & MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID)) + return -1; + + if (!(pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET)) + return -1; + + /* + * board data structure already normalized to platform endianness + * shifted to avoid unaligned access on 64 bit architecture + */ + rid->node_name = ((u64)pg0->WWNN.High) << 32 | (u64)pg0->WWNN.Low; + rid->port_name = ((u64)pg0->WWPN.High) << 32 | (u64)pg0->WWPN.Low; + rid->port_id = pg0->PortIdentifier; + rid->roles = FC_RPORT_ROLE_UNKNOWN; + rid->roles |= FC_RPORT_ROLE_FCP_TARGET; + if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR) + rid->roles |= FC_RPORT_ROLE_FCP_INITIATOR; + + return 0; +} + +static void +mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) +{ + struct fc_rport_identifiers rport_ids; + struct fc_rport *rport; + struct mptfc_rport_info *ri; + int match = 0; + u64 port_name; + unsigned long flags; + + if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0) + return; + + /* scan list looking for a match */ + spin_lock_irqsave(&ioc->fc_rport_lock, flags); + list_for_each_entry(ri, &ioc->fc_rports, list) { + port_name = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low; + if (port_name == rport_ids.port_name) { /* match */ + list_move_tail(&ri->list, &ioc->fc_rports); + match = 1; + break; + } + } + if (!match) { /* allocate one */ + spin_unlock_irqrestore(&ioc->fc_rport_lock, flags); + ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL); + if (!ri) + return; + spin_lock_irqsave(&ioc->fc_rport_lock, flags); + list_add_tail(&ri->list, &ioc->fc_rports); + } + + ri->pg0 = *pg0; /* add/update pg0 data */ + ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING; + + if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) { + ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED; + spin_unlock_irqrestore(&ioc->fc_rport_lock, flags); + rport = fc_remote_port_add(ioc->sh,channel, &rport_ids); + spin_lock_irqsave(&ioc->fc_rport_lock, flags); + if (rport) { + if (*((struct mptfc_rport_info **)rport->dd_data) != ri) { + ri->flags &= ~MPT_RPORT_INFO_FLAGS_MAPPED_VDEV; + ri->vdev = NULL; + ri->rport = rport; + *((struct mptfc_rport_info **)rport->dd_data) = ri; + } + rport->dev_loss_tmo = mptfc_dev_loss_tmo; + /* + * if already mapped, remap here. If not mapped, + * slave_alloc will allocate vdev and map + */ + if (ri->flags & MPT_RPORT_INFO_FLAGS_MAPPED_VDEV) { + ri->vdev->target_id = ri->pg0.CurrentTargetID; + ri->vdev->bus_id = ri->pg0.CurrentBus; + ri->vdev->vtarget->target_id = ri->vdev->target_id; + ri->vdev->vtarget->bus_id = ri->vdev->bus_id; + } + #ifdef MPT_DEBUG + printk ("mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, " + "rport tid %d, tmo %d\n", + ioc->sh->host_no, + pg0->PortIdentifier, + pg0->WWNN, + pg0->WWPN, + pg0->CurrentTargetID, + ri->rport->scsi_target_id, + ri->rport->dev_loss_tmo); + #endif + } else { + list_del(&ri->list); + kfree(ri); + ri = NULL; + } + } + spin_unlock_irqrestore(&ioc->fc_rport_lock,flags); + +} + /* - * mptfc_probe - Installs scsi devices per bus. - * @pdev: Pointer to pci_dev structure - * - * Returns 0 for success, non-zero for failure. - * + * OS entry point to allow host driver to alloc memory + * for each scsi device. Called once per device the bus scan. + * Return non-zero if allocation fails. + * Init memory once per LUN. */ +int +mptfc_slave_alloc(struct scsi_device *sdev) +{ + MPT_SCSI_HOST *hd; + VirtTarget *vtarget; + VirtDevice *vdev; + struct scsi_target *starget; + struct fc_rport *rport; + struct mptfc_rport_info *ri; + unsigned long flags; + + + rport = starget_to_rport(scsi_target(sdev)); + + if (!rport || fc_remote_port_chkready(rport)) + return -ENXIO; + + hd = (MPT_SCSI_HOST *)sdev->host->hostdata; + + vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL); + if (!vdev) { + printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", + hd->ioc->name, sizeof(VirtDevice)); + return -ENOMEM; + } + memset(vdev, 0, sizeof(VirtDevice)); + + spin_lock_irqsave(&hd->ioc->fc_rport_lock,flags); + + if (!(ri = *((struct mptfc_rport_info **)rport->dd_data))) { + spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags); + kfree(vdev); + return -ENODEV; + } + + sdev->hostdata = vdev; + starget = scsi_target(sdev); + vtarget = starget->hostdata; + if (vtarget->num_luns == 0) { + vtarget->tflags = MPT_TARGET_FLAGS_Q_YES | + MPT_TARGET_FLAGS_VALID_INQUIRY; + hd->Targets[sdev->id] = vtarget; + } + + vtarget->target_id = vdev->target_id; + vtarget->bus_id = vdev->bus_id; + + vdev->vtarget = vtarget; + vdev->ioc_id = hd->ioc->id; + vdev->lun = sdev->lun; + vdev->target_id = ri->pg0.CurrentTargetID; + vdev->bus_id = ri->pg0.CurrentBus; + + ri->flags |= MPT_RPORT_INFO_FLAGS_MAPPED_VDEV; + ri->vdev = vdev; + + spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags); + + vtarget->num_luns++; + +#ifdef MPT_DEBUG + printk ("mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, " + "CurrentTargetID %d, %x %llx %llx\n", + sdev->host->host_no, + vtarget->num_luns, + sdev->id, ri->pg0.CurrentTargetID, + ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN); +#endif + + return 0; +} + +static int +mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) +{ + struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device)); + int err; + + err = fc_remote_port_chkready(rport); + if (unlikely(err)) { + SCpnt->result = err; + done(SCpnt); + return 0; + } + return mptscsih_qcmd(SCpnt,done); +} + +static void +mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum) +{ + unsigned class = 0, cos = 0; + + /* don't know what to do as only one scsi (fc) host was allocated */ + if (portnum != 0) + return; + + class = ioc->fc_port_page0[portnum].SupportedServiceClass; + if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_1) + cos |= FC_COS_CLASS1; + if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_2) + cos |= FC_COS_CLASS2; + if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_3) + cos |= FC_COS_CLASS3; + + fc_host_node_name(ioc->sh) = + (u64)ioc->fc_port_page0[portnum].WWNN.High << 32 + | (u64)ioc->fc_port_page0[portnum].WWNN.Low; + + fc_host_port_name(ioc->sh) = + (u64)ioc->fc_port_page0[portnum].WWPN.High << 32 + | (u64)ioc->fc_port_page0[portnum].WWPN.Low; + + fc_host_port_id(ioc->sh) = ioc->fc_port_page0[portnum].PortIdentifier; + + fc_host_supported_classes(ioc->sh) = cos; + + fc_host_tgtid_bind_type(ioc->sh) = FC_TGTID_BIND_BY_WWPN; +} + +static void +mptfc_rescan_devices(void *arg) +{ + MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; + int ii; + int work_to_do; + unsigned long flags; + struct mptfc_rport_info *ri; + + do { + /* start by tagging all ports as missing */ + spin_lock_irqsave(&ioc->fc_rport_lock,flags); + list_for_each_entry(ri, &ioc->fc_rports, list) { + if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) { + ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING; + } + } + spin_unlock_irqrestore(&ioc->fc_rport_lock,flags); + + /* + * now rescan devices known to adapter, + * will reregister existing rports + */ + for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { + (void) mptbase_GetFcPortPage0(ioc, ii); + mptfc_init_host_attr(ioc,ii); /* refresh */ + mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev); + } + + /* delete devices still missing */ + spin_lock_irqsave(&ioc->fc_rport_lock, flags); + list_for_each_entry(ri, &ioc->fc_rports, list) { + /* if newly missing, delete it */ + if ((ri->flags & (MPT_RPORT_INFO_FLAGS_REGISTERED | + MPT_RPORT_INFO_FLAGS_MISSING)) + == (MPT_RPORT_INFO_FLAGS_REGISTERED | + MPT_RPORT_INFO_FLAGS_MISSING)) { + + ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED| + MPT_RPORT_INFO_FLAGS_MISSING); + fc_remote_port_delete(ri->rport); + /* + * remote port not really deleted 'cause + * binding is by WWPN and driver only + * registers FCP_TARGETs + */ + #ifdef MPT_DEBUG + printk ("mptfc_rescan.%d: %llx deleted\n", + ioc->sh->host_no, ri->pg0.WWPN); + #endif + } + } + spin_unlock_irqrestore(&ioc->fc_rport_lock,flags); + + /* + * allow multiple passes as target state + * might have changed during scan + */ + spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); + if (ioc->fc_rescan_work_count > 2) /* only need one more */ + ioc->fc_rescan_work_count = 2; + work_to_do = --ioc->fc_rescan_work_count; + spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); + } while (work_to_do); +} + static int mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -154,10 +628,10 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) int ioc_cap; int error=0; int r; - + if ((r = mpt_attach(pdev,id)) != 0) return r; - + ioc = pci_get_drvdata(pdev); ioc->DoneCtx = mptfcDoneCtx; ioc->TaskCtx = mptfcTaskCtx; @@ -193,7 +667,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) printk(MYIOC_s_WARN_FMT "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n", ioc->name, ioc); - return 0; + return -ENODEV; } sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST)); @@ -206,6 +680,8 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto out_mptfc_probe; } + INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc); + spin_lock_irqsave(&ioc->FreeQlock, flags); /* Attach the SCSI Host to the IOC structure @@ -322,6 +798,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) hd->scandv_wait_done = 0; hd->last_queue_full = 0; + sh->transportt = mptfc_transport_template; error = scsi_add_host (sh, &ioc->pcidev->dev); if(error) { dprintk((KERN_ERR MYNAM @@ -329,7 +806,11 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto out_mptfc_probe; } - scsi_scan_host(sh); + for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { + mptfc_init_host_attr(ioc,ii); + mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev); + } + return 0; out_mptfc_probe: @@ -342,7 +823,7 @@ static struct pci_driver mptfc_driver = { .name = "mptfc", .id_table = mptfc_pci_table, .probe = mptfc_probe, - .remove = __devexit_p(mptscsih_remove), + .remove = __devexit_p(mptfc_remove), .shutdown = mptscsih_shutdown, #ifdef CONFIG_PM .suspend = mptscsih_suspend, @@ -360,9 +841,20 @@ static struct pci_driver mptfc_driver = { static int __init mptfc_init(void) { + int error; show_mptmod_ver(my_NAME, my_VERSION); + /* sanity check module parameter */ + if (mptfc_dev_loss_tmo == 0) + mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO; + + mptfc_transport_template = + fc_attach_transport(&mptfc_transport_functions); + + if (!mptfc_transport_template) + return -ENODEV; + mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER); mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER); mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER); @@ -377,7 +869,33 @@ mptfc_init(void) ": Registered for IOC reset notifications\n")); } - return pci_register_driver(&mptfc_driver); + error = pci_register_driver(&mptfc_driver); + if (error) { + fc_release_transport(mptfc_transport_template); + } + + return error; +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/** + * mptfc_remove - Removed fc infrastructure for devices + * @pdev: Pointer to pci_dev structure + * + */ +static void __devexit mptfc_remove(struct pci_dev *pdev) +{ + MPT_ADAPTER *ioc = pci_get_drvdata(pdev); + struct mptfc_rport_info *p, *n; + + fc_remove_host(ioc->sh); + + list_for_each_entry_safe(p, n, &ioc->fc_rports, list) { + list_del(&p->list); + kfree(p); + } + + mptscsih_remove(pdev); } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -390,7 +908,8 @@ static void __exit mptfc_exit(void) { pci_unregister_driver(&mptfc_driver); - + fc_release_transport(mptfc_transport_template); + mpt_reset_deregister(mptfcDoneCtx); dprintk((KERN_INFO MYNAM ": Deregistered for IOC reset notifications\n")); diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 525d9aea201..cdac5578fdf 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -893,6 +893,7 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd) * when a lun is disable by mid-layer. * Do NOT access the referenced scsi_cmnd structure or * members. Will cause either a paging or NULL ptr error. + * (BUT, BUT, BUT, the code does reference it! - mdr) * @hd: Pointer to a SCSI HOST structure * @vdevice: per device private data * @@ -2557,13 +2558,25 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) hd->cmdPtr = NULL; } - /* 7. Set flag to force DV and re-read IOC Page 3 + /* 7. SPI: Set flag to force DV and re-read IOC Page 3 */ if (ioc->bus_type == SPI) { ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3; ddvtprintk(("Set reload IOC Pg3 Flag\n")); } + /* 7. FC: Rescan for blocked rports which might have returned. + */ + else if (ioc->bus_type == FC) { + int work_count; + unsigned long flags; + + spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); + work_count = ++ioc->fc_rescan_work_count; + spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); + if (work_count == 1) + schedule_work(&ioc->fc_rescan_work); + } dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name)); } @@ -2587,6 +2600,8 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) { MPT_SCSI_HOST *hd; u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; + int work_count; + unsigned long flags; devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", ioc->name, event)); @@ -2608,11 +2623,18 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) /* FIXME! */ break; + case MPI_EVENT_RESCAN: /* 06 */ + spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); + work_count = ++ioc->fc_rescan_work_count; + spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); + if (work_count == 1) + schedule_work(&ioc->fc_rescan_work); + break; + /* * CHECKME! Don't think we need to do * anything for these, but... */ - case MPI_EVENT_RESCAN: /* 06 */ case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */ case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */ /* @@ -3950,8 +3972,6 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice) mptscsih_do_cmd(hd, &iocmd); } -/* Search IOC page 3 to determine if this is hidden physical disk - */ /* Search IOC page 3 to determine if this is hidden physical disk */ static int -- GitLab From 6d5b0c315e0c14f8a0fe274eda7676d62cbd8584 Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Fri, 13 Jan 2006 16:25:26 -0700 Subject: [PATCH 205/465] [SCSI] fusion - adding support for FC949ES Add software recognition for the new LSI Logic Fibre Channel controller. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.c | 4 ++++ drivers/message/fusion/mptfc.c | 2 ++ include/linux/pci_ids.h | 1 + 3 files changed, 7 insertions(+) diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 8c26f093fb6..33213370027 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -1378,6 +1378,10 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) ioc->bus_type = FC; ioc->errata_flag_1064 = 1; } + else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949E) { + ioc->prod_name = "LSIFC949E"; + ioc->bus_type = FC; + } else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) { ioc->prod_name = "LSI53C1030"; ioc->bus_type = SPI; diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index a380fe105a2..b102c7666d0 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -145,6 +145,8 @@ static struct pci_device_id mptfc_pci_table[] = { PCI_ANY_ID, PCI_ANY_ID }, { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949X, PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949ES, + PCI_ANY_ID, PCI_ANY_ID }, {0} /* Terminating entry */ }; MODULE_DEVICE_TABLE(pci, mptfc_pci_table); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 7fb397e3f2d..5403257ae3e 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -181,6 +181,7 @@ #define PCI_DEVICE_ID_LSI_FC929X 0x0626 #define PCI_DEVICE_ID_LSI_FC939X 0x0642 #define PCI_DEVICE_ID_LSI_FC949X 0x0640 +#define PCI_DEVICE_ID_LSI_FC949ES 0x0646 #define PCI_DEVICE_ID_LSI_FC919X 0x0628 #define PCI_DEVICE_ID_NCR_YELLOWFIN 0x0701 #define PCI_DEVICE_ID_LSI_61C102 0x0901 -- GitLab From e02f3f59225d8c3b2a0ad0dc941a09865e27da61 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 13 Jan 2006 19:04:00 +0100 Subject: [PATCH 206/465] [SCSI] remove target parent limitiation When James Smart fixed the issue of the userspace scan atributes crashing the system with the FC transport class he added a patch to let the transport class check if the parent is valid for a given transport class. When adding support for the integrated raid of fusion sas devices we ran into a problem with that, as it didn't allow adding virtual raid volumes without the transport class knowing about it. So this patch adds a user_scan attribute instead, that takes over from scsi_scan_host_selected if the transport class sets it and thus lets the transport class control the user-initiated scanning. As this plugs the hole about user-initiated scanning the target_parent hook goes away and we rely on callers of the scanning routines to do something sensible. For SAS this meant I had to switch from a spinlock to a mutex to synchronize the topology linked lists, in FC they were completely unsynchronized which seems wrong. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley --- drivers/scsi/scsi_priv.h | 6 ----- drivers/scsi/scsi_proc.c | 6 ++++- drivers/scsi/scsi_scan.c | 16 ++---------- drivers/scsi/scsi_sysfs.c | 5 +++- drivers/scsi/scsi_transport_fc.c | 22 ++++++++++------ drivers/scsi/scsi_transport_sas.c | 42 ++++++++++++++++++------------- include/scsi/scsi.h | 6 +++++ include/scsi/scsi_transport.h | 7 ++---- 8 files changed, 57 insertions(+), 53 deletions(-) diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 14a6198cb8d..27c48274e8c 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -26,12 +26,6 @@ struct Scsi_Host; #define SCSI_SENSE_VALID(scmd) \ (((scmd)->sense_buffer[0] & 0x70) == 0x70) -/* - * Special value for scanning to specify scanning or rescanning of all - * possible channels, (target) ids, or luns on a given shost. - */ -#define SCAN_WILD_CARD ~0 - /* hosts.c */ extern int scsi_init_hosts(void); extern void scsi_exit_hosts(void); diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c index 1b5711e714a..07be62bbaae 100644 --- a/drivers/scsi/scsi_proc.c +++ b/drivers/scsi/scsi_proc.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "scsi_priv.h" #include "scsi_logging.h" @@ -200,7 +201,10 @@ static int scsi_add_single_device(uint host, uint channel, uint id, uint lun) if (IS_ERR(shost)) return PTR_ERR(shost); - error = scsi_scan_host_selected(shost, channel, id, lun, 1); + if (shost->transportt->user_scan) + error = shost->transportt->user_scan(shost, channel, id, lun); + else + error = scsi_scan_host_selected(shost, channel, id, lun, 1); scsi_host_put(shost); return error; } diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index edcd80b749c..752fb5da3de 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -334,19 +334,6 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, struct scsi_target *starget; struct scsi_target *found_target; - /* - * Obtain the real parent from the transport. The transport - * is allowed to fail (no error) if there is nothing at that - * target id. - */ - if (shost->transportt->target_parent) { - spin_lock_irqsave(shost->host_lock, flags); - parent = shost->transportt->target_parent(shost, channel, id); - spin_unlock_irqrestore(shost->host_lock, flags); - if (!parent) - return NULL; - } - starget = kmalloc(size, GFP_KERNEL); if (!starget) { printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__); @@ -1283,8 +1270,9 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, struct scsi_device *sdev; struct device *parent = &shost->shost_gendev; int res; - struct scsi_target *starget = scsi_alloc_target(parent, channel, id); + struct scsi_target *starget; + starget = scsi_alloc_target(parent, channel, id); if (!starget) return ERR_PTR(-ENOMEM); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 2cb962751a7..a77b32deaf8 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -106,7 +106,10 @@ static int scsi_scan(struct Scsi_Host *shost, const char *str) return -EINVAL; if (check_set(&lun, s3)) return -EINVAL; - res = scsi_scan_host_selected(shost, channel, id, lun, 1); + if (shost->transportt->user_scan) + res = shost->transportt->user_scan(shost, channel, id, lun); + else + res = scsi_scan_host_selected(shost, channel, id, lun, 1); return res; } diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 625f4a664d0..f2c9acf11bd 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -1093,17 +1093,23 @@ static int fc_rport_match(struct attribute_container *cont, /* * Must be called with shost->host_lock held */ -static struct device *fc_target_parent(struct Scsi_Host *shost, - int channel, uint id) +static int fc_user_scan(struct Scsi_Host *shost, uint channel, + uint id, uint lun) { struct fc_rport *rport; - list_for_each_entry(rport, &fc_host_rports(shost), peers) - if ((rport->channel == channel) && - (rport->scsi_target_id == id)) - return &rport->dev; + list_for_each_entry(rport, &fc_host_rports(shost), peers) { + if (rport->scsi_target_id == -1) + continue; - return NULL; + if ((channel == SCAN_WILD_CARD || channel == rport->channel) && + (id == SCAN_WILD_CARD || id == rport->scsi_target_id)) { + scsi_scan_target(&rport->dev, rport->channel, + rport->scsi_target_id, lun, 1); + } + } + + return 0; } struct scsi_transport_template * @@ -1142,7 +1148,7 @@ fc_attach_transport(struct fc_function_template *ft) /* Transport uses the shost workq for scsi scanning */ i->t.create_work_queue = 1; - i->t.target_parent = fc_target_parent; + i->t.user_scan = fc_user_scan; /* * Setup SCSI Target Attributes. diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index e950435a11d..fb6641b42df 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -62,7 +63,7 @@ struct sas_internal { struct sas_host_attrs { struct list_head rphy_list; - spinlock_t lock; + struct mutex lock; u32 next_target_id; }; #define to_sas_host_attrs(host) ((struct sas_host_attrs *)(host)->shost_data) @@ -165,7 +166,7 @@ static int sas_host_setup(struct transport_container *tc, struct device *dev, struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); INIT_LIST_HEAD(&sas_host->rphy_list); - spin_lock_init(&sas_host->lock); + mutex_init(&sas_host->lock); sas_host->next_target_id = 0; return 0; } @@ -626,7 +627,7 @@ int sas_rphy_add(struct sas_rphy *rphy) transport_add_device(&rphy->dev); transport_configure_device(&rphy->dev); - spin_lock(&sas_host->lock); + mutex_lock(&sas_host->lock); list_add_tail(&rphy->list, &sas_host->rphy_list); if (identify->device_type == SAS_END_DEVICE && (identify->target_port_protocols & @@ -634,7 +635,7 @@ int sas_rphy_add(struct sas_rphy *rphy) rphy->scsi_target_id = sas_host->next_target_id++; else rphy->scsi_target_id = -1; - spin_unlock(&sas_host->lock); + mutex_unlock(&sas_host->lock); if (rphy->scsi_target_id != -1) { scsi_scan_target(&rphy->dev, parent->number, @@ -661,9 +662,9 @@ void sas_rphy_free(struct sas_rphy *rphy) struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent); struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); - spin_lock(&sas_host->lock); + mutex_lock(&sas_host->lock); list_del(&rphy->list); - spin_unlock(&sas_host->lock); + mutex_unlock(&sas_host->lock); transport_destroy_device(&rphy->dev); put_device(rphy->dev.parent); @@ -703,9 +704,9 @@ sas_rphy_delete(struct sas_rphy *rphy) device_del(dev); transport_destroy_device(dev); - spin_lock(&sas_host->lock); + mutex_lock(&sas_host->lock); list_del(&rphy->list); - spin_unlock(&sas_host->lock); + mutex_unlock(&sas_host->lock); parent->rphy = NULL; @@ -731,23 +732,28 @@ EXPORT_SYMBOL(scsi_is_sas_rphy); * SCSI scan helper */ -static struct device *sas_target_parent(struct Scsi_Host *shost, - int channel, uint id) +static int sas_user_scan(struct Scsi_Host *shost, uint channel, + uint id, uint lun) { struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); struct sas_rphy *rphy; - struct device *dev = NULL; - spin_lock(&sas_host->lock); + mutex_lock(&sas_host->lock); list_for_each_entry(rphy, &sas_host->rphy_list, list) { struct sas_phy *parent = dev_to_phy(rphy->dev.parent); - if (parent->number == channel && - rphy->scsi_target_id == id) - dev = &rphy->dev; + + if (rphy->scsi_target_id == -1) + continue; + + if ((channel == SCAN_WILD_CARD || channel == parent->number) && + (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) { + scsi_scan_target(&rphy->dev, parent->number, + rphy->scsi_target_id, lun, 1); + } } - spin_unlock(&sas_host->lock); + mutex_unlock(&sas_host->lock); - return dev; + return 0; } @@ -792,7 +798,7 @@ sas_attach_transport(struct sas_function_template *ft) return NULL; memset(i, 0, sizeof(struct sas_internal)); - i->t.target_parent = sas_target_parent; + i->t.user_scan = sas_user_scan; i->t.host_attrs.ac.attrs = &i->host_attrs[0]; i->t.host_attrs.ac.class = &sas_host_class.class; diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 6cb1e2788d8..c60b8ff2f5e 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -31,6 +31,12 @@ extern const unsigned char scsi_command_size[8]; #define MAX_SCSI_DEVICE_CODE 15 extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE]; +/* + * Special value for scanning to specify scanning or rescanning of all + * possible channels, (target) ids, or luns on a given shost. + */ +#define SCAN_WILD_CARD ~0 + /* * SCSI opcodes */ diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h index f6e0bb484c6..e7b1054adf8 100644 --- a/include/scsi/scsi_transport.h +++ b/include/scsi/scsi_transport.h @@ -30,12 +30,9 @@ struct scsi_transport_template { struct transport_container device_attrs; /* - * If set, call target_parent prior to allocating a scsi_target, - * so we get the appropriate parent for the target. This function - * is required for transports like FC and iSCSI that do not put the - * scsi_target under scsi_host. + * If set, called from sysfs and legacy procfs rescanning code. */ - struct device *(*target_parent)(struct Scsi_Host *, int, uint); + int (*user_scan)(struct Scsi_Host *, uint, uint, uint); /* The size of the specific transport attribute structure (a * space of this size will be left at the end of the -- GitLab From 816aa907b909177bdf6e6e6b0d00c5e5a6e2be8c Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Fri, 13 Jan 2006 16:25:20 -0700 Subject: [PATCH 207/465] [SCSI] fusion - adding raid support in mptsas The SAS RAID volumes are reported beyond the expected number of phys. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.h | 1 + drivers/message/fusion/mptsas.c | 27 ++++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 25f44064b96..47053ac6506 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -630,6 +630,7 @@ typedef struct _MPT_ADAPTER struct list_head sas_topology; struct mutex sas_topology_mutex; MPT_SAS_MGMT sas_mgmt; + int num_ports; struct list_head fc_rports; spinlock_t fc_rport_lock; /* list and ri flags */ diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 668a101b89f..5a06d8d8694 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -274,6 +274,16 @@ mptsas_slave_alloc(struct scsi_device *sdev) hd->Targets[sdev->id] = vtarget; } + /* + RAID volumes placed beyond the last expected port. + */ + if (sdev->channel == hd->ioc->num_ports) { + vdev->target_id = sdev->id; + vdev->bus_id = 0; + vdev->lun = 0; + goto out; + } + rphy = dev_to_rphy(sdev->sdev_target->dev.parent); mutex_lock(&hd->ioc->sas_topology_mutex); list_for_each_entry(p, &hd->ioc->sas_topology, list) { @@ -284,6 +294,7 @@ mptsas_slave_alloc(struct scsi_device *sdev) p->phy_info[i].attached.id; vdev->bus_id = p->phy_info[i].attached.channel; vdev->lun = sdev->lun; + mutex_unlock(&hd->ioc->sas_topology_mutex); goto out; } } @@ -295,7 +306,6 @@ mptsas_slave_alloc(struct scsi_device *sdev) return -ENODEV; out: - mutex_unlock(&hd->ioc->sas_topology_mutex); vtarget->ioc_id = vdev->ioc_id; vtarget->target_id = vdev->target_id; vtarget->bus_id = vdev->bus_id; @@ -1051,6 +1061,7 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index) if (error) goto out_free_port_info; + ioc->num_ports = port_info->num_phys; mutex_lock(&ioc->sas_topology_mutex); list_add_tail(&port_info->list, &ioc->sas_topology); mutex_unlock(&ioc->sas_topology_mutex); @@ -1585,6 +1596,20 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) mptsas_scan_sas_topology(ioc); + /* + Reporting RAID volumes. + */ + if (!ioc->raid_data.pIocPg2) + return 0; + if (!ioc->raid_data.pIocPg2->NumActiveVolumes) + return 0; + for (ii=0;iiraid_data.pIocPg2->NumActiveVolumes;ii++) { + scsi_add_device(sh, + ioc->num_ports, + ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeID, + 0); + } + return 0; out_mptsas_probe: -- GitLab From 4b915a73663fe0951077ebcdaf02337ff2bddcfc Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Fri, 13 Jan 2006 16:25:23 -0700 Subject: [PATCH 208/465] [SCSI] fusion - mpi header udpate This updates mpi headers in fusion drivers to version 1.5.12. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/lsi/mpi.h | 10 +- drivers/message/fusion/lsi/mpi_cnfg.h | 158 ++++++++++++-------- drivers/message/fusion/lsi/mpi_history.txt | 77 +++++++--- drivers/message/fusion/lsi/mpi_init.h | 8 +- drivers/message/fusion/lsi/mpi_ioc.h | 122 +++++++++++++++- drivers/message/fusion/lsi/mpi_log_fc.h | 89 +++++++++++ drivers/message/fusion/lsi/mpi_log_sas.h | 162 +++++++++++++++++++++ drivers/message/fusion/lsi/mpi_sas.h | 30 ++-- 8 files changed, 554 insertions(+), 102 deletions(-) create mode 100644 drivers/message/fusion/lsi/mpi_log_fc.h create mode 100644 drivers/message/fusion/lsi/mpi_log_sas.h diff --git a/drivers/message/fusion/lsi/mpi.h b/drivers/message/fusion/lsi/mpi.h index b61e3d17507..02cdc840a06 100644 --- a/drivers/message/fusion/lsi/mpi.h +++ b/drivers/message/fusion/lsi/mpi.h @@ -6,7 +6,7 @@ * Title: MPI Message independent structures and definitions * Creation Date: July 27, 2000 * - * mpi.h Version: 01.05.08 + * mpi.h Version: 01.05.10 * * Version History * --------------- @@ -74,6 +74,8 @@ * 06-24-05 01.05.08 Added function codes for SCSI IO 32 and * TargetAssistExtended requests. * Added EEDP IOCStatus codes. + * 08-03-05 01.05.09 Bumped MPI_HEADER_VERSION_UNIT. + * 08-30-05 01.05.10 Added 2 new IOCStatus codes for Target. * -------------------------------------------------------------------------- */ @@ -104,7 +106,7 @@ /* Note: The major versions of 0xe0 through 0xff are reserved */ /* versioning for this MPI header set */ -#define MPI_HEADER_VERSION_UNIT (0x0A) +#define MPI_HEADER_VERSION_UNIT (0x0C) #define MPI_HEADER_VERSION_DEV (0x00) #define MPI_HEADER_VERSION_UNIT_MASK (0xFF00) #define MPI_HEADER_VERSION_UNIT_SHIFT (8) @@ -711,6 +713,8 @@ typedef struct _MSG_DEFAULT_REPLY #define MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR (0x006D) #define MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E) #define MPI_IOCSTATUS_TARGET_IU_TOO_SHORT (0x006F) +#define MPI_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT (0x0070) +#define MPI_IOCSTATUS_TARGET_NAK_RECEIVED (0x0071) /****************************************************************************/ /* Additional FCP target values (obsolete) */ @@ -745,7 +749,7 @@ typedef struct _MSG_DEFAULT_REPLY #define MPI_IOCSTATUS_LAN_CANCELED (0x0087) /****************************************************************************/ -/* Serial Attached SCSI values */ +/* Serial Attached SCSI values */ /****************************************************************************/ #define MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED (0x0090) diff --git a/drivers/message/fusion/lsi/mpi_cnfg.h b/drivers/message/fusion/lsi/mpi_cnfg.h index d8339896f73..b1becec27e1 100644 --- a/drivers/message/fusion/lsi/mpi_cnfg.h +++ b/drivers/message/fusion/lsi/mpi_cnfg.h @@ -6,7 +6,7 @@ * Title: MPI Config message, structures, and Pages * Creation Date: July 27, 2000 * - * mpi_cnfg.h Version: 01.05.09 + * mpi_cnfg.h Version: 01.05.11 * * Version History * --------------- @@ -249,6 +249,23 @@ * Added OwnerDevHandle and Flags field to SAS PHY Page 0. * Added IOC GPIO Flags define to SAS Enclosure Page 0. * Fixed the value for MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT. + * 08-03-05 01.05.10 Removed ISDataScrubRate and ISResyncRate from + * Manufacturing Page 4. + * Added MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE bit. + * Added NumDevsPerEnclosure field to SAS IO Unit page 2. + * Added MPI_SAS_IOUNIT2_FLAGS_HOST_ASSIGNED_PHYS_MAP + * define. + * Added EnclosureHandle field to SAS Expander page 0. + * Removed redundant NumTableEntriesProg field from SAS + * Expander Page 1. + * 08-30-05 01.05.11 Added DeviceID for FC949E and changed the DeviceID for + * SAS1078. + * Added more defines for Manufacturing Page 4 Flags field. + * Added more defines for IOCSettings and added + * ExpanderSpinup field to Bios Page 1. + * Added postpone SATA Init bit to SAS IO Unit Page 1 + * ControlFlags. + * Changed LogEntry format for Log Page 0. * -------------------------------------------------------------------------- */ @@ -494,7 +511,7 @@ typedef struct _MSG_CONFIG_REPLY #define MPI_MANUFACTPAGE_DEVICEID_FC929X (0x0626) #define MPI_MANUFACTPAGE_DEVICEID_FC939X (0x0642) #define MPI_MANUFACTPAGE_DEVICEID_FC949X (0x0640) -#define MPI_MANUFACTPAGE_DEVICEID_FC949ES (0x0646) +#define MPI_MANUFACTPAGE_DEVICEID_FC949E (0x0646) /* SCSI */ #define MPI_MANUFACTPAGE_DEVID_53C1030 (0x0030) #define MPI_MANUFACTPAGE_DEVID_53C1030ZC (0x0031) @@ -510,7 +527,7 @@ typedef struct _MSG_CONFIG_REPLY #define MPI_MANUFACTPAGE_DEVID_SAS1066E (0x005A) #define MPI_MANUFACTPAGE_DEVID_SAS1068 (0x0054) #define MPI_MANUFACTPAGE_DEVID_SAS1068E (0x0058) -#define MPI_MANUFACTPAGE_DEVID_SAS1078 (0x0060) +#define MPI_MANUFACTPAGE_DEVID_SAS1078 (0x0062) typedef struct _CONFIG_PAGE_MANUFACTURING_0 @@ -602,9 +619,7 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_4 U32 IMVolumeSettings; /* 50h */ U32 Reserved3; /* 54h */ U32 Reserved4; /* 58h */ - U8 ISDataScrubRate; /* 5Ch */ - U8 ISResyncRate; /* 5Dh */ - U16 Reserved5; /* 5Eh */ + U32 Reserved5; /* 5Ch */ U8 IMEDataScrubRate; /* 60h */ U8 IMEResyncRate; /* 61h */ U16 Reserved6; /* 62h */ @@ -616,9 +631,14 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_4 } CONFIG_PAGE_MANUFACTURING_4, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_4, ManufacturingPage4_t, MPI_POINTER pManufacturingPage4_t; -#define MPI_MANUFACTURING4_PAGEVERSION (0x02) +#define MPI_MANUFACTURING4_PAGEVERSION (0x03) /* defines for the Flags field */ +#define MPI_MANPAGE4_IME_DISABLE (0x20) +#define MPI_MANPAGE4_IM_DISABLE (0x10) +#define MPI_MANPAGE4_IS_DISABLE (0x08) +#define MPI_MANPAGE4_IR_MODEPAGE8_DISABLE (0x04) +#define MPI_MANPAGE4_IM_RESYNC_CACHE_ENABLE (0x02) #define MPI_MANPAGE4_IR_NO_MIX_SAS_SATA (0x01) @@ -669,7 +689,7 @@ typedef struct _CONFIG_PAGE_IO_UNIT_1 } CONFIG_PAGE_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_1, IOUnitPage1_t, MPI_POINTER pIOUnitPage1_t; -#define MPI_IOUNITPAGE1_PAGEVERSION (0x01) +#define MPI_IOUNITPAGE1_PAGEVERSION (0x02) /* IO Unit Page 1 Flags defines */ #define MPI_IOUNITPAGE1_MULTI_FUNCTION (0x00000000) @@ -681,7 +701,7 @@ typedef struct _CONFIG_PAGE_IO_UNIT_1 #define MPI_IOUNITPAGE1_DISABLE_IR (0x00000040) #define MPI_IOUNITPAGE1_FORCE_32 (0x00000080) #define MPI_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE (0x00000100) - +#define MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE (0x00000200) typedef struct _MPI_ADAPTER_INFO { @@ -968,7 +988,8 @@ typedef struct _CONFIG_PAGE_BIOS_1 U32 Reserved1; /* 0Ch */ U32 DeviceSettings; /* 10h */ U16 NumberOfDevices; /* 14h */ - U16 Reserved2; /* 16h */ + U8 ExpanderSpinup; /* 16h */ + U8 Reserved2; /* 17h */ U16 IOTimeoutBlockDevicesNonRM; /* 18h */ U16 IOTimeoutSequential; /* 1Ah */ U16 IOTimeoutOther; /* 1Ch */ @@ -976,7 +997,7 @@ typedef struct _CONFIG_PAGE_BIOS_1 } CONFIG_PAGE_BIOS_1, MPI_POINTER PTR_CONFIG_PAGE_BIOS_1, BIOSPage1_t, MPI_POINTER pBIOSPage1_t; -#define MPI_BIOSPAGE1_PAGEVERSION (0x02) +#define MPI_BIOSPAGE1_PAGEVERSION (0x03) /* values for the BiosOptions field */ #define MPI_BIOSPAGE1_OPTIONS_SPI_ENABLE (0x00000400) @@ -985,8 +1006,15 @@ typedef struct _CONFIG_PAGE_BIOS_1 #define MPI_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001) /* values for the IOCSettings field */ +#define MPI_BIOSPAGE1_IOCSET_MASK_INITIAL_SPINUP_DELAY (0x0F000000) +#define MPI_BIOSPAGE1_IOCSET_SHIFT_INITIAL_SPINUP_DELAY (24) + #define MPI_BIOSPAGE1_IOCSET_MASK_PORT_ENABLE_DELAY (0x00F00000) #define MPI_BIOSPAGE1_IOCSET_SHIFT_PORT_ENABLE_DELAY (20) + +#define MPI_BIOSPAGE1_IOCSET_AUTO_PORT_ENABLE (0x00080000) +#define MPI_BIOSPAGE1_IOCSET_DIRECT_ATTACH_SPINUP_MODE (0x00040000) + #define MPI_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE (0x00030000) #define MPI_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT (0x00000000) #define MPI_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT (0x00010000) @@ -1016,6 +1044,11 @@ typedef struct _CONFIG_PAGE_BIOS_1 #define MPI_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN (0x00000002) #define MPI_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN (0x00000001) +/* defines for the ExpanderSpinup field */ +#define MPI_BIOSPAGE1_EXPSPINUP_MASK_MAX_TARGET (0xF0) +#define MPI_BIOSPAGE1_EXPSPINUP_SHIFT_MAX_TARGET (4) +#define MPI_BIOSPAGE1_EXPSPINUP_MASK_DELAY (0x0F) + typedef struct _MPI_BOOT_DEVICE_ADAPTER_ORDER { U32 Reserved1; /* 00h */ @@ -1233,13 +1266,13 @@ typedef struct _CONFIG_PAGE_SCSI_PORT_0 #define MPI_SCSIPORTPAGE0_CAP_SHIFT_MIN_SYNC_PERIOD (8) #define MPI_SCSIPORTPAGE0_CAP_GET_MIN_SYNC_PERIOD(Cap) \ - ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MASK_MIN_SYNC_PERIOD) \ + ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK) \ >> MPI_SCSIPORTPAGE0_CAP_SHIFT_MIN_SYNC_PERIOD \ ) #define MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK (0x00FF0000) #define MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET (16) #define MPI_SCSIPORTPAGE0_CAP_GET_MAX_SYNC_OFFSET(Cap) \ - ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MASK_MAX_SYNC_OFFSET) \ + ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK) \ >> MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET \ ) #define MPI_SCSIPORTPAGE0_CAP_IDP (0x08000000) @@ -2370,47 +2403,48 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1 } CONFIG_PAGE_SAS_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_1, SasIOUnitPage1_t, MPI_POINTER pSasIOUnitPage1_t; -#define MPI_SASIOUNITPAGE1_PAGEVERSION (0x04) +#define MPI_SASIOUNITPAGE1_PAGEVERSION (0x05) /* values for SAS IO Unit Page 1 ControlFlags */ -#define MPI_SAS_IOUNIT1_CONTROL_DEVICE_SELF_TEST (0x8000) -#define MPI_SAS_IOUNIT1_CONTROL_SATA_3_0_MAX (0x4000) -#define MPI_SAS_IOUNIT1_CONTROL_SATA_1_5_MAX (0x2000) -#define MPI_SAS_IOUNIT1_CONTROL_SATA_SW_PRESERVE (0x1000) -#define MPI_SAS_IOUNIT1_CONTROL_DISABLE_SAS_HASH (0x0800) - -#define MPI_SAS_IOUNIT1_CONTROL_MASK_DEV_SUPPORT (0x0600) -#define MPI_SAS_IOUNIT1_CONTROL_SHIFT_DEV_SUPPORT (9) -#define MPI_SAS_IOUNIT1_CONTROL_DEV_SUPPORT_BOTH (0x00) -#define MPI_SAS_IOUNIT1_CONTROL_DEV_SAS_SUPPORT (0x01) -#define MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT (0x02) - -#define MPI_SAS_IOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080) -#define MPI_SAS_IOUNIT1_CONTROL_SATA_SMART_REQUIRED (0x0040) -#define MPI_SAS_IOUNIT1_CONTROL_SATA_NCQ_REQUIRED (0x0020) -#define MPI_SAS_IOUNIT1_CONTROL_SATA_FUA_REQUIRED (0x0010) -#define MPI_SAS_IOUNIT1_CONTROL_PHY_ENABLE_ORDER_HIGH (0x0008) -#define MPI_SAS_IOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL (0x0004) -#define MPI_SAS_IOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY (0x0002) -#define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001) +#define MPI_SAS_IOUNIT1_CONTROL_DEVICE_SELF_TEST (0x8000) +#define MPI_SAS_IOUNIT1_CONTROL_SATA_3_0_MAX (0x4000) +#define MPI_SAS_IOUNIT1_CONTROL_SATA_1_5_MAX (0x2000) +#define MPI_SAS_IOUNIT1_CONTROL_SATA_SW_PRESERVE (0x1000) +#define MPI_SAS_IOUNIT1_CONTROL_DISABLE_SAS_HASH (0x0800) + +#define MPI_SAS_IOUNIT1_CONTROL_MASK_DEV_SUPPORT (0x0600) +#define MPI_SAS_IOUNIT1_CONTROL_SHIFT_DEV_SUPPORT (9) +#define MPI_SAS_IOUNIT1_CONTROL_DEV_SUPPORT_BOTH (0x00) +#define MPI_SAS_IOUNIT1_CONTROL_DEV_SAS_SUPPORT (0x01) +#define MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT (0x02) + +#define MPI_SAS_IOUNIT1_CONTROL_POSTPONE_SATA_INIT (0x0100) +#define MPI_SAS_IOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080) +#define MPI_SAS_IOUNIT1_CONTROL_SATA_SMART_REQUIRED (0x0040) +#define MPI_SAS_IOUNIT1_CONTROL_SATA_NCQ_REQUIRED (0x0020) +#define MPI_SAS_IOUNIT1_CONTROL_SATA_FUA_REQUIRED (0x0010) +#define MPI_SAS_IOUNIT1_CONTROL_PHY_ENABLE_ORDER_HIGH (0x0008) +#define MPI_SAS_IOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL (0x0004) +#define MPI_SAS_IOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY (0x0002) +#define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001) /* values for SAS IO Unit Page 1 PortFlags */ -#define MPI_SAS_IOUNIT1_PORT_FLAGS_0_TARGET_IOC_NUM (0x00) -#define MPI_SAS_IOUNIT1_PORT_FLAGS_1_TARGET_IOC_NUM (0x04) -#define MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01) +#define MPI_SAS_IOUNIT1_PORT_FLAGS_0_TARGET_IOC_NUM (0x00) +#define MPI_SAS_IOUNIT1_PORT_FLAGS_1_TARGET_IOC_NUM (0x04) +#define MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01) /* values for SAS IO Unit Page 0 PhyFlags */ -#define MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE (0x04) -#define MPI_SAS_IOUNIT1_PHY_FLAGS_TX_INVERT (0x02) -#define MPI_SAS_IOUNIT1_PHY_FLAGS_RX_INVERT (0x01) +#define MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE (0x04) +#define MPI_SAS_IOUNIT1_PHY_FLAGS_TX_INVERT (0x02) +#define MPI_SAS_IOUNIT1_PHY_FLAGS_RX_INVERT (0x01) /* values for SAS IO Unit Page 0 MaxMinLinkRate */ -#define MPI_SAS_IOUNIT1_MAX_RATE_MASK (0xF0) -#define MPI_SAS_IOUNIT1_MAX_RATE_1_5 (0x80) -#define MPI_SAS_IOUNIT1_MAX_RATE_3_0 (0x90) -#define MPI_SAS_IOUNIT1_MIN_RATE_MASK (0x0F) -#define MPI_SAS_IOUNIT1_MIN_RATE_1_5 (0x08) -#define MPI_SAS_IOUNIT1_MIN_RATE_3_0 (0x09) +#define MPI_SAS_IOUNIT1_MAX_RATE_MASK (0xF0) +#define MPI_SAS_IOUNIT1_MAX_RATE_1_5 (0x80) +#define MPI_SAS_IOUNIT1_MAX_RATE_3_0 (0x90) +#define MPI_SAS_IOUNIT1_MIN_RATE_MASK (0x0F) +#define MPI_SAS_IOUNIT1_MIN_RATE_1_5 (0x08) +#define MPI_SAS_IOUNIT1_MIN_RATE_3_0 (0x09) /* see mpi_sas.h for values for SAS IO Unit Page 1 ControllerPhyDeviceInfo values */ @@ -2418,16 +2452,18 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1 typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2 { CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ - U32 Reserved1; /* 08h */ + U8 NumDevsPerEnclosure; /* 08h */ + U8 Reserved1; /* 09h */ + U16 Reserved2; /* 0Ah */ U16 MaxPersistentIDs; /* 0Ch */ U16 NumPersistentIDsUsed; /* 0Eh */ U8 Status; /* 10h */ U8 Flags; /* 11h */ - U16 MaxNumPhysicalMappedIDs;/* 12h */ /* 12h */ + U16 MaxNumPhysicalMappedIDs;/* 12h */ } CONFIG_PAGE_SAS_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_2, SasIOUnitPage2_t, MPI_POINTER pSasIOUnitPage2_t; -#define MPI_SASIOUNITPAGE2_PAGEVERSION (0x04) +#define MPI_SASIOUNITPAGE2_PAGEVERSION (0x05) /* values for SAS IO Unit Page 2 Status field */ #define MPI_SAS_IOUNIT2_STATUS_DISABLED_PERSISTENT_MAPPINGS (0x02) @@ -2441,6 +2477,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2 #define MPI_SAS_IOUNIT2_FLAGS_NO_PHYS_MAP (0x00) #define MPI_SAS_IOUNIT2_FLAGS_DIRECT_ATTACH_PHYS_MAP (0x01) #define MPI_SAS_IOUNIT2_FLAGS_ENCLOSURE_SLOT_PHYS_MAP (0x02) +#define MPI_SAS_IOUNIT2_FLAGS_HOST_ASSIGNED_PHYS_MAP (0x07) #define MPI_SAS_IOUNIT2_FLAGS_RESERVE_ID_0_FOR_BOOT (0x10) #define MPI_SAS_IOUNIT2_FLAGS_DA_STARTING_SLOT (0x20) @@ -2473,7 +2510,7 @@ typedef struct _CONFIG_PAGE_SAS_EXPANDER_0 CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */ U8 PhysicalPort; /* 08h */ U8 Reserved1; /* 09h */ - U16 Reserved2; /* 0Ah */ + U16 EnclosureHandle; /* 0Ah */ U64 SASAddress; /* 0Ch */ U32 DiscoveryStatus; /* 14h */ U16 DevHandle; /* 18h */ @@ -2487,7 +2524,7 @@ typedef struct _CONFIG_PAGE_SAS_EXPANDER_0 } CONFIG_PAGE_SAS_EXPANDER_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_0, SasExpanderPage0_t, MPI_POINTER pSasExpanderPage0_t; -#define MPI_SASEXPANDER0_PAGEVERSION (0x02) +#define MPI_SASEXPANDER0_PAGEVERSION (0x03) /* values for SAS Expander Page 0 DiscoveryStatus field */ #define MPI_SAS_EXPANDER0_DS_LOOP_DETECTED (0x00000001) @@ -2527,9 +2564,9 @@ typedef struct _CONFIG_PAGE_SAS_EXPANDER_1 U8 NegotiatedLinkRate; /* 1Fh */ U8 PhyIdentifier; /* 20h */ U8 AttachedPhyIdentifier; /* 21h */ - U8 NumTableEntriesProg; /* 22h */ + U8 Reserved3; /* 22h */ U8 DiscoveryInfo; /* 23h */ - U32 Reserved3; /* 24h */ + U32 Reserved4; /* 24h */ } CONFIG_PAGE_SAS_EXPANDER_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_1, SasExpanderPage1_t, MPI_POINTER pSasExpanderPage1_t; @@ -2766,16 +2803,15 @@ typedef struct _CONFIG_PAGE_SAS_ENCLOSURE_0 #define MPI_LOG_0_NUM_LOG_ENTRIES (1) #endif -#define MPI_LOG_0_LOG_DATA_LENGTH (20) +#define MPI_LOG_0_LOG_DATA_LENGTH (0x1C) typedef struct _MPI_LOG_0_ENTRY { - U64 WWID; /* 00h */ - U32 TimeStamp; /* 08h */ - U32 Reserved1; /* 0Ch */ - U16 LogSequence; /* 10h */ - U16 LogEntryQualifier; /* 12h */ - U8 LogData[MPI_LOG_0_LOG_DATA_LENGTH]; /* 14h */ + U32 TimeStamp; /* 00h */ + U32 Reserved1; /* 04h */ + U16 LogSequence; /* 08h */ + U16 LogEntryQualifier; /* 0Ah */ + U8 LogData[MPI_LOG_0_LOG_DATA_LENGTH]; /* 0Ch */ } MPI_LOG_0_ENTRY, MPI_POINTER PTR_MPI_LOG_0_ENTRY, MpiLog0Entry_t, MPI_POINTER pMpiLog0Entry_t; @@ -2794,7 +2830,7 @@ typedef struct _CONFIG_PAGE_LOG_0 } CONFIG_PAGE_LOG_0, MPI_POINTER PTR_CONFIG_PAGE_LOG_0, LogPage0_t, MPI_POINTER pLogPage0_t; -#define MPI_LOG_0_PAGEVERSION (0x00) +#define MPI_LOG_0_PAGEVERSION (0x01) #endif diff --git a/drivers/message/fusion/lsi/mpi_history.txt b/drivers/message/fusion/lsi/mpi_history.txt index 1a30ef16adb..4a5f8dd1d76 100644 --- a/drivers/message/fusion/lsi/mpi_history.txt +++ b/drivers/message/fusion/lsi/mpi_history.txt @@ -6,25 +6,25 @@ Copyright (c) 2000-2005 LSI Logic Corporation. --------------------------------------- - Header Set Release Version: 01.05.10 - Header Set Release Date: 03-11-05 + Header Set Release Version: 01.05.12 + Header Set Release Date: 08-30-05 --------------------------------------- Filename Current version Prior version ---------- --------------- ------------- - mpi.h 01.05.08 01.05.07 - mpi_ioc.h 01.05.09 01.05.08 - mpi_cnfg.h 01.05.09 01.05.08 - mpi_init.h 01.05.05 01.05.04 - mpi_targ.h 01.05.05 01.05.04 + mpi.h 01.05.10 01.05.09 + mpi_ioc.h 01.05.10 01.05.09 + mpi_cnfg.h 01.05.11 01.05.10 + mpi_init.h 01.05.06 01.05.06 + mpi_targ.h 01.05.05 01.05.05 mpi_fc.h 01.05.01 01.05.01 mpi_lan.h 01.05.01 01.05.01 mpi_raid.h 01.05.02 01.05.02 mpi_tool.h 01.05.03 01.05.03 mpi_inb.h 01.05.01 01.05.01 - mpi_sas.h 01.05.01 01.05.01 - mpi_type.h 01.05.01 01.05.01 - mpi_history.txt 01.05.09 01.05.09 + mpi_sas.h 01.05.02 01.05.01 + mpi_type.h 01.05.02 01.05.01 + mpi_history.txt 01.05.12 01.05.11 * Date Version Description @@ -91,6 +91,8 @@ mpi.h * 06-24-05 01.05.08 Added function codes for SCSI IO 32 and * TargetAssistExtended requests. * Added EEDP IOCStatus codes. + * 08-03-05 01.05.09 Bumped MPI_HEADER_VERSION_UNIT. + * 08-30-05 01.05.10 Added 2 new IOCStatus codes for Target. * -------------------------------------------------------------------------- mpi_ioc.h @@ -164,6 +166,10 @@ mpi_ioc.h * Removed IOCFacts Reply EEDP Capability bit. * 06-24-05 01.05.09 Added 5 new IOCFacts Reply IOCCapabilities bits. * Added Max SATA Targets to SAS Discovery Error event. + * 08-30-05 01.05.10 Added 4 new events and their event data structures. + * Added new ReasonCode value for SAS Device Status Change + * event. + * Added new family code for FC949E. * -------------------------------------------------------------------------- mpi_cnfg.h @@ -402,6 +408,23 @@ mpi_cnfg.h * Added OwnerDevHandle and Flags field to SAS PHY Page 0. * Added IOC GPIO Flags define to SAS Enclosure Page 0. * Fixed the value for MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT. + * 08-03-05 01.05.10 Removed ISDataScrubRate and ISResyncRate from + * Manufacturing Page 4. + * Added MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE bit. + * Added NumDevsPerEnclosure field to SAS IO Unit page 2. + * Added MPI_SAS_IOUNIT2_FLAGS_HOST_ASSIGNED_PHYS_MAP + * define. + * Added EnclosureHandle field to SAS Expander page 0. + * Removed redundant NumTableEntriesProg field from SAS + * Expander Page 1. + * 08-30-05 01.05.11 Added DeviceID for FC949E and changed the DeviceID for + * SAS1078. + * Added more defines for Manufacturing Page 4 Flags field. + * Added more defines for IOCSettings and added + * ExpanderSpinup field to Bios Page 1. + * Added postpone SATA Init bit to SAS IO Unit Page 1 + * ControlFlags. + * Changed LogEntry format for Log Page 0. * -------------------------------------------------------------------------- mpi_init.h @@ -442,6 +465,8 @@ mpi_init.h * addressing. * 06-24-05 01.05.05 Added SCSI IO 32 structures and defines. * Added four new defines for SEP SlotStatus. + * 08-03-05 01.05.06 Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them + * unique in the first 32 characters. * -------------------------------------------------------------------------- mpi_targ.h @@ -582,6 +607,9 @@ mpi_inb.h mpi_sas.h * 08-19-04 01.05.01 Original release. + * 08-30-05 01.05.02 Added DeviceInfo bit for SEP. + * Added PrimFlags and Primitive field to SAS IO Unit + * Control request, and added a new operation code. * -------------------------------------------------------------------------- mpi_type.h @@ -592,24 +620,25 @@ mpi_type.h * 08-08-01 01.02.01 Original release for v1.2 work. * 05-11-04 01.03.01 Original release for MPI v1.3. * 08-19-04 01.05.01 Original release for MPI v1.5. + * 08-30-05 01.05.02 Added PowerPC option to #ifdef's. * -------------------------------------------------------------------------- mpi_history.txt Parts list history -Filename 01.05.10 01.05.09 ----------- -------- -------- -mpi.h 01.05.08 01.05.07 -mpi_ioc.h 01.05.09 01.05.08 -mpi_cnfg.h 01.05.09 01.05.08 -mpi_init.h 01.05.05 01.05.04 -mpi_targ.h 01.05.05 01.05.04 -mpi_fc.h 01.05.01 01.05.01 -mpi_lan.h 01.05.01 01.05.01 -mpi_raid.h 01.05.02 01.05.02 -mpi_tool.h 01.05.03 01.05.03 -mpi_inb.h 01.05.01 01.05.01 -mpi_sas.h 01.05.01 01.05.01 -mpi_type.h 01.05.01 01.05.01 +Filename 01.05.12 01.05.11 01.05.10 01.05.09 +---------- -------- -------- -------- -------- +mpi.h 01.05.10 01.05.09 01.05.08 01.05.07 +mpi_ioc.h 01.05.10 01.05.09 01.05.09 01.05.08 +mpi_cnfg.h 01.05.11 01.05.10 01.05.09 01.05.08 +mpi_init.h 01.05.06 01.05.06 01.05.05 01.05.04 +mpi_targ.h 01.05.05 01.05.05 01.05.05 01.05.04 +mpi_fc.h 01.05.01 01.05.01 01.05.01 01.05.01 +mpi_lan.h 01.05.01 01.05.01 01.05.01 01.05.01 +mpi_raid.h 01.05.02 01.05.02 01.05.02 01.05.02 +mpi_tool.h 01.05.03 01.05.03 01.05.03 01.05.03 +mpi_inb.h 01.05.01 01.05.01 01.05.01 01.05.01 +mpi_sas.h 01.05.02 01.05.01 01.05.01 01.05.01 +mpi_type.h 01.05.02 01.05.01 01.05.01 01.05.01 Filename 01.05.08 01.05.07 01.05.06 01.05.05 01.05.04 01.05.03 ---------- -------- -------- -------- -------- -------- -------- diff --git a/drivers/message/fusion/lsi/mpi_init.h b/drivers/message/fusion/lsi/mpi_init.h index d5af75afbd9..68941f459ca 100644 --- a/drivers/message/fusion/lsi/mpi_init.h +++ b/drivers/message/fusion/lsi/mpi_init.h @@ -6,7 +6,7 @@ * Title: MPI initiator mode messages and structures * Creation Date: June 8, 2000 * - * mpi_init.h Version: 01.05.05 + * mpi_init.h Version: 01.05.06 * * Version History * --------------- @@ -50,6 +50,8 @@ * addressing. * 06-24-05 01.05.05 Added SCSI IO 32 structures and defines. * Added four new defines for SEP SlotStatus. + * 08-03-05 01.05.06 Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them + * unique in the first 32 characters. * -------------------------------------------------------------------------- */ @@ -290,8 +292,8 @@ typedef struct _MSG_SCSI_IO32_REQUEST /* SCSI IO 32 MsgFlags bits */ #define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH (0x01) -#define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH_32 (0x00) -#define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH_64 (0x01) +#define MPI_SCSIIO32_MSGFLGS_32_SENSE_WIDTH (0x00) +#define MPI_SCSIIO32_MSGFLGS_64_SENSE_WIDTH (0x01) #define MPI_SCSIIO32_MSGFLGS_SENSE_LOCATION (0x02) #define MPI_SCSIIO32_MSGFLGS_SENSE_LOC_HOST (0x00) diff --git a/drivers/message/fusion/lsi/mpi_ioc.h b/drivers/message/fusion/lsi/mpi_ioc.h index 93b70e2b426..2c5f43fa7c7 100644 --- a/drivers/message/fusion/lsi/mpi_ioc.h +++ b/drivers/message/fusion/lsi/mpi_ioc.h @@ -6,7 +6,7 @@ * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages * Creation Date: August 11, 2000 * - * mpi_ioc.h Version: 01.05.09 + * mpi_ioc.h Version: 01.05.10 * * Version History * --------------- @@ -83,6 +83,10 @@ * Removed IOCFacts Reply EEDP Capability bit. * 06-24-05 01.05.09 Added 5 new IOCFacts Reply IOCCapabilities bits. * Added Max SATA Targets to SAS Discovery Error event. + * 08-30-05 01.05.10 Added 4 new events and their event data structures. + * Added new ReasonCode value for SAS Device Status Change + * event. + * Added new family code for FC949E. * -------------------------------------------------------------------------- */ @@ -464,6 +468,10 @@ typedef struct _MSG_EVENT_ACK_REPLY #define MPI_EVENT_PERSISTENT_TABLE_FULL (0x00000011) #define MPI_EVENT_SAS_PHY_LINK_STATUS (0x00000012) #define MPI_EVENT_SAS_DISCOVERY_ERROR (0x00000013) +#define MPI_EVENT_IR_RESYNC_UPDATE (0x00000014) +#define MPI_EVENT_IR2 (0x00000015) +#define MPI_EVENT_SAS_DISCOVERY (0x00000016) +#define MPI_EVENT_LOG_ENTRY_ADDED (0x00000021) /* AckRequired field values */ @@ -480,6 +488,29 @@ typedef struct _EVENT_DATA_EVENT_CHANGE } EVENT_DATA_EVENT_CHANGE, MPI_POINTER PTR_EVENT_DATA_EVENT_CHANGE, EventDataEventChange_t, MPI_POINTER pEventDataEventChange_t; +/* LogEntryAdded Event data */ + +/* this structure matches MPI_LOG_0_ENTRY in mpi_cnfg.h */ +#define MPI_EVENT_DATA_LOG_ENTRY_DATA_LENGTH (0x1C) +typedef struct _EVENT_DATA_LOG_ENTRY +{ + U32 TimeStamp; /* 00h */ + U32 Reserved1; /* 04h */ + U16 LogSequence; /* 08h */ + U16 LogEntryQualifier; /* 0Ah */ + U8 LogData[MPI_EVENT_DATA_LOG_ENTRY_DATA_LENGTH]; /* 0Ch */ +} EVENT_DATA_LOG_ENTRY, MPI_POINTER PTR_EVENT_DATA_LOG_ENTRY, + MpiEventDataLogEntry_t, MPI_POINTER pMpiEventDataLogEntry_t; + +typedef struct _EVENT_DATA_LOG_ENTRY_ADDED +{ + U16 LogSequence; /* 00h */ + U16 Reserved1; /* 02h */ + U32 Reserved2; /* 04h */ + EVENT_DATA_LOG_ENTRY LogEntry; /* 08h */ +} EVENT_DATA_LOG_ENTRY_ADDED, MPI_POINTER PTR_EVENT_DATA_LOG_ENTRY_ADDED, + MpiEventDataLogEntryAdded_t, MPI_POINTER pMpiEventDataLogEntryAdded_t; + /* SCSI Event data for Port, Bus and Device forms */ typedef struct _EVENT_DATA_SCSI @@ -538,6 +569,7 @@ typedef struct _EVENT_DATA_SAS_DEVICE_STATUS_CHANGE #define MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA (0x05) #define MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED (0x06) #define MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED (0x07) +#define MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET (0x08) /* SCSI Event data for Queue Full event */ @@ -579,6 +611,79 @@ typedef struct _EVENT_DATA_RAID #define MPI_EVENT_RAID_RC_SMART_DATA (0x0A) #define MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED (0x0B) + +/* MPI Integrated RAID Resync Update Event data */ + +typedef struct _MPI_EVENT_DATA_IR_RESYNC_UPDATE +{ + U8 VolumeID; /* 00h */ + U8 VolumeBus; /* 01h */ + U8 ResyncComplete; /* 02h */ + U8 Reserved1; /* 03h */ + U32 Reserved2; /* 04h */ +} MPI_EVENT_DATA_IR_RESYNC_UPDATE, + MPI_POINTER PTR_MPI_EVENT_DATA_IR_RESYNC_UPDATE, + MpiEventDataIrResyncUpdate_t, MPI_POINTER pMpiEventDataIrResyncUpdate_t; + +/* MPI IR2 Event data */ + +/* MPI_LD_STATE or MPI_PD_STATE */ +typedef struct _IR2_STATE_CHANGED +{ + U16 PreviousState; /* 00h */ + U16 NewState; /* 02h */ +} IR2_STATE_CHANGED, MPI_POINTER PTR_IR2_STATE_CHANGED; + +typedef struct _IR2_PD_INFO +{ + U16 DeviceHandle; /* 00h */ + U8 TruncEnclosureHandle; /* 02h */ + U8 TruncatedSlot; /* 03h */ +} IR2_PD_INFO, MPI_POINTER PTR_IR2_PD_INFO; + +typedef union _MPI_IR2_RC_EVENT_DATA +{ + IR2_STATE_CHANGED StateChanged; + U32 Lba; + IR2_PD_INFO PdInfo; +} MPI_IR2_RC_EVENT_DATA, MPI_POINTER PTR_MPI_IR2_RC_EVENT_DATA; + +typedef struct _MPI_EVENT_DATA_IR2 +{ + U8 TargetID; /* 00h */ + U8 Bus; /* 01h */ + U8 ReasonCode; /* 02h */ + U8 PhysDiskNum; /* 03h */ + MPI_IR2_RC_EVENT_DATA IR2EventData; /* 04h */ +} MPI_EVENT_DATA_IR2, MPI_POINTER PTR_MPI_EVENT_DATA_IR2, + MpiEventDataIR2_t, MPI_POINTER pMpiEventDataIR2_t; + +/* MPI IR2 Event data ReasonCode values */ +#define MPI_EVENT_IR2_RC_LD_STATE_CHANGED (0x01) +#define MPI_EVENT_IR2_RC_PD_STATE_CHANGED (0x02) +#define MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL (0x03) +#define MPI_EVENT_IR2_RC_PD_INSERTED (0x04) +#define MPI_EVENT_IR2_RC_PD_REMOVED (0x05) +#define MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED (0x06) +#define MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR (0x07) + +/* defines for logical disk states */ +#define MPI_LD_STATE_OPTIMAL (0x00) +#define MPI_LD_STATE_DEGRADED (0x01) +#define MPI_LD_STATE_FAILED (0x02) +#define MPI_LD_STATE_MISSING (0x03) +#define MPI_LD_STATE_OFFLINE (0x04) + +/* defines for physical disk states */ +#define MPI_PD_STATE_ONLINE (0x00) +#define MPI_PD_STATE_MISSING (0x01) +#define MPI_PD_STATE_NOT_COMPATIBLE (0x02) +#define MPI_PD_STATE_FAILED (0x03) +#define MPI_PD_STATE_INITIALIZING (0x04) +#define MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST (0x05) +#define MPI_PD_STATE_FAILED_AT_HOST_REQUEST (0x06) +#define MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON (0xFF) + /* MPI Link Status Change Event data */ typedef struct _EVENT_DATA_LINK_STATUS @@ -660,6 +765,20 @@ typedef struct _EVENT_DATA_SAS_PHY_LINK_STATUS #define MPI_EVENT_SAS_PLS_LR_RATE_1_5 (0x08) #define MPI_EVENT_SAS_PLS_LR_RATE_3_0 (0x09) +/* SAS Discovery Event data */ + +typedef struct _EVENT_DATA_SAS_DISCOVERY +{ + U32 DiscoveryStatus; /* 00h */ + U32 Reserved1; /* 04h */ +} EVENT_DATA_SAS_DISCOVERY, MPI_POINTER PTR_EVENT_DATA_SAS_DISCOVERY, + EventDataSasDiscovery_t, MPI_POINTER pEventDataSasDiscovery_t; + +#define MPI_EVENT_SAS_DSCVRY_COMPLETE (0x00000000) +#define MPI_EVENT_SAS_DSCVRY_IN_PROGRESS (0x00000001) +#define MPI_EVENT_SAS_DSCVRY_PHY_BITS_MASK (0xFFFF0000) +#define MPI_EVENT_SAS_DSCVRY_PHY_BITS_SHIFT (16) + /* SAS Discovery Errror Event data */ typedef struct _EVENT_DATA_DISCOVERY_ERROR @@ -869,6 +988,7 @@ typedef struct _MPI_FW_HEADER #define MPI_FW_HEADER_PID_FAMILY_919XL_FC (0x0003) /* 919XL and 929XL */ #define MPI_FW_HEADER_PID_FAMILY_939X_FC (0x0004) /* 939X and 949X */ #define MPI_FW_HEADER_PID_FAMILY_959_FC (0x0005) +#define MPI_FW_HEADER_PID_FAMILY_949E_FC (0x0006) /* SAS */ #define MPI_FW_HEADER_PID_FAMILY_1064_SAS (0x0001) #define MPI_FW_HEADER_PID_FAMILY_1068_SAS (0x0002) diff --git a/drivers/message/fusion/lsi/mpi_log_fc.h b/drivers/message/fusion/lsi/mpi_log_fc.h new file mode 100644 index 00000000000..dc98d46f907 --- /dev/null +++ b/drivers/message/fusion/lsi/mpi_log_fc.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2000-2001 LSI Logic Corporation. All rights reserved. + * + * NAME: fc_log.h + * SUMMARY: MPI IocLogInfo definitions for the SYMFC9xx chips + * DESCRIPTION: Contains the enumerated list of values that may be returned + * in the IOCLogInfo field of a MPI Default Reply Message. + * + * CREATION DATE: 6/02/2000 + * ID: $Id: fc_log.h,v 4.6 2001/07/26 14:41:33 sschremm Exp $ + */ + + +/* + * MpiIocLogInfo_t enum + * + * These 32 bit values are used in the IOCLogInfo field of the MPI reply + * messages. + * The value is 0xabcccccc where + * a = The type of log info as per the MPI spec. Since these codes are + * all for Fibre Channel this value will always be 2. + * b = Specifies a subclass of the firmware where + * 0 = FCP Initiator + * 1 = FCP Target + * 2 = LAN + * 3 = MPI Message Layer + * 4 = FC Link + * 5 = Context Manager + * 6 = Invalid Field Offset + * 7 = State Change Info + * all others are reserved for future use + * c = A specific value within the subclass. + * + * NOTE: Any new values should be added to the end of each subclass so that the + * codes remain consistent across firmware releases. + */ +typedef enum _MpiIocLogInfoFc +{ + MPI_IOCLOGINFO_FC_INIT_BASE = 0x20000000, + MPI_IOCLOGINFO_FC_INIT_ERROR_OUT_OF_ORDER_FRAME = 0x20000001, /* received an out of order frame - unsupported */ + MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_START_OF_FRAME = 0x20000002, /* Bad Rx Frame, bad start of frame primative */ + MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_END_OF_FRAME = 0x20000003, /* Bad Rx Frame, bad end of frame primative */ + MPI_IOCLOGINFO_FC_INIT_ERROR_OVER_RUN = 0x20000004, /* Bad Rx Frame, overrun */ + MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OTHER = 0x20000005, /* Other errors caught by IOC which require retries */ + MPI_IOCLOGINFO_FC_INIT_ERROR_SUBPROC_DEAD = 0x20000006, /* Main processor could not initialize sub-processor */ + MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OVERRUN = 0x20000007, /* Scatter Gather overrun */ + MPI_IOCLOGINFO_FC_INIT_ERROR_RX_BAD_STATUS = 0x20000008, /* Receiver detected context mismatch via invalid header */ + MPI_IOCLOGINFO_FC_INIT_ERROR_RX_UNEXPECTED_FRAME= 0x20000009, /* CtxMgr detected unsupported frame type */ + MPI_IOCLOGINFO_FC_INIT_ERROR_LINK_FAILURE = 0x2000000A, /* Link failure occurred */ + MPI_IOCLOGINFO_FC_INIT_ERROR_TX_TIMEOUT = 0x2000000B, /* Transmitter timeout error */ + + MPI_IOCLOGINFO_FC_TARGET_BASE = 0x21000000, + MPI_IOCLOGINFO_FC_TARGET_NO_PDISC = 0x21000001, /* not sent because we are waiting for a PDISC from the initiator */ + MPI_IOCLOGINFO_FC_TARGET_NO_LOGIN = 0x21000002, /* not sent because we are not logged in to the remote node */ + MPI_IOCLOGINFO_FC_TARGET_DOAR_KILLED_BY_LIP = 0x21000003, /* Data Out, Auto Response, not sent due to a LIP */ + MPI_IOCLOGINFO_FC_TARGET_DIAR_KILLED_BY_LIP = 0x21000004, /* Data In, Auto Response, not sent due to a LIP */ + MPI_IOCLOGINFO_FC_TARGET_DIAR_MISSING_DATA = 0x21000005, /* Data In, Auto Response, missing data frames */ + MPI_IOCLOGINFO_FC_TARGET_DONR_KILLED_BY_LIP = 0x21000006, /* Data Out, No Response, not sent due to a LIP */ + MPI_IOCLOGINFO_FC_TARGET_WRSP_KILLED_BY_LIP = 0x21000007, /* Auto-response after a write not sent due to a LIP */ + MPI_IOCLOGINFO_FC_TARGET_DINR_KILLED_BY_LIP = 0x21000008, /* Data In, No Response, not completed due to a LIP */ + MPI_IOCLOGINFO_FC_TARGET_DINR_MISSING_DATA = 0x21000009, /* Data In, No Response, missing data frames */ + MPI_IOCLOGINFO_FC_TARGET_MRSP_KILLED_BY_LIP = 0x2100000a, /* Manual Response not sent due to a LIP */ + MPI_IOCLOGINFO_FC_TARGET_NO_CLASS_3 = 0x2100000b, /* not sent because remote node does not support Class 3 */ + MPI_IOCLOGINFO_FC_TARGET_LOGIN_NOT_VALID = 0x2100000c, /* not sent because login to remote node not validated */ + MPI_IOCLOGINFO_FC_TARGET_FROM_OUTBOUND = 0x2100000e, /* cleared from the outbound queue after a logout */ + MPI_IOCLOGINFO_FC_TARGET_WAITING_FOR_DATA_IN = 0x2100000f, /* cleared waiting for data after a logout */ + + MPI_IOCLOGINFO_FC_LAN_BASE = 0x22000000, + MPI_IOCLOGINFO_FC_LAN_TRANS_SGL_MISSING = 0x22000001, /* Transaction Context Sgl Missing */ + MPI_IOCLOGINFO_FC_LAN_TRANS_WRONG_PLACE = 0x22000002, /* Transaction Context found before an EOB */ + MPI_IOCLOGINFO_FC_LAN_TRANS_RES_BITS_SET = 0x22000003, /* Transaction Context value has reserved bits set */ + MPI_IOCLOGINFO_FC_LAN_WRONG_SGL_FLAG = 0x22000004, /* Invalid SGL Flags */ + + MPI_IOCLOGINFO_FC_MSG_BASE = 0x23000000, + + MPI_IOCLOGINFO_FC_LINK_BASE = 0x24000000, + MPI_IOCLOGINFO_FC_LINK_LOOP_INIT_TIMEOUT = 0x24000001, /* Loop initialization timed out */ + MPI_IOCLOGINFO_FC_LINK_ALREADY_INITIALIZED = 0x24000002, /* Another system controller already initialized the loop */ + MPI_IOCLOGINFO_FC_LINK_LINK_NOT_ESTABLISHED = 0x24000003, /* Not synchronized to signal or still negotiating (possible cable problem) */ + MPI_IOCLOGINFO_FC_LINK_CRC_ERROR = 0x24000004, /* CRC check detected error on received frame */ + + MPI_IOCLOGINFO_FC_CTX_BASE = 0x25000000, + + MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET = 0x26000000, /* The lower 24 bits give the byte offset of the field in the request message that is invalid */ + MPI_IOCLOGINFO_FC_INVALID_FIELD_MAX_OFFSET = 0x26ffffff, + + MPI_IOCLOGINFO_FC_STATE_CHANGE = 0x27000000 /* The lower 24 bits give additional information concerning state change */ + +} MpiIocLogInfoFc_t; diff --git a/drivers/message/fusion/lsi/mpi_log_sas.h b/drivers/message/fusion/lsi/mpi_log_sas.h new file mode 100644 index 00000000000..9259d1ad6e6 --- /dev/null +++ b/drivers/message/fusion/lsi/mpi_log_sas.h @@ -0,0 +1,162 @@ + +/*************************************************************************** + * * + * Copyright 2003 LSI Logic Corporation. All rights reserved. * + * * + * This file is confidential and a trade secret of LSI Logic. The * + * receipt of or possession of this file does not convey any rights to * + * reproduce or disclose its contents or to manufacture, use, or sell * + * anything it may describe, in whole, or in part, without the specific * + * written consent of LSI Logic Corporation. * + * * + *************************************************************************** + * + * Name: iopiIocLogInfo.h + * Title: SAS Firmware IOP Interface IOC Log Info Definitions + * Programmer: Guy Kendall + * Creation Date: September 24, 2003 + * + * Version History + * --------------- + * + * Last Updated + * ------------- + * Version %version: 22 % + * Date Updated %date_modified: % + * Programmer %created_by: nperucca % + * + * Date Who Description + * -------- --- ------------------------------------------------------- + * 09/24/03 GWK Initial version + * + * + * Description + * ------------ + * This include file contains SAS firmware interface IOC Log Info codes + * + *------------------------------------------------------------------------- + */ + +#ifndef IOPI_IOCLOGINFO_H_INCLUDED +#define IOPI_IOCLOGINFO_H_INCLUDED + + +/****************************************************************************/ +/* IOC LOGINFO defines, 0x00000000 - 0x0FFFFFFF */ +/* Format: */ +/* Bits 31-28: MPI_IOCLOGINFO_TYPE_SAS (3) */ +/* Bits 27-24: IOC_LOGINFO_ORIGINATOR: 0=IOP, 1=PL, 2=IR */ +/* Bits 23-16: LOGINFO_CODE */ +/* Bits 15-0: LOGINFO_CODE Specific */ +/****************************************************************************/ + +/****************************************************************************/ +/* IOC_LOGINFO_ORIGINATOR defines */ +/****************************************************************************/ +#define IOC_LOGINFO_ORIGINATOR_IOP (0x00000000) +#define IOC_LOGINFO_ORIGINATOR_PL (0x01000000) +#define IOC_LOGINFO_ORIGINATOR_IR (0x02000000) + +/****************************************************************************/ +/* LOGINFO_CODE defines */ +/****************************************************************************/ +#define IOC_LOGINFO_CODE_MASK (0x00FF0000) +#define IOC_LOGINFO_CODE_SHIFT (16) + +/****************************************************************************/ +/* IOP LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = IOP */ +/****************************************************************************/ +#define IOP_LOGINFO_CODE_INVALID_SAS_ADDRESS (0x00010000) +#define IOP_LOGINFO_CODE_UNUSED2 (0x00020000) +#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x00030000) +#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_RT (0x00030100) /* Route Table Entry not found */ +#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PN (0x00030200) /* Invalid Page Number */ +#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM (0x00030300) /* Invalid FORM */ +#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x00030400) /* Invalid Page Type */ +#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DNM (0x00030500) /* Device Not Mapped */ +#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PERSIST (0x00030600) /* Persistent Page not found */ +#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DEFAULT (0x00030700) /* Default Page not found */ +#define IOP_LOGINFO_CODE_TASK_TERMINATED (0x00050000) + + +/****************************************************************************/ +/* PL LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = PL */ +/****************************************************************************/ +#define PL_LOGINFO_CODE_OPEN_FAILURE (0x00010000) +#define PL_LOGINFO_CODE_INVALID_SGL (0x00020000) +#define PL_LOGINFO_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00030000) +#define PL_LOGINFO_CODE_FRAME_XFER_ERROR (0x00040000) +#define PL_LOGINFO_CODE_TX_FM_CONNECTED_LOW (0x00050000) +#define PL_LOGINFO_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET (0x00060000) +#define PL_LOGINFO_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR (0x00070000) +#define PL_LOGINFO_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR (0x00080000) +#define PL_LOGINFO_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS (0x00090000) +#define PL_LOGINFO_CODE_RX_FM_INVALID_MESSAGE (0x000A0000) +#define PL_LOGINFO_CODE_RX_CTX_MESSAGE_VALID_ERROR (0x000B0000) +#define PL_LOGINFO_CODE_RX_FM_CURRENT_FRAME_ERROR (0x000C0000) +#define PL_LOGINFO_CODE_SATA_LINK_DOWN (0x000D0000) +#define PL_LOGINFO_CODE_DISCOVERY_SATA_INIT_W_IOS (0x000E0000) +#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x000F0000) +#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x000F0100) /* Invalid Page Type */ +#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NUM_PHYS (0x000F0200) /* Invalid Number of Phys */ +#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NOT_IMP (0x000F0300) /* Case Not Handled */ +#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_DEV (0x000F0400) /* No Device Found */ +#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM (0x000F0500) /* Invalid FORM */ +#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PHY (0x000F0600) /* Invalid Phy */ +#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_OWNER (0x000F0700) /* No Owner Found */ +#define PL_LOGINFO_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00100000) +#define PL_LOGINFO_CODE_RESET (0x00110000) +#define PL_LOGINFO_CODE_ABORT (0x00120000) +#define PL_LOGINFO_CODE_IO_NOT_YET_EXECUTED (0x00130000) +#define PL_LOGINFO_CODE_IO_EXECUTED (0x00140000) +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE (0x00000100) +#define PL_LOGINFO_SUB_CODE_INVALID_SGL (0x00000200) +#define PL_LOGINFO_SUB_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00000300) +#define PL_LOGINFO_SUB_CODE_FRAME_XFER_ERROR (0x00000400) +#define PL_LOGINFO_SUB_CODE_TX_FM_CONNECTED_LOW (0x00000500) +#define PL_LOGINFO_SUB_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET (0x00000600) +#define PL_LOGINFO_SUB_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR (0x00000700) +#define PL_LOGINFO_SUB_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR (0x00000800) +#define PL_LOGINFO_SUB_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS (0x00000900) +#define PL_LOGINFO_SUB_CODE_RX_FM_INVALID_MESSAGE (0x00000A00) +#define PL_LOGINFO_SUB_CODE_RX_CTX_MESSAGE_VALID_ERROR (0x00000B00) +#define PL_LOGINFO_SUB_CODE_RX_FM_CURRENT_FRAME_ERROR (0x00000C00) +#define PL_LOGINFO_SUB_CODE_SATA_LINK_DOWN (0x00000D00) +#define PL_LOGINFO_SUB_CODE_DISCOVERY_SATA_INIT_W_IOS (0x00000E00) +#define PL_LOGINFO_SUB_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00001000) + + +#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE (0x00200000) /* Can't get SMP Frame */ +#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR (0x00200001) /* Error occured on SMP Read */ +#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR (0x00200002) /* Error occured on SMP Write */ +#define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL (0x00200004) /* Encl Mgmt services not available for this WWID */ +#define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED (0x00200005) /* Address Mode not suppored */ +#define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM (0x00200006) /* Invalid Slot Number in SEP Msg */ +#define PL_LOGINFO_CODE_ENCL_MGMT_SGPIO_NOT_PRESENT (0x00200007) /* SGPIO not present/enabled */ + +#define PL_LOGINFO_DA_SEP_NOT_PRESENT (0x00200100) /* SEP not present when msg received */ +#define PL_LOGINFO_DA_SEP_SINGLE_THREAD_ERROR (0x00200101) /* Can only accept 1 msg at a time */ +#define PL_LOGINFO_DA_SEP_ISTWI_INTR_IN_IDLE_STATE (0x00200102) /* ISTWI interrupt recvd. while IDLE */ +#define PL_LOGINFO_DA_SEP_RECEIVED_NACK_FROM_SLAVE (0x00200103) /* SEP NACK'd, it is busy */ +#define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM (0x00200104) /* SEP stopped or sent bad chksum in Hdr */ +#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1 (0x00200105) /* SEP returned unknown scsi status */ +#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2 (0x00200106) /* SEP returned unknown scsi status */ +#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP (0x00200107) /* SEP returned bad chksum after STOP */ +#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP_GETDATA (0x00200108) /* SEP returned bad chksum after STOP while gettin data*/ + + +/****************************************************************************/ +/* IR LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = IR */ +/****************************************************************************/ +#define IR_LOGINFO_CODE_UNUSED1 (0x00010000) +#define IR_LOGINFO_CODE_UNUSED2 (0x00020000) + +/****************************************************************************/ +/* Defines for convienence */ +/****************************************************************************/ +#define IOC_LOGINFO_PREFIX_IOP ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_IOP) +#define IOC_LOGINFO_PREFIX_PL ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_PL) +#define IOC_LOGINFO_PREFIX_IR ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_IR) + +#endif /* end of file */ + diff --git a/drivers/message/fusion/lsi/mpi_sas.h b/drivers/message/fusion/lsi/mpi_sas.h index 230fa69b535..70514867bdd 100644 --- a/drivers/message/fusion/lsi/mpi_sas.h +++ b/drivers/message/fusion/lsi/mpi_sas.h @@ -6,7 +6,7 @@ * Title: MPI Serial Attached SCSI structures and definitions * Creation Date: August 19, 2004 * - * mpi_sas.h Version: 01.05.01 + * mpi_sas.h Version: 01.05.02 * * Version History * --------------- @@ -14,6 +14,9 @@ * Date Version Description * -------- -------- ------------------------------------------------------ * 08-19-04 01.05.01 Original release. + * 08-30-05 01.05.02 Added DeviceInfo bit for SEP. + * Added PrimFlags and Primitive field to SAS IO Unit + * Control request, and added a new operation code. * -------------------------------------------------------------------------- */ @@ -51,6 +54,7 @@ * Values for the SAS DeviceInfo field used in SAS Device Status Change Event * data and SAS IO Unit Configuration pages. */ +#define MPI_SAS_DEVICE_INFO_SEP (0x00004000) #define MPI_SAS_DEVICE_INFO_ATAPI_DEVICE (0x00002000) #define MPI_SAS_DEVICE_INFO_LSI_DEVICE (0x00001000) #define MPI_SAS_DEVICE_INFO_DIRECT_ATTACH (0x00000800) @@ -212,20 +216,26 @@ typedef struct _MSG_SAS_IOUNIT_CONTROL_REQUEST U8 TargetID; /* 0Ch */ U8 Bus; /* 0Dh */ U8 PhyNum; /* 0Eh */ - U8 Reserved4; /* 0Fh */ - U32 Reserved5; /* 10h */ + U8 PrimFlags; /* 0Fh */ + U32 Primitive; /* 10h */ U64 SASAddress; /* 14h */ - U32 Reserved6; /* 1Ch */ + U32 Reserved4; /* 1Ch */ } MSG_SAS_IOUNIT_CONTROL_REQUEST, MPI_POINTER PTR_MSG_SAS_IOUNIT_CONTROL_REQUEST, SasIoUnitControlRequest_t, MPI_POINTER pSasIoUnitControlRequest_t; /* values for the Operation field */ -#define MPI_SAS_OP_CLEAR_NOT_PRESENT (0x01) -#define MPI_SAS_OP_CLEAR_ALL_PERSISTENT (0x02) -#define MPI_SAS_OP_PHY_LINK_RESET (0x06) -#define MPI_SAS_OP_PHY_HARD_RESET (0x07) -#define MPI_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08) -#define MPI_SAS_OP_MAP_CURRENT (0x09) +#define MPI_SAS_OP_CLEAR_NOT_PRESENT (0x01) +#define MPI_SAS_OP_CLEAR_ALL_PERSISTENT (0x02) +#define MPI_SAS_OP_PHY_LINK_RESET (0x06) +#define MPI_SAS_OP_PHY_HARD_RESET (0x07) +#define MPI_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08) +#define MPI_SAS_OP_MAP_CURRENT (0x09) +#define MPI_SAS_OP_SEND_PRIMITIVE (0x0A) + +/* values for the PrimFlags field */ +#define MPI_SAS_PRIMFLAGS_SINGLE (0x08) +#define MPI_SAS_PRIMFLAGS_TRIPLE (0x02) +#define MPI_SAS_PRIMFLAGS_REDUNDANT (0x01) /* SAS IO Unit Control Reply */ -- GitLab From e6bc863cf25f30ed8e2a4d41b76d5688f8efaee9 Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Fri, 13 Jan 2006 16:33:59 -0700 Subject: [PATCH 209/465] [SCSI] scsi_transport_sas: mapping the rphy channel equal to the port identifier We will be mapping the RAID volumes in mptsas to a reserved channel that is one larger than the anticapated number of ports on the direct attached host adapter. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_sas.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index fb6641b42df..a3e0b7bc2d7 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -638,7 +638,7 @@ int sas_rphy_add(struct sas_rphy *rphy) mutex_unlock(&sas_host->lock); if (rphy->scsi_target_id != -1) { - scsi_scan_target(&rphy->dev, parent->number, + scsi_scan_target(&rphy->dev, parent->port_identifier, rphy->scsi_target_id, ~0, 0); } @@ -745,9 +745,9 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel, if (rphy->scsi_target_id == -1) continue; - if ((channel == SCAN_WILD_CARD || channel == parent->number) && + if ((channel == SCAN_WILD_CARD || channel == parent->port_identifier) && (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) { - scsi_scan_target(&rphy->dev, parent->number, + scsi_scan_target(&rphy->dev, parent->port_identifier, rphy->scsi_target_id, lun, 1); } } -- GitLab From 569b11dcfa9d764e775f9e964a680c32265ab7f2 Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Fri, 13 Jan 2006 16:25:29 -0700 Subject: [PATCH 210/465] [SCSI] fusion - fix pci express bug The fix is to write 'MPI_HIM_DIM' to the Host Interrupt Mask register, when enabling interrupts. Instead of the tilde of MPI_HIM_RIM. Apparently writing '1's to some of the reserved bits was causing all the bits to go to `1`, which effectly disabled all interrupts. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 33213370027..d890b2b8a93 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -1630,7 +1630,7 @@ mpt_resume(struct pci_dev *pdev) pci_enable_device(pdev); /* enable interrupts */ - CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM)); + CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM); ioc->active = 1; /* F/W not running */ @@ -1723,7 +1723,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */ dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n", ioc->alt_ioc->name)); - CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM)); + CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM); ioc->alt_ioc->active = 1; } @@ -1839,7 +1839,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) if (ret == 0) { /* Enable! (reply interrupt) */ - CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM)); + CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM); ioc->active = 1; } @@ -1847,7 +1847,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) /* (re)Enable alt-IOC! (reply interrupt) */ dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n", ioc->alt_ioc->name)); - CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM)); + CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM); ioc->alt_ioc->active = 1; } -- GitLab From 3759b788498ffc0b2563181567af4c82d983f921 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sat, 14 Jan 2006 09:28:07 -0600 Subject: [PATCH 211/465] [SCSI] mptfc: need to select transport attrs Now that mptfc actually uses the transport class, it can't be built without it. Signed-off-by: James Bottomley --- drivers/message/fusion/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig index 1883d22cffe..e67cf15e9c3 100644 --- a/drivers/message/fusion/Kconfig +++ b/drivers/message/fusion/Kconfig @@ -23,6 +23,7 @@ config FUSION_FC tristate "Fusion MPT ScsiHost drivers for FC" depends on PCI && SCSI select FUSION + select SCSI_FC_ATTRS ---help--- SCSI HOST support for a Fiber Channel host adapters. -- GitLab From a12e25bd59e36d12dcd026ffa3c65d48b5cf5442 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Wed, 11 Jan 2006 08:39:45 -0500 Subject: [PATCH 212/465] [SCSI] sem2mutex 3w-[x9]xxx Convert a the 3w-9xxx.c and 3w-xxxx.c drivers to use mutexes instead of semaphores. Untested, but compiles and looks obviously correct. Signed-off-by: Jes Sorensen Signed-off-by: James Bottomley --- drivers/scsi/3w-9xxx.c | 7 ++++--- drivers/scsi/3w-9xxx.h | 2 +- drivers/scsi/3w-xxxx.c | 7 ++++--- drivers/scsi/3w-xxxx.h | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index 3ff74f47224..31c49754227 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -73,6 +73,7 @@ #include #include #include +#include #include #include #include @@ -615,7 +616,7 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int void __user *argp = (void __user *)arg; /* Only let one of these through at a time */ - if (down_interruptible(&tw_dev->ioctl_sem)) { + if (mutex_lock_interruptible(&tw_dev->ioctl_lock)) { retval = TW_IOCTL_ERROR_OS_EINTR; goto out; } @@ -852,7 +853,7 @@ out3: /* Now free ioctl buf memory */ dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_Ioctl_Buf_Apache) - 1, cpu_addr, dma_handle); out2: - up(&tw_dev->ioctl_sem); + mutex_unlock(&tw_dev->ioctl_lock); out: return retval; } /* End twa_chrdev_ioctl() */ @@ -1182,7 +1183,7 @@ static int twa_initialize_device_extension(TW_Device_Extension *tw_dev) tw_dev->error_sequence_id = 1; tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE; - init_MUTEX(&tw_dev->ioctl_sem); + mutex_init(&tw_dev->ioctl_lock); init_waitqueue_head(&tw_dev->ioctl_wqueue); retval = 0; diff --git a/drivers/scsi/3w-9xxx.h b/drivers/scsi/3w-9xxx.h index 46f22cdc829..1b16d57f031 100644 --- a/drivers/scsi/3w-9xxx.h +++ b/drivers/scsi/3w-9xxx.h @@ -672,7 +672,7 @@ typedef struct TAG_TW_Device_Extension { u32 ioctl_msec; int chrdev_request_id; wait_queue_head_t ioctl_wqueue; - struct semaphore ioctl_sem; + struct mutex ioctl_lock; char aen_clobber; unsigned short working_srl; unsigned short working_branch; diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index 283f6d25892..25f678d0780 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c @@ -203,6 +203,7 @@ #include #include #include +#include #include #include #include @@ -888,7 +889,7 @@ static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl()\n"); /* Only let one of these through at a time */ - if (down_interruptible(&tw_dev->ioctl_sem)) + if (mutex_lock_interruptible(&tw_dev->ioctl_lock)) return -EINTR; /* First copy down the buffer length */ @@ -1029,7 +1030,7 @@ out2: /* Now free ioctl buf memory */ dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle); out: - up(&tw_dev->ioctl_sem); + mutex_unlock(&tw_dev->ioctl_lock); return retval; } /* End tw_chrdev_ioctl() */ @@ -1270,7 +1271,7 @@ static int tw_initialize_device_extension(TW_Device_Extension *tw_dev) tw_dev->pending_tail = TW_Q_START; tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE; - init_MUTEX(&tw_dev->ioctl_sem); + mutex_init(&tw_dev->ioctl_lock); init_waitqueue_head(&tw_dev->ioctl_wqueue); return 0; diff --git a/drivers/scsi/3w-xxxx.h b/drivers/scsi/3w-xxxx.h index 4f81fc39ec5..31fe5ea1592 100644 --- a/drivers/scsi/3w-xxxx.h +++ b/drivers/scsi/3w-xxxx.h @@ -420,7 +420,7 @@ typedef struct TAG_TW_Device_Extension { u32 max_sector_count; u32 aen_count; struct Scsi_Host *host; - struct semaphore ioctl_sem; + struct mutex ioctl_lock; unsigned short aen_queue[TW_Q_LENGTH]; unsigned char aen_head; unsigned char aen_tail; -- GitLab From 42f72aa9e5bc969a34e5989fc00e7e2d71e8a95b Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Fri, 13 Jan 2006 18:05:35 -0600 Subject: [PATCH 213/465] [SCSI] iscsi: whitespace cleanup Remove extra whitespaces. Signed-off-by: Alex Aizman Signed-off-by: Dmitry Yusupov Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 1067d77da10..49d6dd5572c 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -687,7 +687,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn) switch(conn->in.opcode) { case ISCSI_OP_LOGIN_RSP: case ISCSI_OP_TEXT_RSP: - case ISCSI_OP_LOGOUT_RSP: + case ISCSI_OP_LOGOUT_RSP: rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)hdr); if (rc) @@ -728,12 +728,12 @@ iscsi_hdr_recv(struct iscsi_conn *conn) } spin_unlock(&session->lock); break; - case ISCSI_OP_NOOP_IN: + case ISCSI_OP_NOOP_IN: if (hdr->ttt != ISCSI_RESERVED_TAG) { rc = ISCSI_ERR_PROTO; break; } - rc = iscsi_check_assign_cmdsn(session, + rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)hdr); if (rc) break; @@ -768,7 +768,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn) if (!rc && hdr->ttt != ISCSI_RESERVED_TAG) rc = iscsi_recv_pdu(iscsi_handle(conn), hdr, NULL, 0); - } else + } else rc = ISCSI_ERR_PROTO; break; case ISCSI_OP_REJECT: @@ -930,7 +930,7 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn) sc->request_bufflen, ctask->data_offset); if (rc == -EAGAIN) return rc; - if (conn->datadgst_en) + if (conn->datadgst_en) iscsi_recv_digest_update(conn, sc->request_buffer, i); rc = 0; goto done; @@ -1025,7 +1025,7 @@ iscsi_data_recv(struct iscsi_conn *conn) conn->in.hdr = &conn->hdr; conn->senselen = (conn->data[0] << 8) | conn->data[1]; rc = iscsi_cmd_rsp(conn, conn->in.ctask); - if (!rc && conn->datadgst_en) + if (!rc && conn->datadgst_en) iscsi_recv_digest_update(conn, conn->data, conn->in.datalen); } @@ -1052,7 +1052,7 @@ iscsi_data_recv(struct iscsi_conn *conn) rc = iscsi_recv_pdu(iscsi_handle(conn), conn->in.hdr, conn->data, conn->in.datalen); - if (!rc && conn->datadgst_en && + if (!rc && conn->datadgst_en && conn->in.opcode != ISCSI_OP_LOGIN_RSP) iscsi_recv_digest_update(conn, conn->data, conn->in.datalen); @@ -1681,7 +1681,7 @@ iscsi_cmd_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, zero_data(ctask->hdr.dlength); } - iscsi_buf_init_virt(&ctask->headbuf, (char*)&ctask->hdr, + iscsi_buf_init_virt(&ctask->headbuf, (char*)&ctask->hdr, sizeof(struct iscsi_hdr)); conn->scsicmd_pdus_cnt++; } @@ -1747,7 +1747,7 @@ static inline int handle_xmstate_r_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { ctask->xmstate &= ~XMSTATE_R_HDR; - if (conn->hdrdgst_en) + if (conn->hdrdgst_en) iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext); if (!iscsi_sendhdr(conn, &ctask->headbuf, 0)) { BUG_ON(ctask->xmstate != XMSTATE_IDLE); @@ -1761,7 +1761,7 @@ static inline int handle_xmstate_w_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { ctask->xmstate &= ~XMSTATE_W_HDR; - if (conn->hdrdgst_en) + if (conn->hdrdgst_en) iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext); if (iscsi_sendhdr(conn, &ctask->headbuf, ctask->imm_count)) { ctask->xmstate |= XMSTATE_W_HDR; @@ -2149,7 +2149,7 @@ unsolicit_head_again: solicit_head_again: r2t = ctask->r2t; if (conn->hdrdgst_en) - iscsi_hdr_digest(conn, &r2t->headbuf, + iscsi_hdr_digest(conn, &r2t->headbuf, (u8*)r2t->dtask->hdrext); if (iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count)) { ctask->xmstate &= ~XMSTATE_SOL_DATA; -- GitLab From bf310b8f582bddec20c27e32ffbaf8e2c91e147c Mon Sep 17 00:00:00 2001 From: "zhenyu.z.wang@intel.com" Date: Fri, 13 Jan 2006 18:05:38 -0600 Subject: [PATCH 214/465] [SCSI] iscsi: data under/over flow fix We need to check the ISCSI_FLAG_DATA_* flags. Signed-off-by: Alex Aizman Signed-off-by: Dmitry Yusupov Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 49d6dd5572c..550ff66ba9e 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -357,7 +357,7 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) struct scsi_cmnd *sc = ctask->sc; conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1; - if (rhdr->flags & ISCSI_FLAG_CMD_UNDERFLOW) { + if (rhdr->flags & ISCSI_FLAG_DATA_UNDERFLOW) { int res_count = be32_to_cpu(rhdr->residual_count); if (res_count > 0 && @@ -367,9 +367,7 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) } else sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; - } else if (rhdr->flags & ISCSI_FLAG_CMD_BIDI_UNDERFLOW) - sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; - else if (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW) { + } else if (rhdr->flags & ISCSI_FLAG_DATA_OVERFLOW) { sc->resid = be32_to_cpu(rhdr->residual_count); sc->result = (DID_OK << 16) | rhdr->cmd_status; } else -- GitLab From 3e97c7e6cda933e3a1b518a8100d155c532a3cfc Mon Sep 17 00:00:00 2001 From: "zhenyu.z.wang@intel.com" Date: Fri, 13 Jan 2006 18:05:41 -0600 Subject: [PATCH 215/465] [SCSI] iscsi: host locking fix We should be taking the host_lock instead of the conn lock when checking host_busy. Signed-off-by: Alex Aizman Signed-off-by: Dmitry Yusupov Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 550ff66ba9e..cd1491e5236 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -2559,6 +2559,7 @@ iscsi_conn_destroy(iscsi_connh_t connh) { struct iscsi_conn *conn = iscsi_ptr(connh); struct iscsi_session *session = conn->session; + unsigned long flags; mutex_lock(&conn->xmitmutex); set_bit(SUSPEND_BIT, &conn->suspend_tx); @@ -2598,12 +2599,12 @@ iscsi_conn_destroy(iscsi_connh_t connh) * time out or fail. */ for (;;) { - spin_lock_bh(&conn->lock); + spin_lock_irqsave(session->host->host_lock, flags); if (!session->host->host_busy) { /* OK for ERL == 0 */ - spin_unlock_bh(&conn->lock); + spin_unlock_irqrestore(session->host->host_lock, flags); break; } - spin_unlock_bh(&conn->lock); + spin_unlock_irqrestore(session->host->host_lock, flags); msleep_interruptible(500); printk("conn_destroy(): host_busy %d host_failed %d\n", session->host->host_busy, session->host->host_failed); -- GitLab From 56851698c23430f0f291d6e50da344e6b414f3b9 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Fri, 13 Jan 2006 18:05:44 -0600 Subject: [PATCH 216/465] [SCSI] iscsi: data digest page cache usage fix Users can write to a page while we are sending it and making digest calculations. This ends up causing us to retry the command when a digest error is later reported. By using sock_no_sendpage when data digests are calculated we can avoid a lot of (not all but it helps) the retries becuase sock_no_sendpage is not zero copy. Signed-off-by: Alex Aizman Signed-off-by: Dmitry Yusupov Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 16 +++++++++------- drivers/scsi/iscsi_tcp.h | 2 ++ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index cd1491e5236..5e8b3135574 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -1318,15 +1318,15 @@ iscsi_conn_restore_callbacks(struct iscsi_conn *conn) * to use tcp_sendmsg(). */ static inline int -iscsi_send(struct socket *sk, struct iscsi_buf *buf, int size, int flags) +iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags) { + struct socket *sk = conn->sock; int res; if ((int)buf->sg.offset >= 0) { int offset = buf->sg.offset + buf->sent; - /* tcp_sendpage */ - res = sk->ops->sendpage(sk, buf->sg.page, offset, size, flags); + res = conn->sendpage(sk, buf->sg.page, offset, size, flags); } else { struct msghdr msg; @@ -1354,7 +1354,6 @@ iscsi_send(struct socket *sk, struct iscsi_buf *buf, int size, int flags) static inline int iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen) { - struct socket *sk = conn->sock; int flags = 0; /* MSG_DONTWAIT; */ int res, size; @@ -1363,7 +1362,7 @@ iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen) if (buf->sent + size != buf->sg.length || datalen) flags |= MSG_MORE; - res = iscsi_send(sk, buf, size, flags); + res = iscsi_send(conn, buf, size, flags); debug_tcp("sendhdr %d bytes, sent %d res %d\n", size, buf->sent, res); if (res >= 0) { conn->txdata_octets += res; @@ -1394,7 +1393,6 @@ static inline int iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf, int *count, int *sent) { - struct socket *sk = conn->sock; int flags = 0; /* MSG_DONTWAIT; */ int res, size; @@ -1405,7 +1403,7 @@ iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf, if (buf->sent + size != buf->sg.length || *count != size) flags |= MSG_MORE; - res = iscsi_send(sk, buf, size, flags); + res = iscsi_send(conn, buf, size, flags); debug_tcp("sendpage: %d bytes, sent %d left %d sent %d res %d\n", size, buf->sent, *count, *sent, res); if (res >= 0) { @@ -2713,6 +2711,8 @@ iscsi_conn_bind(iscsi_sessionh_t sessionh, iscsi_connh_t connh, */ iscsi_conn_set_callbacks(conn); + conn->sendpage = conn->sock->ops->sendpage; + /* * set receive state machine into initial state */ @@ -3467,6 +3467,8 @@ iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param, if (conn->data_rx_tfm) crypto_free_tfm(conn->data_rx_tfm); } + conn->sendpage = conn->datadgst_en ? + sock_no_sendpage : conn->sock->ops->sendpage; break; case ISCSI_PARAM_INITIAL_R2T_EN: session->initial_r2t_en = value; diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h index 9badafe8820..c8bb5b0bcb4 100644 --- a/drivers/scsi/iscsi_tcp.h +++ b/drivers/scsi/iscsi_tcp.h @@ -191,6 +191,8 @@ struct iscsi_conn { uint32_t sendpage_failures_cnt; uint32_t discontiguous_hdr_cnt; uint32_t eh_abort_cnt; + + ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int); }; struct iscsi_session { -- GitLab From 7cae5159dd2623300cf9820865bfbf6dcdb7c1b9 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Fri, 13 Jan 2006 18:05:47 -0600 Subject: [PATCH 217/465] [SCSI] iscsi: add high mem support From Mike Christie and FUJITA Tomonori : We cannot use page_address becuase some pages could be highmem. Instead, we can use sock_no_sendpage which does kmap for us. Signed-off-by: Alex Aizman Signed-off-by: Dmitry Yusupov Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 84 ++++++++++++++-------------------------- drivers/scsi/iscsi_tcp.h | 2 +- 2 files changed, 31 insertions(+), 55 deletions(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 5e8b3135574..0acc4b235d9 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -87,35 +87,32 @@ iscsi_buf_init_virt(struct iscsi_buf *ibuf, char *vbuf, int size) { sg_init_one(&ibuf->sg, (u8 *)vbuf, size); ibuf->sent = 0; + ibuf->use_sendmsg = 0; } static inline void iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int size) { - ibuf->sg.page = (void*)vbuf; - ibuf->sg.offset = (unsigned int)-1; + ibuf->sg.page = virt_to_page(vbuf); + ibuf->sg.offset = offset_in_page(vbuf); ibuf->sg.length = size; ibuf->sent = 0; -} - -static inline void* -iscsi_buf_iov_base(struct iscsi_buf *ibuf) -{ - return (char*)ibuf->sg.page + ibuf->sent; + ibuf->use_sendmsg = 1; } static inline void iscsi_buf_init_sg(struct iscsi_buf *ibuf, struct scatterlist *sg) { + ibuf->sg.page = sg->page; + ibuf->sg.offset = sg->offset; + ibuf->sg.length = sg->length; /* * Fastpath: sg element fits into single page */ - if (sg->length + sg->offset <= PAGE_SIZE && page_count(sg->page) >= 2) { - ibuf->sg.page = sg->page; - ibuf->sg.offset = sg->offset; - ibuf->sg.length = sg->length; - } else - iscsi_buf_init_iov(ibuf, page_address(sg->page), sg->length); + if (sg->length + sg->offset <= PAGE_SIZE && page_count(sg->page) >= 2) + ibuf->use_sendmsg = 0; + else + ibuf->use_sendmsg = 1; ibuf->sent = 0; } @@ -1311,35 +1308,25 @@ iscsi_conn_restore_callbacks(struct iscsi_conn *conn) * @buf: buffer to write from * @size: actual size to write * @flags: socket's flags - * - * Notes: - * depending on buffer will use tcp_sendpage() or tcp_sendmsg(). - * buf->sg.offset == -1 tells us that buffer is non S/G and forces - * to use tcp_sendmsg(). */ static inline int iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags) { struct socket *sk = conn->sock; - int res; - - if ((int)buf->sg.offset >= 0) { - int offset = buf->sg.offset + buf->sent; - - res = conn->sendpage(sk, buf->sg.page, offset, size, flags); - } else { - struct msghdr msg; - - buf->iov.iov_base = iscsi_buf_iov_base(buf); - buf->iov.iov_len = size; - - memset(&msg, 0, sizeof(struct msghdr)); - - /* tcp_sendmsg */ - res = kernel_sendmsg(sk, &msg, &buf->iov, 1, size); - } + int offset = buf->sg.offset + buf->sent; - return res; + /* + * if we got use_sg=0 or are sending something we kmallocd + * then we did not have to do kmap (kmap returns page_address) + * + * if we got use_sg > 0, but had to drop down, we do not + * set clustering so this should only happen for that + * slab case. + */ + if (buf->use_sendmsg) + return sock_no_sendpage(sk, buf->sg.page, offset, size, flags); + else + return conn->sendpage(sk, buf->sg.page, offset, size, flags); } /** @@ -1431,19 +1418,6 @@ iscsi_data_digest_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) ctask->digest_count = 4; } -static inline void -iscsi_buf_data_digest_update(struct iscsi_conn *conn, struct iscsi_buf *buf) -{ - struct scatterlist sg; - - if (buf->sg.offset != -1) - crypto_digest_update(conn->data_tx_tfm, &buf->sg, 1); - else { - sg_init_one(&sg, (char *)buf->sg.page, buf->sg.length); - crypto_digest_update(conn->data_tx_tfm, &sg, 1); - } -} - static inline int iscsi_digest_final_send(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, struct iscsi_buf *buf, uint32_t *digest, int final) @@ -1806,7 +1780,8 @@ handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) return -EAGAIN; } if (conn->datadgst_en) - iscsi_buf_data_digest_update(conn, &ctask->sendbuf); + crypto_digest_update(conn->data_tx_tfm, + &ctask->sendbuf.sg, 1); if (!ctask->imm_count) break; @@ -1891,7 +1866,8 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) * so pass it */ if (conn->datadgst_en && ctask->sent - start > 0) - iscsi_buf_data_digest_update(conn, &ctask->sendbuf); + crypto_digest_update(conn->data_tx_tfm, + &ctask->sendbuf.sg, 1); if (!ctask->data_count) break; @@ -1969,7 +1945,7 @@ solicit_again: BUG_ON(r2t->data_count < 0); if (conn->datadgst_en) - iscsi_buf_data_digest_update(conn, &r2t->sendbuf); + crypto_digest_update(conn->data_tx_tfm, &r2t->sendbuf.sg, 1); if (r2t->data_count) { BUG_ON(ctask->sc->use_sg == 0); @@ -2051,7 +2027,7 @@ handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) } if (conn->datadgst_en) { - iscsi_buf_data_digest_update(conn, &ctask->sendbuf); + crypto_digest_update(conn->data_tx_tfm, &ctask->sendbuf.sg, 1); /* imm data? */ if (!dtask) { if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf, diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h index c8bb5b0bcb4..f95e61b76f7 100644 --- a/drivers/scsi/iscsi_tcp.h +++ b/drivers/scsi/iscsi_tcp.h @@ -242,8 +242,8 @@ struct iscsi_session { struct iscsi_buf { struct scatterlist sg; - struct kvec iov; unsigned int sent; + char use_sendmsg; }; struct iscsi_data_task { -- GitLab From 7b8631b53bea286b68847a939b87135198335b66 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Fri, 13 Jan 2006 18:05:50 -0600 Subject: [PATCH 218/465] [SCSI] iscsi: seperate iscsi interface from setup functions This is the second version of the patch to address Christoph's comments. Instead of doing the lib, I just kept everything in scsi_trnapsort_iscsi.c like the FC and SPI class. This was becuase the driver model and sysfs class is tied to the session and connection setup so separating did not buy very much at this time. The reason for this patch was becuase HW iscsi LLDs like qla4xxx cannot use the iscsi class becuase the scsi_host was tied to the interface and class code. This patch just seperates the session from scsi host so that LLDs that allocate the host per some resource like pci device can still use the class. This is also fixes a couple refcount bugs that can be triggered when users have a sysfs file open, close the session, then read or write to the file. Signed-off-by: Alex Aizman Signed-off-by: Dmitry Yusupov Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 118 ++-- drivers/scsi/scsi_transport_iscsi.c | 845 +++++++++++++++------------- include/scsi/iscsi_if.h | 6 + include/scsi/scsi_transport_iscsi.h | 75 ++- 4 files changed, 583 insertions(+), 461 deletions(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 0acc4b235d9..e31d350e6b6 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -2435,17 +2435,20 @@ iscsi_pool_free(struct iscsi_queue *q, void **items) kfree(items); } -static iscsi_connh_t -iscsi_conn_create(iscsi_sessionh_t sessionh, uint32_t conn_idx) +static struct iscsi_cls_conn * +iscsi_conn_create(struct Scsi_Host *shost, uint32_t conn_idx) { - struct iscsi_session *session = iscsi_ptr(sessionh); - struct iscsi_conn *conn = NULL; + struct iscsi_session *session = iscsi_hostdata(shost->hostdata); + struct iscsi_conn *conn; + struct iscsi_cls_conn *cls_conn; - conn = kmalloc(sizeof(struct iscsi_conn), GFP_KERNEL); - if (conn == NULL) - goto conn_alloc_fail; - memset(conn, 0, sizeof(struct iscsi_conn)); + cls_conn = iscsi_create_conn(hostdata_session(shost->hostdata), + conn_idx); + if (!cls_conn) + return NULL; + conn = cls_conn->dd_data; + memset(conn, 0, sizeof(struct iscsi_conn)); conn->c_stage = ISCSI_CONN_INITIAL_STAGE; conn->in_progress = IN_PROGRESS_WAIT_HEADER; conn->id = conn_idx; @@ -2507,7 +2510,7 @@ iscsi_conn_create(iscsi_sessionh_t sessionh, uint32_t conn_idx) mutex_init(&conn->xmitmutex); init_waitqueue_head(&conn->ehwait); - return iscsi_handle(conn); + return cls_conn; max_recv_dlenght_alloc_fail: spin_lock_bh(&session->lock); @@ -2523,15 +2526,14 @@ immqueue_alloc_fail: writequeue_alloc_fail: kfifo_free(conn->xmitqueue); xmitqueue_alloc_fail: - kfree(conn); -conn_alloc_fail: - return iscsi_handle(NULL); + iscsi_destroy_conn(cls_conn); + return NULL; } static void -iscsi_conn_destroy(iscsi_connh_t connh) +iscsi_conn_destroy(struct iscsi_cls_conn *cls_conn) { - struct iscsi_conn *conn = iscsi_ptr(connh); + struct iscsi_conn *conn = cls_conn->dd_data; struct iscsi_session *session = conn->session; unsigned long flags; @@ -2626,7 +2628,8 @@ iscsi_conn_destroy(iscsi_connh_t connh) kfifo_free(conn->writequeue); kfifo_free(conn->immqueue); kfifo_free(conn->mgmtqueue); - kfree(conn); + + iscsi_destroy_conn(cls_conn); } static int @@ -3257,17 +3260,23 @@ static struct scsi_host_template iscsi_sht = { .this_id = -1, }; -static iscsi_sessionh_t -iscsi_session_create(uint32_t initial_cmdsn, struct Scsi_Host *host) +static struct iscsi_transport iscsi_tcp_transport; + +static struct Scsi_Host * +iscsi_session_create(struct scsi_transport_template *scsit, + uint32_t initial_cmdsn) { - int cmd_i; + struct Scsi_Host *shost; struct iscsi_session *session; + int cmd_i; - session = iscsi_hostdata(host->hostdata); - memset(session, 0, sizeof(struct iscsi_session)); + shost = iscsi_transport_create_session(scsit, &iscsi_tcp_transport); + if (!shost) + return NULL; - session->host = host; - session->id = host->host_no; + session = iscsi_hostdata(shost->hostdata); + memset(session, 0, sizeof(struct iscsi_session)); + session->host = shost; session->state = ISCSI_STATE_LOGGED_IN; session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX; session->cmds_max = ISCSI_XMIT_CMDS_MAX; @@ -3311,7 +3320,7 @@ iscsi_session_create(uint32_t initial_cmdsn, struct Scsi_Host *host) if (iscsi_r2tpool_alloc(session)) goto r2tpool_alloc_fail; - return iscsi_handle(session); + return shost; r2tpool_alloc_fail: for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) @@ -3321,15 +3330,15 @@ immdata_alloc_fail: mgmtpool_alloc_fail: iscsi_pool_free(&session->cmdpool, (void**)session->cmds); cmdpool_alloc_fail: - return iscsi_handle(NULL); + return NULL; } static void -iscsi_session_destroy(iscsi_sessionh_t sessionh) +iscsi_session_destroy(struct Scsi_Host *shost) { + struct iscsi_session *session = iscsi_hostdata(shost->hostdata); int cmd_i; struct iscsi_data_task *dtask, *n; - struct iscsi_session *session = iscsi_ptr(sessionh); for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; @@ -3345,6 +3354,8 @@ iscsi_session_destroy(iscsi_sessionh_t sessionh) iscsi_r2tpool_free(session); iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); iscsi_pool_free(&session->cmdpool, (void**)session->cmds); + + iscsi_transport_destroy_session(shost); } static int @@ -3493,25 +3504,12 @@ iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param, } static int -iscsi_conn_get_param(iscsi_connh_t connh, enum iscsi_param param, - uint32_t *value) +iscsi_session_get_param(struct Scsi_Host *shost, + enum iscsi_param param, uint32_t *value) { - struct iscsi_conn *conn = iscsi_ptr(connh); - struct iscsi_session *session = conn->session; + struct iscsi_session *session = iscsi_hostdata(shost->hostdata); switch(param) { - case ISCSI_PARAM_MAX_RECV_DLENGTH: - *value = conn->max_recv_dlength; - break; - case ISCSI_PARAM_MAX_XMIT_DLENGTH: - *value = conn->max_xmit_dlength; - break; - case ISCSI_PARAM_HDRDGST_EN: - *value = conn->hdrdgst_en; - break; - case ISCSI_PARAM_DATADGST_EN: - *value = conn->datadgst_en; - break; case ISCSI_PARAM_INITIAL_R2T_EN: *value = session->initial_r2t_en; break; @@ -3549,6 +3547,31 @@ iscsi_conn_get_param(iscsi_connh_t connh, enum iscsi_param param, return 0; } +static int +iscsi_conn_get_param(void *data, enum iscsi_param param, uint32_t *value) +{ + struct iscsi_conn *conn = data; + + switch(param) { + case ISCSI_PARAM_MAX_RECV_DLENGTH: + *value = conn->max_recv_dlength; + break; + case ISCSI_PARAM_MAX_XMIT_DLENGTH: + *value = conn->max_xmit_dlength; + break; + case ISCSI_PARAM_HDRDGST_EN: + *value = conn->hdrdgst_en; + break; + case ISCSI_PARAM_DATADGST_EN: + *value = conn->datadgst_en; + break; + default: + return ISCSI_ERR_PARAM_NOT_FOUND; + } + + return 0; +} + static void iscsi_conn_get_stats(iscsi_connh_t connh, struct iscsi_stats *stats) { @@ -3593,6 +3616,7 @@ static struct iscsi_transport iscsi_tcp_transport = { | CAP_DATADGST, .host_template = &iscsi_sht, .hostdata_size = sizeof(struct iscsi_session), + .conndata_size = sizeof(struct iscsi_conn), .max_conn = 1, .max_cmd_len = ISCSI_TCP_MAX_CMD_LEN, .create_session = iscsi_session_create, @@ -3601,7 +3625,8 @@ static struct iscsi_transport iscsi_tcp_transport = { .bind_conn = iscsi_conn_bind, .destroy_conn = iscsi_conn_destroy, .set_param = iscsi_conn_set_param, - .get_param = iscsi_conn_get_param, + .get_conn_param = iscsi_conn_get_param, + .get_session_param = iscsi_session_get_param, .start_conn = iscsi_conn_start, .stop_conn = iscsi_conn_stop, .send_pdu = iscsi_conn_send_pdu, @@ -3611,8 +3636,6 @@ static struct iscsi_transport iscsi_tcp_transport = { static int __init iscsi_tcp_init(void) { - int error; - if (iscsi_max_lun < 1) { printk(KERN_ERR "Invalid max_lun value of %u\n", iscsi_max_lun); return -EINVAL; @@ -3625,11 +3648,10 @@ iscsi_tcp_init(void) if (!taskcache) return -ENOMEM; - error = iscsi_register_transport(&iscsi_tcp_transport); - if (error) + if (!iscsi_register_transport(&iscsi_tcp_transport)) kmem_cache_destroy(taskcache); - return error; + return 0; } static void __exit diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 50ed88f98f4..45e31635a59 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -21,12 +21,9 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include -#include -#include #include #include #include - #include #include #include @@ -45,11 +42,6 @@ struct iscsi_internal { * List of sessions for this transport */ struct list_head sessions; - /* - * lock to serialize access to the sessions list which must - * be taken after the rx_queue_mutex - */ - spinlock_t session_lock; /* * based on transport capabilities, at register time we set these * bits to tell the transport class it wants attributes displayed @@ -157,7 +149,7 @@ struct mempool_zone { spinlock_t freelock; }; -static struct mempool_zone z_reply; +static struct mempool_zone *z_reply; /* * Z_MAX_* - actual mempool size allocated at the mempool_zone_init() time @@ -172,50 +164,270 @@ static struct mempool_zone z_reply; #define Z_MAX_ERROR 16 #define Z_HIWAT_ERROR 12 -struct iscsi_if_conn { - struct list_head conn_list; /* item in connlist */ - struct list_head session_list; /* item in session->connections */ - iscsi_connh_t connh; - int active; /* must be accessed with the connlock */ - struct Scsi_Host *host; /* originated shost */ - struct device dev; /* sysfs transport/container device */ - struct iscsi_transport *transport; - struct mempool_zone z_error; - struct mempool_zone z_pdu; - struct list_head freequeue; -}; +static LIST_HEAD(connlist); +static DEFINE_SPINLOCK(connlock); -#define iscsi_dev_to_if_conn(_dev) \ - container_of(_dev, struct iscsi_if_conn, dev) +/* + * The following functions can be used by LLDs that allocate + * their own scsi_hosts or by software iscsi LLDs + */ +static void iscsi_session_release(struct device *dev) +{ + struct iscsi_cls_session *session = iscsi_dev_to_session(dev); + struct iscsi_transport *transport = session->transport; + struct Scsi_Host *shost; -#define iscsi_cdev_to_if_conn(_cdev) \ - iscsi_dev_to_if_conn(_cdev->dev) + shost = iscsi_session_to_shost(session); + scsi_host_put(shost); + kfree(session); + module_put(transport->owner); +} -static LIST_HEAD(connlist); -static DEFINE_SPINLOCK(connlock); +static int iscsi_is_session_dev(const struct device *dev) +{ + return dev->release == iscsi_session_release; +} -struct iscsi_if_session { - struct list_head list; /* item in session_list */ - struct list_head connections; - iscsi_sessionh_t sessionh; - struct iscsi_transport *transport; - struct device dev; /* sysfs transport/container device */ -}; +/** + * iscsi_create_session - create iscsi class session + * @shost: scsi host + * @transport: iscsi transport + * + * This can be called from a LLD or iscsi_transport + **/ +struct iscsi_cls_session * +iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport) +{ + struct iscsi_cls_session *session; + int err; + + if (!try_module_get(transport->owner)) + return NULL; + + session = kzalloc(sizeof(*session), GFP_KERNEL); + if (!session) + goto module_put; + session->transport = transport; + + /* this is released in the dev's release function */ + scsi_host_get(shost); + snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", shost->host_no); + session->dev.parent = &shost->shost_gendev; + session->dev.release = iscsi_session_release; + err = device_register(&session->dev); + if (err) { + dev_printk(KERN_ERR, &session->dev, "iscsi: could not " + "register session's dev\n"); + goto free_session; + } + transport_register_device(&session->dev); + + return session; + +free_session: + kfree(session); +module_put: + module_put(transport->owner); + return NULL; +} + +EXPORT_SYMBOL_GPL(iscsi_create_session); + +/** + * iscsi_destroy_session - destroy iscsi session + * @session: iscsi_session + * + * Can be called by a LLD or iscsi_transport. There must not be + * any running connections. + **/ +int iscsi_destroy_session(struct iscsi_cls_session *session) +{ + transport_unregister_device(&session->dev); + device_unregister(&session->dev); + return 0; +} + +EXPORT_SYMBOL_GPL(iscsi_destroy_session); + +static void iscsi_conn_release(struct device *dev) +{ + struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev); + struct device *parent = conn->dev.parent; + + kfree(conn); + put_device(parent); +} + +static int iscsi_is_conn_dev(const struct device *dev) +{ + return dev->release == iscsi_conn_release; +} + +/** + * iscsi_create_conn - create iscsi class connection + * @session: iscsi cls session + * @cid: connection id + * + * This can be called from a LLD or iscsi_transport. The connection + * is child of the session so cid must be unique for all connections + * on the session. + **/ +struct iscsi_cls_conn * +iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid) +{ + struct iscsi_transport *transport = session->transport; + struct Scsi_Host *shost = iscsi_session_to_shost(session); + struct iscsi_cls_conn *conn; + int err; + + conn = kzalloc(sizeof(*conn) + transport->conndata_size, GFP_KERNEL); + if (!conn) + return NULL; + + if (transport->conndata_size) + conn->dd_data = &conn[1]; + + INIT_LIST_HEAD(&conn->conn_list); + conn->transport = transport; + + /* this is released in the dev's release function */ + if (!get_device(&session->dev)) + goto free_conn; + snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u", + shost->host_no, cid); + conn->dev.parent = &session->dev; + conn->dev.release = iscsi_conn_release; + err = device_register(&conn->dev); + if (err) { + dev_printk(KERN_ERR, &conn->dev, "iscsi: could not register " + "connection's dev\n"); + goto release_parent_ref; + } + transport_register_device(&conn->dev); + return conn; + +release_parent_ref: + put_device(&session->dev); +free_conn: + kfree(conn); + return NULL; +} + +EXPORT_SYMBOL_GPL(iscsi_create_conn); + +/** + * iscsi_destroy_conn - destroy iscsi class connection + * @session: iscsi cls session + * + * This can be called from a LLD or iscsi_transport. + **/ +int iscsi_destroy_conn(struct iscsi_cls_conn *conn) +{ + transport_unregister_device(&conn->dev); + device_unregister(&conn->dev); + return 0; +} + +EXPORT_SYMBOL_GPL(iscsi_destroy_conn); + +/* + * These functions are used only by software iscsi_transports + * which do not allocate and more their scsi_hosts since this + * is initiated from userspace. + */ + +/* + * iSCSI Session's hostdata organization: + * + * *------------------* <== hostdata_session(host->hostdata) + * | ptr to class sess| + * |------------------| <== iscsi_hostdata(host->hostdata) + * | transport's data | + * *------------------* + */ + +#define hostdata_privsize(_t) (sizeof(unsigned long) + _t->hostdata_size + \ + _t->hostdata_size % sizeof(unsigned long)) + +#define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata)) + +/** + * iscsi_transport_create_session - create iscsi cls session and host + * scsit: scsi transport template + * transport: iscsi transport template + * + * This can be used by software iscsi_transports that allocate + * a session per scsi host. + **/ +struct Scsi_Host * +iscsi_transport_create_session(struct scsi_transport_template *scsit, + struct iscsi_transport *transport) +{ + struct iscsi_cls_session *session; + struct Scsi_Host *shost; + + shost = scsi_host_alloc(transport->host_template, + hostdata_privsize(transport)); + if (!shost) { + printk(KERN_ERR "iscsi: can not allocate SCSI host for " + "session\n"); + return NULL; + } + + shost->max_id = 1; + shost->max_channel = 0; + shost->max_lun = transport->max_lun; + shost->max_cmd_len = transport->max_cmd_len; + shost->transportt = scsit; + + if (scsi_add_host(shost, NULL)) + goto free_host; + + session = iscsi_create_session(shost, transport); + if (!session) + goto remove_host; -#define iscsi_dev_to_if_session(_dev) \ - container_of(_dev, struct iscsi_if_session, dev) + *(unsigned long*)shost->hostdata = (unsigned long)session; + return shost; + +remove_host: + scsi_remove_host(shost); +free_host: + scsi_host_put(shost); + return NULL; +} -#define iscsi_cdev_to_if_session(_cdev) \ - iscsi_dev_to_if_session(_cdev->dev) +EXPORT_SYMBOL_GPL(iscsi_transport_create_session); -#define iscsi_if_session_to_shost(_session) \ - dev_to_shost(_session->dev.parent) +/** + * iscsi_transport_destroy_session - destroy session and scsi host + * shost: scsi host + * + * This can be used by software iscsi_transports that allocate + * a session per scsi host. + **/ +int iscsi_transport_destroy_session(struct Scsi_Host *shost) +{ + struct iscsi_cls_session *session; -static struct iscsi_if_conn* + scsi_remove_host(shost); + session = hostdata_session(shost->hostdata); + iscsi_destroy_session(session); + /* ref from host alloc */ + scsi_host_put(shost); + return 0; +} + +EXPORT_SYMBOL_GPL(iscsi_transport_destroy_session); + +/* + * iscsi interface functions + */ +static struct iscsi_cls_conn* iscsi_if_find_conn(uint64_t key) { unsigned long flags; - struct iscsi_if_conn *conn; + struct iscsi_cls_conn *conn; spin_lock_irqsave(&connlock, flags); list_for_each_entry(conn, &connlist, conn_list) @@ -250,7 +462,7 @@ static inline struct list_head *skb_to_lh(struct sk_buff *skb) } static void* -mempool_zone_alloc_skb(gfp_t gfp_mask, void *pool_data) +mempool_zone_alloc_skb(unsigned int gfp_mask, void *pool_data) { struct mempool_zone *zone = pool_data; @@ -282,14 +494,21 @@ mempool_zone_complete(struct mempool_zone *zone) spin_unlock_irqrestore(&zone->freelock, flags); } -static int -mempool_zone_init(struct mempool_zone *zp, unsigned max, unsigned size, - unsigned hiwat) +static struct mempool_zone * +mempool_zone_init(unsigned max, unsigned size, unsigned hiwat) { + struct mempool_zone *zp; + + zp = kzalloc(sizeof(*zp), GFP_KERNEL); + if (!zp) + return NULL; + zp->pool = mempool_create(max, mempool_zone_alloc_skb, mempool_zone_free_skb, zp); - if (!zp->pool) - return -ENOMEM; + if (!zp->pool) { + kfree(zp); + return NULL; + } zp->size = size; zp->hiwat = hiwat; @@ -298,9 +517,14 @@ mempool_zone_init(struct mempool_zone *zp, unsigned max, unsigned size, spin_lock_init(&zp->freelock); atomic_set(&zp->allocated, 0); - return 0; + return zp; } +static void mempool_zone_destroy(struct mempool_zone *zp) +{ + mempool_destroy(zp->pool); + kfree(zp); +} static struct sk_buff* mempool_zone_get_skb(struct mempool_zone *zone) @@ -340,7 +564,7 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr, struct nlmsghdr *nlh; struct sk_buff *skb; struct iscsi_uevent *ev; - struct iscsi_if_conn *conn; + struct iscsi_cls_conn *conn; char *pdu; int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) + data_size); @@ -348,13 +572,13 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr, conn = iscsi_if_find_conn(connh); BUG_ON(!conn); - mempool_zone_complete(&conn->z_pdu); + mempool_zone_complete(conn->z_pdu); - skb = mempool_zone_get_skb(&conn->z_pdu); + skb = mempool_zone_get_skb(conn->z_pdu); if (!skb) { iscsi_conn_error(connh, ISCSI_ERR_CONN_FAILED); - printk(KERN_ERR "iscsi%d: can not deliver control PDU: OOM\n", - conn->host->host_no); + dev_printk(KERN_ERR, &conn->dev, "iscsi: can not deliver " + "control PDU: OOM\n"); return -ENOMEM; } @@ -363,14 +587,14 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr, memset(ev, 0, sizeof(*ev)); ev->transport_handle = iscsi_handle(conn->transport); ev->type = ISCSI_KEVENT_RECV_PDU; - if (atomic_read(&conn->z_pdu.allocated) >= conn->z_pdu.hiwat) + if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat) ev->iferror = -ENOMEM; ev->r.recv_req.conn_handle = connh; pdu = (char*)ev + sizeof(*ev); memcpy(pdu, hdr, sizeof(struct iscsi_hdr)); memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size); - return iscsi_unicast_skb(&conn->z_pdu, skb); + return iscsi_unicast_skb(conn->z_pdu, skb); } EXPORT_SYMBOL_GPL(iscsi_recv_pdu); @@ -379,18 +603,18 @@ void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error) struct nlmsghdr *nlh; struct sk_buff *skb; struct iscsi_uevent *ev; - struct iscsi_if_conn *conn; + struct iscsi_cls_conn *conn; int len = NLMSG_SPACE(sizeof(*ev)); conn = iscsi_if_find_conn(connh); BUG_ON(!conn); - mempool_zone_complete(&conn->z_error); + mempool_zone_complete(conn->z_error); - skb = mempool_zone_get_skb(&conn->z_error); + skb = mempool_zone_get_skb(conn->z_error); if (!skb) { - printk(KERN_ERR "iscsi%d: gracefully ignored conn error (%d)\n", - conn->host->host_no, error); + dev_printk(KERN_ERR, &conn->dev, "iscsi: gracefully ignored " + "conn error (%d)\n", error); return; } @@ -398,15 +622,15 @@ void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error) ev = NLMSG_DATA(nlh); ev->transport_handle = iscsi_handle(conn->transport); ev->type = ISCSI_KEVENT_CONN_ERROR; - if (atomic_read(&conn->z_error.allocated) >= conn->z_error.hiwat) + if (atomic_read(&conn->z_error->allocated) >= conn->z_error->hiwat) ev->iferror = -ENOMEM; ev->r.connerror.error = error; ev->r.connerror.conn_handle = connh; - iscsi_unicast_skb(&conn->z_error, skb); + iscsi_unicast_skb(conn->z_error, skb); - printk(KERN_INFO "iscsi%d: detected conn error (%d)\n", - conn->host->host_no, error); + dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n", + error); } EXPORT_SYMBOL_GPL(iscsi_conn_error); @@ -420,9 +644,9 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi, int flags = multi ? NLM_F_MULTI : 0; int t = done ? NLMSG_DONE : type; - mempool_zone_complete(&z_reply); + mempool_zone_complete(z_reply); - skb = mempool_zone_get_skb(&z_reply); + skb = mempool_zone_get_skb(z_reply); /* * FIXME: * user is supposed to react on iferror == -ENOMEM; @@ -433,366 +657,197 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi, nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0); nlh->nlmsg_flags = flags; memcpy(NLMSG_DATA(nlh), payload, size); - return iscsi_unicast_skb(&z_reply, skb); + return iscsi_unicast_skb(z_reply, skb); } -/* - * iSCSI Session's hostdata organization: - * - * *------------------* <== host->hostdata - * | transport | - * |------------------| <== iscsi_hostdata(host->hostdata) - * | transport's data | - * |------------------| <== hostdata_session(host->hostdata) - * | interface's data | - * *------------------* - */ +static int +iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb, + struct nlmsghdr *nlh) +{ + struct iscsi_uevent *ev = NLMSG_DATA(nlh); + struct iscsi_stats *stats; + struct sk_buff *skbstat; + struct iscsi_cls_conn *conn; + struct nlmsghdr *nlhstat; + struct iscsi_uevent *evstat; + int len = NLMSG_SPACE(sizeof(*ev) + + sizeof(struct iscsi_stats) + + sizeof(struct iscsi_stats_custom) * + ISCSI_STATS_CUSTOM_MAX); + int err = 0; -#define hostdata_privsize(_t) (sizeof(unsigned long) + _t->hostdata_size + \ - _t->hostdata_size % sizeof(unsigned long) + \ - sizeof(struct iscsi_if_session)) + conn = iscsi_if_find_conn(ev->u.get_stats.conn_handle); + if (!conn) + return -EEXIST; -#define hostdata_session(_hostdata) ((void*)_hostdata + sizeof(unsigned long) + \ - ((struct iscsi_transport *) \ - iscsi_ptr(*(uint64_t *)_hostdata))->hostdata_size) + do { + int actual_size; -static void iscsi_if_session_dev_release(struct device *dev) -{ - struct iscsi_if_session *session = iscsi_dev_to_if_session(dev); - struct iscsi_transport *transport = session->transport; - struct Scsi_Host *shost = iscsi_if_session_to_shost(session); - struct iscsi_if_conn *conn, *tmp; - unsigned long flags; + mempool_zone_complete(conn->z_pdu); - /* now free connections */ - spin_lock_irqsave(&connlock, flags); - list_for_each_entry_safe(conn, tmp, &session->connections, - session_list) { - list_del(&conn->session_list); - mempool_destroy(conn->z_pdu.pool); - mempool_destroy(conn->z_error.pool); - kfree(conn); - } - spin_unlock_irqrestore(&connlock, flags); - scsi_host_put(shost); - module_put(transport->owner); + skbstat = mempool_zone_get_skb(conn->z_pdu); + if (!skbstat) { + dev_printk(KERN_ERR, &conn->dev, "iscsi: can not " + "deliver stats: OOM\n"); + return -ENOMEM; + } + + nlhstat = __nlmsg_put(skbstat, daemon_pid, 0, 0, + (len - sizeof(*nlhstat)), 0); + evstat = NLMSG_DATA(nlhstat); + memset(evstat, 0, sizeof(*evstat)); + evstat->transport_handle = iscsi_handle(conn->transport); + evstat->type = nlh->nlmsg_type; + if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat) + evstat->iferror = -ENOMEM; + evstat->u.get_stats.conn_handle = + ev->u.get_stats.conn_handle; + stats = (struct iscsi_stats *) + ((char*)evstat + sizeof(*evstat)); + memset(stats, 0, sizeof(*stats)); + + transport->get_stats(ev->u.get_stats.conn_handle, stats); + actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) + + sizeof(struct iscsi_stats) + + sizeof(struct iscsi_stats_custom) * + stats->custom_length); + actual_size -= sizeof(*nlhstat); + actual_size = NLMSG_LENGTH(actual_size); + skb_trim(skb, NLMSG_ALIGN(actual_size)); + nlhstat->nlmsg_len = actual_size; + + err = iscsi_unicast_skb(conn->z_pdu, skbstat); + } while (err < 0 && err != -ECONNREFUSED); + + return err; } static int iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev) { struct iscsi_transport *transport = priv->iscsi_transport; - struct iscsi_if_session *session; struct Scsi_Host *shost; - unsigned long flags; - int error; - - if (!try_module_get(transport->owner)) - return -EPERM; - shost = scsi_host_alloc(transport->host_template, - hostdata_privsize(transport)); - if (!shost) { - ev->r.c_session_ret.session_handle = iscsi_handle(NULL); - printk(KERN_ERR "iscsi: can not allocate SCSI host for " - "session\n"); - error = -ENOMEM; - goto out_module_put; - } - shost->max_id = 1; - shost->max_channel = 0; - shost->max_lun = transport->max_lun; - shost->max_cmd_len = transport->max_cmd_len; - shost->transportt = &priv->t; - - /* store struct iscsi_transport in hostdata */ - *(uint64_t*)shost->hostdata = ev->transport_handle; + if (!transport->create_session) + return -EINVAL; - ev->r.c_session_ret.session_handle = transport->create_session( - ev->u.c_session.initial_cmdsn, shost); - if (ev->r.c_session_ret.session_handle == iscsi_handle(NULL)) { - error = 0; - goto out_host_put; - } + shost = transport->create_session(&priv->t, + ev->u.c_session.initial_cmdsn); + if (!shost) + return -ENOMEM; - /* host_no becomes assigned SID */ + ev->r.c_session_ret.session_handle = iscsi_handle(iscsi_hostdata(shost->hostdata)); ev->r.c_session_ret.sid = shost->host_no; - /* initialize session */ - session = hostdata_session(shost->hostdata); - INIT_LIST_HEAD(&session->connections); - INIT_LIST_HEAD(&session->list); - session->sessionh = ev->r.c_session_ret.session_handle; - session->transport = transport; - - error = scsi_add_host(shost, NULL); - if (error) - goto out_destroy_session; - - /* - * this is released in the dev's release function) - */ - scsi_host_get(shost); - snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", shost->host_no); - session->dev.parent = &shost->shost_gendev; - session->dev.release = iscsi_if_session_dev_release; - error = device_register(&session->dev); - if (error) { - printk(KERN_ERR "iscsi: could not register session%d's dev\n", - shost->host_no); - goto out_remove_host; - } - transport_register_device(&session->dev); - - /* add this session to the list of active sessions */ - spin_lock_irqsave(&priv->session_lock, flags); - list_add(&session->list, &priv->sessions); - spin_unlock_irqrestore(&priv->session_lock, flags); - return 0; - -out_remove_host: - scsi_remove_host(shost); -out_destroy_session: - transport->destroy_session(ev->r.c_session_ret.session_handle); - ev->r.c_session_ret.session_handle = iscsi_handle(NULL); -out_host_put: - scsi_host_put(shost); -out_module_put: - module_put(transport->owner); - return error; } static int iscsi_if_destroy_session(struct iscsi_internal *priv, struct iscsi_uevent *ev) { struct iscsi_transport *transport = priv->iscsi_transport; + struct Scsi_Host *shost; - struct iscsi_if_session *session; - unsigned long flags; - struct iscsi_if_conn *conn; - int error = 0; + + if (!transport->destroy_session) + return -EINVAL; shost = scsi_host_lookup(ev->u.d_session.sid); if (shost == ERR_PTR(-ENXIO)) return -EEXIST; - session = hostdata_session(shost->hostdata); - /* check if we have active connections */ - spin_lock_irqsave(&connlock, flags); - list_for_each_entry(conn, &session->connections, session_list) { - if (conn->active) { - printk(KERN_ERR "iscsi%d: can not destroy session: " - "has active connection (%p)\n", - shost->host_no, iscsi_ptr(conn->connh)); - spin_unlock_irqrestore(&connlock, flags); - error = EIO; - goto out_release_ref; - } - } - spin_unlock_irqrestore(&connlock, flags); - - scsi_remove_host(shost); - transport->destroy_session(ev->u.d_session.session_handle); - transport_unregister_device(&session->dev); - device_unregister(&session->dev); - - /* remove this session from the list of active sessions */ - spin_lock_irqsave(&priv->session_lock, flags); - list_del(&session->list); - spin_unlock_irqrestore(&priv->session_lock, flags); - - /* ref from host alloc */ - scsi_host_put(shost); -out_release_ref: - /* ref from host lookup */ - scsi_host_put(shost); - return error; -} - -static void iscsi_if_conn_dev_release(struct device *dev) -{ - struct iscsi_if_conn *conn = iscsi_dev_to_if_conn(dev); - struct Scsi_Host *shost = conn->host; - - scsi_host_put(shost); + if (transport->destroy_session) + transport->destroy_session(shost); + /* ref from host lookup */ + scsi_host_put(shost); + return 0; } static int -iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev) -{ - struct iscsi_if_session *session; +iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev){ struct Scsi_Host *shost; - struct iscsi_if_conn *conn; + struct iscsi_cls_conn *conn; unsigned long flags; - int error; + + if (!transport->create_conn) + return -EINVAL; shost = scsi_host_lookup(ev->u.c_conn.sid); if (shost == ERR_PTR(-ENXIO)) return -EEXIST; - session = hostdata_session(shost->hostdata); - conn = kmalloc(sizeof(struct iscsi_if_conn), GFP_KERNEL); - if (!conn) { - error = -ENOMEM; - goto out_release_ref; - } - memset(conn, 0, sizeof(struct iscsi_if_conn)); - INIT_LIST_HEAD(&conn->session_list); - INIT_LIST_HEAD(&conn->conn_list); - conn->host = shost; - conn->transport = transport; + conn = transport->create_conn(shost, ev->u.c_conn.cid); + if (!conn) + goto release_ref; - error = mempool_zone_init(&conn->z_pdu, Z_MAX_PDU, + conn->z_pdu = mempool_zone_init(Z_MAX_PDU, NLMSG_SPACE(sizeof(struct iscsi_uevent) + sizeof(struct iscsi_hdr) + DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH), Z_HIWAT_PDU); - if (error) { - printk(KERN_ERR "iscsi%d: can not allocate pdu zone for new " - "conn\n", shost->host_no); - goto out_free_conn; + if (!conn->z_pdu) { + dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate " + "pdu zone for new conn\n"); + goto destroy_conn; } - error = mempool_zone_init(&conn->z_error, Z_MAX_ERROR, + + conn->z_error = mempool_zone_init(Z_MAX_ERROR, NLMSG_SPACE(sizeof(struct iscsi_uevent)), Z_HIWAT_ERROR); - if (error) { - printk(KERN_ERR "iscsi%d: can not allocate error zone for " - "new conn\n", shost->host_no); - goto out_free_pdu_pool; - } - - ev->r.handle = transport->create_conn(ev->u.c_conn.session_handle, - ev->u.c_conn.cid); - if (!ev->r.handle) { - error = -ENODEV; - goto out_free_error_pool; + if (!conn->z_error) { + dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate " + "error zone for new conn\n"); + goto free_pdu_pool; } - conn->connh = ev->r.handle; - - /* - * this is released in the dev's release function - */ - if (!scsi_host_get(shost)) - goto out_destroy_conn; - snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u", - shost->host_no, ev->u.c_conn.cid); - conn->dev.parent = &session->dev; - conn->dev.release = iscsi_if_conn_dev_release; - error = device_register(&conn->dev); - if (error) { - printk(KERN_ERR "iscsi%d: could not register connections%u " - "dev\n", shost->host_no, ev->u.c_conn.cid); - goto out_release_parent_ref; - } - transport_register_device(&conn->dev); + ev->r.handle = conn->connh = iscsi_handle(conn->dd_data); spin_lock_irqsave(&connlock, flags); list_add(&conn->conn_list, &connlist); - list_add(&conn->session_list, &session->connections); conn->active = 1; spin_unlock_irqrestore(&connlock, flags); scsi_host_put(shost); return 0; -out_release_parent_ref: +free_pdu_pool: + mempool_zone_destroy(conn->z_pdu); +destroy_conn: + if (transport->destroy_conn) + transport->destroy_conn(conn->dd_data); +release_ref: scsi_host_put(shost); -out_destroy_conn: - transport->destroy_conn(ev->r.handle); -out_free_error_pool: - mempool_destroy(conn->z_error.pool); -out_free_pdu_pool: - mempool_destroy(conn->z_pdu.pool); -out_free_conn: - kfree(conn); -out_release_ref: - scsi_host_put(shost); - return error; + return -ENOMEM; } static int iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev) { unsigned long flags; - struct iscsi_if_conn *conn; + struct iscsi_cls_conn *conn; + struct mempool_zone *z_error, *z_pdu; conn = iscsi_if_find_conn(ev->u.d_conn.conn_handle); if (!conn) return -EEXIST; - transport->destroy_conn(ev->u.d_conn.conn_handle); + if (!transport->destroy_conn) + return -EINVAL; spin_lock_irqsave(&connlock, flags); conn->active = 0; list_del(&conn->conn_list); spin_unlock_irqrestore(&connlock, flags); - transport_unregister_device(&conn->dev); - device_unregister(&conn->dev); - return 0; -} - -static int -iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb, - struct nlmsghdr *nlh) -{ - struct iscsi_uevent *ev = NLMSG_DATA(nlh); - struct iscsi_stats *stats; - struct sk_buff *skbstat; - struct iscsi_if_conn *conn; - struct nlmsghdr *nlhstat; - struct iscsi_uevent *evstat; - int len = NLMSG_SPACE(sizeof(*ev) + - sizeof(struct iscsi_stats) + - sizeof(struct iscsi_stats_custom) * - ISCSI_STATS_CUSTOM_MAX); - int err = 0; - - conn = iscsi_if_find_conn(ev->u.get_stats.conn_handle); - if (!conn) - return -EEXIST; - - do { - int actual_size; - - mempool_zone_complete(&conn->z_pdu); - - skbstat = mempool_zone_get_skb(&conn->z_pdu); - if (!skbstat) { - printk(KERN_ERR "iscsi%d: can not deliver stats: OOM\n", - conn->host->host_no); - return -ENOMEM; - } - - nlhstat = __nlmsg_put(skbstat, daemon_pid, 0, 0, - (len - sizeof(*nlhstat)), 0); - evstat = NLMSG_DATA(nlhstat); - memset(evstat, 0, sizeof(*evstat)); - evstat->transport_handle = iscsi_handle(conn->transport); - evstat->type = nlh->nlmsg_type; - if (atomic_read(&conn->z_pdu.allocated) >= conn->z_pdu.hiwat) - evstat->iferror = -ENOMEM; - evstat->u.get_stats.conn_handle = - ev->u.get_stats.conn_handle; - stats = (struct iscsi_stats *) - ((char*)evstat + sizeof(*evstat)); - memset(stats, 0, sizeof(*stats)); + z_pdu = conn->z_pdu; + z_error = conn->z_error; - transport->get_stats(ev->u.get_stats.conn_handle, stats); - actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) + - sizeof(struct iscsi_stats) + - sizeof(struct iscsi_stats_custom) * - stats->custom_length); - actual_size -= sizeof(*nlhstat); - actual_size = NLMSG_LENGTH(actual_size); - skb_trim(skb, NLMSG_ALIGN(actual_size)); - nlhstat->nlmsg_len = actual_size; + if (transport->destroy_conn) + transport->destroy_conn(conn); - err = iscsi_unicast_skb(&conn->z_pdu, skbstat); - } while (err < 0 && err != -ECONNREFUSED); + mempool_zone_destroy(z_pdu); + mempool_zone_destroy(z_error); - return err; + return 0; } static int @@ -916,8 +971,8 @@ iscsi_if_rx(struct sock *sk, int len) err = iscsi_if_send_reply( NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq, nlh->nlmsg_type, 0, 0, ev, sizeof(*ev)); - if (atomic_read(&z_reply.allocated) >= - z_reply.hiwat) + if (atomic_read(&z_reply->allocated) >= + z_reply->hiwat) ev->iferror = -ENOMEM; } while (err < 0 && err != -ECONNREFUSED); skb_pull(skb, rlen); @@ -927,6 +982,9 @@ iscsi_if_rx(struct sock *sk, int len) mutex_unlock(&rx_queue_mutex); } +#define iscsi_cdev_to_conn(_cdev) \ + iscsi_dev_to_conn(_cdev->dev) + /* * iSCSI connection attrs */ @@ -935,12 +993,10 @@ static ssize_t \ show_conn_int_param_##param(struct class_device *cdev, char *buf) \ { \ uint32_t value = 0; \ - struct iscsi_if_conn *conn = iscsi_cdev_to_if_conn(cdev); \ - struct iscsi_internal *priv; \ + struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev); \ + struct iscsi_transport *t = conn->transport; \ \ - priv = to_iscsi_internal(conn->host->transportt); \ - if (priv->param_mask & (1 << param)) \ - priv->iscsi_transport->get_param(conn->connh, param, &value); \ + t->get_conn_param(conn->dd_data, param, &value); \ return snprintf(buf, 20, format"\n", value); \ } @@ -955,6 +1011,9 @@ iscsi_conn_int_attr(data_digest, ISCSI_PARAM_DATADGST_EN, "%d"); iscsi_conn_int_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN, "%d"); iscsi_conn_int_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN, "%d"); +#define iscsi_cdev_to_session(_cdev) \ + iscsi_dev_to_session(_cdev->dev) + /* * iSCSI session attrs */ @@ -963,20 +1022,11 @@ static ssize_t \ show_session_int_param_##param(struct class_device *cdev, char *buf) \ { \ uint32_t value = 0; \ - struct iscsi_if_session *session = iscsi_cdev_to_if_session(cdev); \ - struct Scsi_Host *shost = iscsi_if_session_to_shost(session); \ - struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); \ - struct iscsi_if_conn *conn = NULL; \ - unsigned long flags; \ - \ - spin_lock_irqsave(&connlock, flags); \ - if (!list_empty(&session->connections)) \ - conn = list_entry(session->connections.next, \ - struct iscsi_if_conn, session_list); \ - spin_unlock_irqrestore(&connlock, flags); \ + struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \ + struct Scsi_Host *shost = iscsi_session_to_shost(session); \ + struct iscsi_transport *t = session->transport; \ \ - if (conn && (priv->param_mask & (1 << param))) \ - priv->iscsi_transport->get_param(conn->connh, param, &value);\ + t->get_session_param(shost, param, &value); \ return snprintf(buf, 20, format"\n", value); \ } @@ -1005,23 +1055,18 @@ iscsi_session_int_attr(erl, ISCSI_PARAM_ERL, "%d"); count++; \ } -static int iscsi_is_session_dev(const struct device *dev) -{ - return dev->release == iscsi_if_session_dev_release; -} - static int iscsi_session_match(struct attribute_container *cont, struct device *dev) { - struct iscsi_if_session *session; + struct iscsi_cls_session *session; struct Scsi_Host *shost; struct iscsi_internal *priv; if (!iscsi_is_session_dev(dev)) return 0; - session = iscsi_dev_to_if_session(dev); - shost = iscsi_if_session_to_shost(session); + session = iscsi_dev_to_session(dev); + shost = iscsi_session_to_shost(session); if (!shost->transportt) return 0; @@ -1032,23 +1077,21 @@ static int iscsi_session_match(struct attribute_container *cont, return &priv->session_cont.ac == cont; } -static int iscsi_is_conn_dev(const struct device *dev) -{ - return dev->release == iscsi_if_conn_dev_release; -} - static int iscsi_conn_match(struct attribute_container *cont, struct device *dev) { - struct iscsi_if_conn *conn; + struct iscsi_cls_session *session; + struct iscsi_cls_conn *conn; struct Scsi_Host *shost; struct iscsi_internal *priv; if (!iscsi_is_conn_dev(dev)) return 0; - conn = iscsi_dev_to_if_conn(dev); - shost = conn->host; + conn = iscsi_dev_to_conn(dev); + session = iscsi_dev_to_session(conn->dev.parent); + shost = iscsi_session_to_shost(session); + if (!shost->transportt) return 0; @@ -1059,7 +1102,8 @@ static int iscsi_conn_match(struct attribute_container *cont, return &priv->conn_cont.ac == cont; } -int iscsi_register_transport(struct iscsi_transport *tt) +struct scsi_transport_template * +iscsi_register_transport(struct iscsi_transport *tt) { struct iscsi_internal *priv; unsigned long flags; @@ -1069,15 +1113,14 @@ int iscsi_register_transport(struct iscsi_transport *tt) priv = iscsi_if_transport_lookup(tt); if (priv) - return -EEXIST; + return NULL; priv = kmalloc(sizeof(*priv), GFP_KERNEL); if (!priv) - return -ENOMEM; + return NULL; memset(priv, 0, sizeof(*priv)); INIT_LIST_HEAD(&priv->list); INIT_LIST_HEAD(&priv->sessions); - spin_lock_init(&priv->session_lock); priv->iscsi_transport = tt; priv->cdev.class = &iscsi_transport_class; @@ -1143,13 +1186,13 @@ int iscsi_register_transport(struct iscsi_transport *tt) spin_unlock_irqrestore(&iscsi_transport_lock, flags); printk(KERN_NOTICE "iscsi: registered transport (%s)\n", tt->name); - return 0; + return &priv->t; unregister_cdev: class_device_unregister(&priv->cdev); free_priv: kfree(priv); - return err; + return NULL; } EXPORT_SYMBOL_GPL(iscsi_register_transport); @@ -1165,14 +1208,6 @@ int iscsi_unregister_transport(struct iscsi_transport *tt) priv = iscsi_if_transport_lookup(tt); BUG_ON (!priv); - spin_lock_irqsave(&priv->session_lock, flags); - if (!list_empty(&priv->sessions)) { - spin_unlock_irqrestore(&priv->session_lock, flags); - mutex_unlock(&rx_queue_mutex); - return -EPERM; - } - spin_unlock_irqrestore(&priv->session_lock, flags); - spin_lock_irqsave(&iscsi_transport_lock, flags); list_del(&priv->list); spin_unlock_irqrestore(&iscsi_transport_lock, flags); @@ -1195,14 +1230,14 @@ iscsi_rcv_nl_event(struct notifier_block *this, unsigned long event, void *ptr) if (event == NETLINK_URELEASE && n->protocol == NETLINK_ISCSI && n->pid) { - struct iscsi_if_conn *conn; + struct iscsi_cls_conn *conn; unsigned long flags; - mempool_zone_complete(&z_reply); + mempool_zone_complete(z_reply); spin_lock_irqsave(&connlock, flags); list_for_each_entry(conn, &connlist, conn_list) { - mempool_zone_complete(&conn->z_error); - mempool_zone_complete(&conn->z_pdu); + mempool_zone_complete(conn->z_error); + mempool_zone_complete(conn->z_pdu); } spin_unlock_irqrestore(&connlock, flags); } @@ -1235,15 +1270,15 @@ static __init int iscsi_transport_init(void) goto unregister_session_class; nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx, - THIS_MODULE); + THIS_MODULE); if (!nls) { err = -ENOBUFS; goto unregister_notifier; } - err = mempool_zone_init(&z_reply, Z_MAX_REPLY, + z_reply = mempool_zone_init(Z_MAX_REPLY, NLMSG_SPACE(sizeof(struct iscsi_uevent)), Z_HIWAT_REPLY); - if (!err) + if (z_reply) return 0; sock_release(nls->sk_socket); @@ -1260,7 +1295,7 @@ unregister_transport_class: static void __exit iscsi_transport_exit(void) { - mempool_destroy(z_reply.pool); + mempool_zone_destroy(z_reply); sock_release(nls->sk_socket); netlink_unregister_notifier(&iscsi_nl_notifier); transport_class_unregister(&iscsi_connection_class); diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h index be1bc792ab1..3e5cb5ab2d3 100644 --- a/include/scsi/iscsi_if.h +++ b/include/scsi/iscsi_if.h @@ -168,6 +168,12 @@ typedef uint64_t iscsi_connh_t; /* iSCSI Data-Path connection handle */ #define iscsi_ptr(_handle) ((void*)(unsigned long)_handle) #define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr) +#define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata)) + +/** + * iscsi_hostdata - get LLD hostdata from scsi_host + * @_hostdata: pointer to scsi host's hostdata + **/ #define iscsi_hostdata(_hostdata) ((void*)_hostdata + sizeof(unsigned long)) /* diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index f25041c386e..16602a547a6 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -23,8 +23,14 @@ #ifndef SCSI_TRANSPORT_ISCSI_H #define SCSI_TRANSPORT_ISCSI_H +#include #include +struct scsi_transport_template; +struct Scsi_Host; +struct mempool_zone; +struct iscsi_cls_conn; + /** * struct iscsi_transport - iSCSI Transport template * @@ -48,23 +54,31 @@ struct iscsi_transport { char *name; unsigned int caps; struct scsi_host_template *host_template; + /* LLD session/scsi_host data size */ int hostdata_size; + /* LLD iscsi_host data size */ + int ihostdata_size; + /* LLD connection data size */ + int conndata_size; int max_lun; unsigned int max_conn; unsigned int max_cmd_len; - iscsi_sessionh_t (*create_session) (uint32_t initial_cmdsn, - struct Scsi_Host *shost); - void (*destroy_session) (iscsi_sessionh_t session); - iscsi_connh_t (*create_conn) (iscsi_sessionh_t session, uint32_t cid); + struct Scsi_Host *(*create_session) (struct scsi_transport_template *t, + uint32_t initial_cmdsn); + void (*destroy_session) (struct Scsi_Host *shost); + struct iscsi_cls_conn *(*create_conn) (struct Scsi_Host *shost, + uint32_t cid); int (*bind_conn) (iscsi_sessionh_t session, iscsi_connh_t conn, uint32_t transport_fd, int is_leading); int (*start_conn) (iscsi_connh_t conn); void (*stop_conn) (iscsi_connh_t conn, int flag); - void (*destroy_conn) (iscsi_connh_t conn); + void (*destroy_conn) (struct iscsi_cls_conn *conn); int (*set_param) (iscsi_connh_t conn, enum iscsi_param param, uint32_t value); - int (*get_param) (iscsi_connh_t conn, enum iscsi_param param, - uint32_t *value); + int (*get_conn_param) (void *conndata, enum iscsi_param param, + uint32_t *value); + int (*get_session_param) (struct Scsi_Host *shost, + enum iscsi_param param, uint32_t *value); int (*send_pdu) (iscsi_connh_t conn, struct iscsi_hdr *hdr, char *data, uint32_t data_size); void (*get_stats) (iscsi_connh_t conn, struct iscsi_stats *stats); @@ -73,7 +87,7 @@ struct iscsi_transport { /* * transport registration upcalls */ -extern int iscsi_register_transport(struct iscsi_transport *tt); +extern struct scsi_transport_template *iscsi_register_transport(struct iscsi_transport *tt); extern int iscsi_unregister_transport(struct iscsi_transport *tt); /* @@ -83,4 +97,49 @@ extern void iscsi_conn_error(iscsi_connh_t conn, enum iscsi_err error); extern int iscsi_recv_pdu(iscsi_connh_t conn, struct iscsi_hdr *hdr, char *data, uint32_t data_size); +struct iscsi_cls_conn { + struct list_head conn_list; /* item in connlist */ + void *dd_data; /* LLD private data */ + struct iscsi_transport *transport; + iscsi_connh_t connh; + int active; /* must be accessed with the connlock */ + struct device dev; /* sysfs transport/container device */ + struct mempool_zone *z_error; + struct mempool_zone *z_pdu; + struct list_head freequeue; +}; + +#define iscsi_dev_to_conn(_dev) \ + container_of(_dev, struct iscsi_cls_conn, dev) + +struct iscsi_cls_session { + struct list_head list; /* item in session_list */ + struct iscsi_transport *transport; + struct device dev; /* sysfs transport/container device */ +}; + +#define iscsi_dev_to_session(_dev) \ + container_of(_dev, struct iscsi_cls_session, dev) + +#define iscsi_session_to_shost(_session) \ + dev_to_shost(_session->dev.parent) + +/* + * session and connection functions that can be used by HW iSCSI LLDs + */ +extern struct iscsi_cls_session *iscsi_create_session(struct Scsi_Host *shost, + struct iscsi_transport *t); +extern int iscsi_destroy_session(struct iscsi_cls_session *session); +extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess, + uint32_t cid); +extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn); + +/* + * session functions used by software iscsi + */ +extern struct Scsi_Host * +iscsi_transport_create_session(struct scsi_transport_template *scsit, + struct iscsi_transport *transport); +extern int iscsi_transport_destroy_session(struct Scsi_Host *shost); + #endif -- GitLab From 55e3299d9eca01fb2351c5d37e222872b7c6e0af Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Fri, 13 Jan 2006 18:05:53 -0600 Subject: [PATCH 219/465] [SCSI] iscsi: fix 4k stack iscsi setups When we run the xmit code from queuecomand the stack trace gets too deep. The patch runs the xmit code from the scsi_host work queue. This fixes 4k stack and xfs support and should fix the st and sg stack usage bugs. Signed-off-by: Alex Aizman Signed-off-by: Dmitry Yusupov Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 19 +++++-------------- drivers/scsi/scsi_transport_iscsi.c | 1 + 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index e31d350e6b6..4e4b1061a5e 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -525,7 +525,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) __kfifo_put(ctask->r2tqueue, (void*)&r2t, sizeof(void*)); __kfifo_put(conn->writequeue, (void*)&ctask, sizeof(void*)); - schedule_work(&conn->xmitwork); + scsi_queue_work(session->host, &conn->xmitwork); conn->r2t_pdus_cnt++; spin_unlock(&session->lock); @@ -1267,7 +1267,7 @@ iscsi_write_space(struct sock *sk) conn->old_write_space(sk); debug_tcp("iscsi_write_space: cid %d\n", conn->id); clear_bit(SUSPEND_BIT, &conn->suspend_tx); - schedule_work(&conn->xmitwork); + scsi_queue_work(conn->session->host, &conn->xmitwork); } static void @@ -2275,7 +2275,7 @@ iscsi_xmitworker(void *data) */ mutex_lock(&conn->xmitmutex); if (iscsi_data_xmit(conn)) - schedule_work(&conn->xmitwork); + scsi_queue_work(conn->session->host, &conn->xmitwork); mutex_unlock(&conn->xmitmutex); } @@ -2340,15 +2340,7 @@ iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1); spin_unlock(&session->lock); - if (!in_interrupt() && mutex_trylock(&conn->xmitmutex)) { - spin_unlock_irq(host->host_lock); - if (iscsi_data_xmit(conn)) - schedule_work(&conn->xmitwork); - mutex_unlock(&conn->xmitmutex); - spin_lock_irq(host->host_lock); - } else - schedule_work(&conn->xmitwork); - + scsi_queue_work(host, &conn->xmitwork); return 0; reject: @@ -2942,8 +2934,7 @@ iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr, else __kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*)); - schedule_work(&conn->xmitwork); - + scsi_queue_work(session->host, &conn->xmitwork); return 0; } diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 45e31635a59..59a1c9d9d3b 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -379,6 +379,7 @@ iscsi_transport_create_session(struct scsi_transport_template *scsit, shost->max_lun = transport->max_lun; shost->max_cmd_len = transport->max_cmd_len; shost->transportt = scsit; + shost->transportt->create_work_queue = 1; if (scsi_add_host(shost, NULL)) goto free_host; -- GitLab From a1e80c20e1ac751dbdd88dee989e9a19c22c4a84 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Fri, 13 Jan 2006 18:05:56 -0600 Subject: [PATCH 220/465] [SCSI] iscsi: use pageslab From: FUJITA Tomonori and zhenyu.z.wang@intel.com: We cannot handle filesystems like XFS becuase of the pages they are sending us. We had thought page_count could be used to work around this, but the correct test is for PageSlab. The proper solution is to figure out what type of pages filesystems can use so we do not have to add tests like this or handle it in the block layer for all network block drivers but the issue still has not been resolved on fs-devel so we are sending this patch as a temporary fix. This is last patch just in case it is Nakd with the explanation that we need to push the correct fix through fs-devel, mm or the block layer. The rest of the patchset can live without the patch, but the driver will not work with filesystems like XFS. Signed-off-by: Alex Aizman Signed-off-by: Dmitry Yusupov Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 4e4b1061a5e..1b495afe6d1 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -109,7 +109,7 @@ iscsi_buf_init_sg(struct iscsi_buf *ibuf, struct scatterlist *sg) /* * Fastpath: sg element fits into single page */ - if (sg->length + sg->offset <= PAGE_SIZE && page_count(sg->page) >= 2) + if (sg->length + sg->offset <= PAGE_SIZE && !PageSlab(sg->page)) ibuf->use_sendmsg = 0; else ibuf->use_sendmsg = 1; -- GitLab From dad9c8c15dbe4eac0ab086c74cdb256ec2fb0b70 Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Fri, 13 Jan 2006 17:04:49 -0800 Subject: [PATCH 221/465] [SCSI] qla2xxx: Reference proper node/port names in fc_host class. The initial-control-block references are not always correct as the use-node-name qualifier during NVRAM configuration will cause the firmware to use the portname as a base for the nodename. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 2efca52dff5..b17ee62dd1a 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -541,7 +541,7 @@ struct fc_function_template qla2xxx_transport_functions = { void qla2x00_init_host_attr(scsi_qla_host_t *ha) { - fc_host_node_name(ha->host) = wwn_to_u64(ha->init_cb->node_name); - fc_host_port_name(ha->host) = wwn_to_u64(ha->init_cb->port_name); + fc_host_node_name(ha->host) = wwn_to_u64(ha->node_name); + fc_host_port_name(ha->host) = wwn_to_u64(ha->port_name); fc_host_supported_classes(ha->host) = FC_COS_CLASS3; } -- GitLab From 9403688e9bca54b55bfcea51053c8af537beba0a Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Fri, 13 Jan 2006 17:04:54 -0800 Subject: [PATCH 222/465] [SCSI] qla2xxx: Correct FC4 feature assignment during RFF_ID. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_gs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index cd6f7c3cfe6..0e8ada08104 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -538,6 +538,7 @@ qla2x00_rff_id(scsi_qla_host_t *ha) ct_req->req.rff_id.port_id[1] = ha->d_id.b.area; ct_req->req.rff_id.port_id[2] = ha->d_id.b.al_pa; + ct_req->req.rff_id.fc4_feature = BIT_1; ct_req->req.rff_id.fc4_type = 0x08; /* SCSI - FCP */ /* Execute MS IOCB */ -- GitLab From e038a1be22bef90795c5239d1563609b89c3aa18 Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Fri, 13 Jan 2006 17:04:59 -0800 Subject: [PATCH 223/465] [SCSI] qla2xxx: Drop noisy 'UNDERRUN' status message. There's no point in displaying the message during a valid underrun case. Limit the message to potentially problematic cases. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_isr.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 5181d966fec..8a539dd4875 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -963,15 +963,16 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) break; case CS_DATA_UNDERRUN: - DEBUG2(printk(KERN_INFO - "scsi(%ld:%d:%d) UNDERRUN status detected 0x%x-0x%x.\n", - ha->host_no, cp->device->id, cp->device->lun, comp_status, - scsi_status)); - resid = resid_len; if (scsi_status & SS_RESIDUAL_UNDER) { cp->resid = resid; CMD_RESID_LEN(cp) = resid; + } else { + DEBUG2(printk(KERN_INFO + "scsi(%ld:%d:%d) UNDERRUN status detected " + "0x%x-0x%x.\n", ha->host_no, cp->device->id, + cp->device->lun, comp_status, scsi_status)); + } /* -- GitLab From 03ab2eabed74708c0c74163723007e8e72244219 Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Fri, 13 Jan 2006 17:05:05 -0800 Subject: [PATCH 224/465] [SCSI] qla2xxx: Use msleep() as delay during ISP polling. Mailbox commands are polled for completion during ISP initialization. During potentially 'long' mailbox commands (i.e. fabric login), we really don't want a busy-wait delay to potentially trigger a (benign) soft-lockup BUG(). Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_mbx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 9746cd1e664..f90e68de0a8 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -196,7 +196,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) /* Check for pending interrupts. */ qla2x00_poll(ha); - udelay(10); /* v4.27 */ + msleep(10); } /* while */ } -- GitLab From 5998983113c1c9158c1ce66ff26a212aceaf7e5c Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Fri, 13 Jan 2006 17:05:10 -0800 Subject: [PATCH 225/465] [SCSI] qla2xxx: Correct excessive delay during LOAD-RISC-RAM mailbox command. Problem report (against 2.4.x driver) from Jeff Layton : An OEM noticed that the U6 qla2200 driver would hang for around 2 minutes at boot time and then proceed normally. I found that the delay was occurring when loading the new firmware into the card, and was due to a schedule_timeout(10) added to the bottom of the polling loop. Some testing showed that the load ram operation on the card was very quick (on the order of a couple of jiffies), but the sleep in the polling loop was making each operation take around 25-30. The attached patch corrects this by making it skip sleeping during the load ram operation, since I believe we only do that when the module is plugged in. It also skips sleeping if the mbox_int flag got set during the current loop. This corrected the hang on my test setup, and OEM also confirmed that it corrected the problem for them. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_mbx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index f90e68de0a8..3de8fee69fa 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -196,7 +196,9 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) /* Check for pending interrupts. */ qla2x00_poll(ha); - msleep(10); + if (command != MBC_LOAD_RISC_RAM_EXTENDED && + !ha->flags.mbox_int) + msleep(10); } /* while */ } -- GitLab From e978010cebcc0ac1be67caab8dfc7c1fa831406d Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Fri, 13 Jan 2006 17:05:15 -0800 Subject: [PATCH 226/465] [SCSI] qla2xxx: Re-enable flash-part write protection on ISP24xx boards. Driver would not correctly re-enable the write-protection bits of the flash part after updates. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_sup.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index d54d2a99c3d..f4d755a643e 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -573,6 +573,9 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, } } while (0); + /* Enable flash write-protection. */ + qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0x9c); + /* Disable flash write. */ WRT_REG_DWORD(®->ctrl_status, RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE); -- GitLab From 210d53507e961b0f480d1a86d9a26832cc68645e Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Fri, 13 Jan 2006 17:05:21 -0800 Subject: [PATCH 227/465] [SCSI] qla2xxx: Update firmware-dump procedure for ISP24xx. Small changes to register retrieval and order as per latest firmware specification. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_dbg.c | 105 +++++++++++++++++---------------- drivers/scsi/qla2xxx/qla_dbg.h | 4 +- 2 files changed, 55 insertions(+), 54 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 5c5d2315cfa..2d9b12ffe09 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -1003,10 +1003,10 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) fw = (struct qla24xx_fw_dump *) ha->fw_dump24; rval = QLA_SUCCESS; - fw->hccr = RD_REG_DWORD(®->hccr); + fw->host_status = RD_REG_DWORD(®->host_status); /* Pause RISC. */ - if ((fw->hccr & HCCRX_RISC_PAUSE) == 0) { + if ((RD_REG_DWORD(®->hccr) & HCCRX_RISC_PAUSE) == 0) { WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_RESET | HCCRX_CLR_HOST_INT); RD_REG_DWORD(®->hccr); /* PCI Posting. */ @@ -1021,16 +1021,54 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) } } - /* Disable interrupts. */ - WRT_REG_DWORD(®->ictrl, 0); - RD_REG_DWORD(®->ictrl); - if (rval == QLA_SUCCESS) { /* Host interface registers. */ dmp_reg = (uint32_t __iomem *)(reg + 0); for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++) fw->host_reg[cnt] = RD_REG_DWORD(dmp_reg++); + /* Disable interrupts. */ + WRT_REG_DWORD(®->ictrl, 0); + RD_REG_DWORD(®->ictrl); + + /* Shadow registers. */ + WRT_REG_DWORD(®->iobase_addr, 0x0F70); + RD_REG_DWORD(®->iobase_addr); + dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); + WRT_REG_DWORD(dmp_reg, 0xB0000000); + dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); + fw->shadow_reg[0] = RD_REG_DWORD(dmp_reg); + + dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); + WRT_REG_DWORD(dmp_reg, 0xB0100000); + dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); + fw->shadow_reg[1] = RD_REG_DWORD(dmp_reg); + + dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); + WRT_REG_DWORD(dmp_reg, 0xB0200000); + dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); + fw->shadow_reg[2] = RD_REG_DWORD(dmp_reg); + + dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); + WRT_REG_DWORD(dmp_reg, 0xB0300000); + dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); + fw->shadow_reg[3] = RD_REG_DWORD(dmp_reg); + + dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); + WRT_REG_DWORD(dmp_reg, 0xB0400000); + dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); + fw->shadow_reg[4] = RD_REG_DWORD(dmp_reg); + + dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); + WRT_REG_DWORD(dmp_reg, 0xB0500000); + dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); + fw->shadow_reg[5] = RD_REG_DWORD(dmp_reg); + + dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); + WRT_REG_DWORD(dmp_reg, 0xB0600000); + dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); + fw->shadow_reg[6] = RD_REG_DWORD(dmp_reg); + /* Mailbox registers. */ mbx_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) @@ -1308,43 +1346,6 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = RD_REG_DWORD(dmp_reg++); - WRT_REG_DWORD(®->iobase_addr, 0x0F70); - RD_REG_DWORD(®->iobase_addr); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); - WRT_REG_DWORD(dmp_reg, 0xB0000000); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); - fw->shadow_reg[0] = RD_REG_DWORD(dmp_reg); - - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); - WRT_REG_DWORD(dmp_reg, 0xB0100000); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); - fw->shadow_reg[1] = RD_REG_DWORD(dmp_reg); - - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); - WRT_REG_DWORD(dmp_reg, 0xB0200000); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); - fw->shadow_reg[2] = RD_REG_DWORD(dmp_reg); - - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); - WRT_REG_DWORD(dmp_reg, 0xB0300000); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); - fw->shadow_reg[3] = RD_REG_DWORD(dmp_reg); - - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); - WRT_REG_DWORD(dmp_reg, 0xB0400000); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); - fw->shadow_reg[4] = RD_REG_DWORD(dmp_reg); - - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); - WRT_REG_DWORD(dmp_reg, 0xB0500000); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); - fw->shadow_reg[5] = RD_REG_DWORD(dmp_reg); - - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); - WRT_REG_DWORD(dmp_reg, 0xB0600000); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); - fw->shadow_reg[6] = RD_REG_DWORD(dmp_reg); - /* Local memory controller registers. */ iter_reg = fw->lmc_reg; WRT_REG_DWORD(®->iobase_addr, 0x3000); @@ -1677,7 +1678,7 @@ qla24xx_ascii_fw_dump(scsi_qla_host_t *ha) ha->fw_major_version, ha->fw_minor_version, ha->fw_subminor_version, ha->fw_attributes); - qla_uprintf(&uiter, "\nHCCR Register\n%04x\n", fw->hccr); + qla_uprintf(&uiter, "\nR2H Status Register\n%04x\n", fw->host_status); qla_uprintf(&uiter, "\nHost Interface Registers"); for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++) { @@ -1687,6 +1688,14 @@ qla24xx_ascii_fw_dump(scsi_qla_host_t *ha) qla_uprintf(&uiter, "%08x ", fw->host_reg[cnt]); } + qla_uprintf(&uiter, "\n\nShadow Registers"); + for (cnt = 0; cnt < sizeof(fw->shadow_reg) / 4; cnt++) { + if (cnt % 8 == 0) + qla_uprintf(&uiter, "\n"); + + qla_uprintf(&uiter, "%08x ", fw->shadow_reg[cnt]); + } + qla_uprintf(&uiter, "\n\nMailbox Registers"); for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) { if (cnt % 8 == 0) @@ -1855,14 +1864,6 @@ qla24xx_ascii_fw_dump(scsi_qla_host_t *ha) qla_uprintf(&uiter, "%08x ", fw->risc_gp_reg[cnt]); } - qla_uprintf(&uiter, "\n\nShadow Registers"); - for (cnt = 0; cnt < sizeof(fw->shadow_reg) / 4; cnt++) { - if (cnt % 8 == 0) - qla_uprintf(&uiter, "\n"); - - qla_uprintf(&uiter, "%08x ", fw->shadow_reg[cnt]); - } - qla_uprintf(&uiter, "\n\nLMC Registers"); for (cnt = 0; cnt < sizeof(fw->lmc_reg) / 4; cnt++) { if (cnt % 8 == 0) diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h index 935a59a8c05..ab6afeaa2f2 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.h +++ b/drivers/scsi/qla2xxx/qla_dbg.h @@ -227,8 +227,9 @@ struct qla2100_fw_dump { #define FW_DUMP_SIZE_24XX 0x2B0000 struct qla24xx_fw_dump { - uint32_t hccr; + uint32_t host_status; uint32_t host_reg[32]; + uint32_t shadow_reg[7]; uint16_t mailbox_reg[32]; uint32_t xseq_gp_reg[128]; uint32_t xseq_0_reg[16]; @@ -250,7 +251,6 @@ struct qla24xx_fw_dump { uint32_t rcvt0_data_dma_reg[32]; uint32_t rcvt1_data_dma_reg[32]; uint32_t risc_gp_reg[128]; - uint32_t shadow_reg[7]; uint32_t lmc_reg[112]; uint32_t fpm_hdw_reg[192]; uint32_t fb_hdw_reg[176]; -- GitLab From c9d02acf39d9fdde18b63281944003b9ec9a3271 Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Fri, 13 Jan 2006 17:05:26 -0800 Subject: [PATCH 228/465] [SCSI] qla2xxx: Correct issue where portstate does not transition during loop-resync. If the Get Port Database call fails during local-loop update, then schedule the DPC routine to perform a rescan as the firmware would have updated the Get ID List port-entries of their new state. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 7d973bd9022..e21316a8ecf 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1939,6 +1939,9 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) "information -- get_port_database=%x, " "loop_id=0x%04x\n", ha->host_no, rval2, new_fcport->loop_id)); + DEBUG2(printk("scsi(%ld): Scheduling resync...\n", + ha->host_no)); + set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); continue; } -- GitLab From f94097edf2c3ac9bc48580252c2eee52947b5e60 Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Fri, 13 Jan 2006 17:05:32 -0800 Subject: [PATCH 229/465] [SCSI] qla2xxx: Correct swing/emphasis settings for ISP24XX. Swing/emphasis settings in NVRAM were not being honoured due to the driver not converting the serial-link options from LE to host-endian format. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index e21316a8ecf..49e831561d1 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1014,11 +1014,13 @@ qla24xx_update_fw_options(scsi_qla_host_t *ha) int rval; /* Update Serial Link options. */ - if ((ha->fw_seriallink_options24[0] & BIT_0) == 0) + if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0) return; - rval = qla2x00_set_serdes_params(ha, ha->fw_seriallink_options24[1], - ha->fw_seriallink_options24[2], ha->fw_seriallink_options24[3]); + rval = qla2x00_set_serdes_params(ha, + le16_to_cpu(ha->fw_seriallink_options24[1]), + le16_to_cpu(ha->fw_seriallink_options24[2]), + le16_to_cpu(ha->fw_seriallink_options24[3])); if (rval != QLA_SUCCESS) { qla_printk(KERN_WARNING, ha, "Unable to update Serial Link options (%x).\n", rval); -- GitLab From 590f98e5e8d6502cc21fdcddc90a0cc09c1f770e Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Fri, 13 Jan 2006 17:05:37 -0800 Subject: [PATCH 230/465] [SCSI] qla2xxx: Collapse load RISC RAM implementations. Simplify essentially duplicate load RISC RAM implementation in qla2x00_load_ram_ext() and qla2x00_load_ram(). Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_gbl.h | 5 +- drivers/scsi/qla2xxx/qla_init.c | 8 +-- drivers/scsi/qla2xxx/qla_mbx.c | 103 ++++---------------------------- 3 files changed, 15 insertions(+), 101 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index bec81adcf4f..7872c11f06e 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -96,10 +96,7 @@ int __qla2x00_marker(scsi_qla_host_t *, uint16_t, uint16_t, uint8_t); * Global Function Prototypes in qla_mbx.c source file. */ extern int -qla2x00_load_ram(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t); - -extern int -qla2x00_load_ram_ext(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t); +qla2x00_load_ram(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t); extern int qla2x00_execute_fw(scsi_qla_host_t *, uint32_t); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 49e831561d1..b4fbef5bf40 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -3672,8 +3672,8 @@ qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr) for (i = 0; i < dlen; i++) dcode[i] = swab32(dcode[i]); - rval = qla2x00_load_ram_ext(ha, ha->request_dma, - risc_addr, dlen); + rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr, + dlen); if (rval) { DEBUG(printk("scsi(%ld):[ERROR] Failed to load " "segment %d of firmware\n", ha->host_no, @@ -3873,8 +3873,8 @@ qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) for (i = 0; i < dlen; i++) dcode[i] = swab32(fwcode[i]); - rval = qla2x00_load_ram_ext(ha, ha->request_dma, - risc_addr, dlen); + rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr, + dlen); if (rval) { DEBUG(printk("scsi(%ld):[ERROR] Failed to load " "segment %d of firmware\n", ha->host_no, diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 3de8fee69fa..3099b379de9 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -327,113 +327,30 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) return rval; } -/* - * qla2x00_load_ram - * Load adapter RAM using DMA. - * - * Input: - * ha = adapter block pointer. - * - * Returns: - * qla2x00 local function return status code. - * - * Context: - * Kernel context. - */ int -qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint16_t risc_addr, - uint16_t risc_code_size) +qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t risc_addr, + uint32_t risc_code_size) { int rval; mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - uint32_t req_len; - dma_addr_t nml_dma; - uint32_t nml_len; - uint32_t normalized; - - DEBUG11(printk("qla2x00_load_ram(%ld): entered.\n", - ha->host_no);) - req_len = risc_code_size; - nml_dma = 0; - nml_len = 0; - - normalized = qla2x00_normalize_dma_addr(&req_dma, &req_len, &nml_dma, - &nml_len); - - /* Load first segment */ - mcp->mb[0] = MBC_LOAD_RISC_RAM; - mcp->mb[1] = risc_addr; - mcp->mb[2] = MSW(req_dma); - mcp->mb[3] = LSW(req_dma); - mcp->mb[4] = (uint16_t)req_len; - mcp->mb[6] = MSW(MSD(req_dma)); - mcp->mb[7] = LSW(MSD(req_dma)); - mcp->out_mb = MBX_7|MBX_6|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; - mcp->in_mb = MBX_0; - mcp->tov = 30; - mcp->flags = 0; - rval = qla2x00_mailbox_command(ha, mcp); - - /* Load second segment - if necessary */ - if (normalized && (rval == QLA_SUCCESS)) { - mcp->mb[0] = MBC_LOAD_RISC_RAM; - mcp->mb[1] = risc_addr + (uint16_t)req_len; - mcp->mb[2] = MSW(nml_dma); - mcp->mb[3] = LSW(nml_dma); - mcp->mb[4] = (uint16_t)nml_len; - mcp->mb[6] = MSW(MSD(nml_dma)); - mcp->mb[7] = LSW(MSD(nml_dma)); - mcp->out_mb = MBX_7|MBX_6|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; - mcp->in_mb = MBX_0; - mcp->tov = 30; - mcp->flags = 0; - rval = qla2x00_mailbox_command(ha, mcp); - } + DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); - if (rval == QLA_SUCCESS) { - /* Empty */ - DEBUG11(printk("qla2x00_load_ram(%ld): done.\n", ha->host_no);) + if (MSW(risc_addr) || IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED; + mcp->mb[8] = MSW(risc_addr); + mcp->out_mb = MBX_8|MBX_0; } else { - /* Empty */ - DEBUG2_3_11(printk("qla2x00_load_ram(%ld): failed. rval=%x " - "mb[0]=%x.\n", ha->host_no, rval, mcp->mb[0]);) + mcp->mb[0] = MBC_LOAD_RISC_RAM; + mcp->out_mb = MBX_0; } - return rval; -} - -/* - * qla2x00_load_ram_ext - * Load adapter extended RAM using DMA. - * - * Input: - * ha = adapter block pointer. - * - * Returns: - * qla2x00 local function return status code. - * - * Context: - * Kernel context. - */ -int -qla2x00_load_ram_ext(scsi_qla_host_t *ha, dma_addr_t req_dma, - uint32_t risc_addr, uint32_t risc_code_size) -{ - int rval; - mbx_cmd_t mc; - mbx_cmd_t *mcp = &mc; - - DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); - - mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED; mcp->mb[1] = LSW(risc_addr); mcp->mb[2] = MSW(req_dma); mcp->mb[3] = LSW(req_dma); mcp->mb[6] = MSW(MSD(req_dma)); mcp->mb[7] = LSW(MSD(req_dma)); - mcp->mb[8] = MSW(risc_addr); - mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1; if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { mcp->mb[4] = MSW(risc_code_size); mcp->mb[5] = LSW(risc_code_size); -- GitLab From bc8fb3cb9e208de0d69223f68058714b78f83833 Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Fri, 13 Jan 2006 17:05:42 -0800 Subject: [PATCH 231/465] [SCSI] qla2xxx: Correct execution-throttle setting for ISP24xx. Similarly to other ISPs, set execution throttle to maximum allowed value since 'throttling' is done on a per-lun basis via queue-depth. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index b4fbef5bf40..8635bd1ae8a 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -3407,6 +3407,8 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) ha->node_name = icb->node_name; ha->port_name = icb->port_name; + icb->execution_throttle = __constant_cpu_to_le16(0xFFFF); + ha->retry_count = le16_to_cpu(nv->login_retry_count); /* Set minimum login_timeout to 4 seconds. */ -- GitLab From c0eb87552654bc3e8da179c501e3e18c92ee4360 Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Fri, 13 Jan 2006 17:05:48 -0800 Subject: [PATCH 232/465] [SCSI] qla2xxx: Correct setting of FDMI supported/current port speed. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_gs.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 0e8ada08104..d620a8e8a61 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -1530,9 +1530,9 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha) eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED); eiter->len = __constant_cpu_to_be16(4 + 4); if (IS_QLA25XX(ha)) - eiter->a.sup_speed = __constant_cpu_to_be32(4); - else if (IS_QLA24XX(ha)) eiter->a.sup_speed = __constant_cpu_to_be32(8); + else if (IS_QLA24XX(ha)) + eiter->a.sup_speed = __constant_cpu_to_be32(4); else if (IS_QLA23XX(ha)) eiter->a.sup_speed = __constant_cpu_to_be32(2); else @@ -1554,9 +1554,6 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha) eiter->a.cur_speed = __constant_cpu_to_be32(2); break; case 3: - eiter->a.cur_speed = __constant_cpu_to_be32(8); - break; - case 4: eiter->a.cur_speed = __constant_cpu_to_be32(4); break; } -- GitLab From fdd52dfa3c311a2583850a2fbea99f329be861d7 Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Fri, 13 Jan 2006 17:05:53 -0800 Subject: [PATCH 233/465] [SCSI] qla2xxx: Kconfig update: Add URL to download firmware images. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig index 02cc79474e8..5758b2566d7 100644 --- a/drivers/scsi/qla2xxx/Kconfig +++ b/drivers/scsi/qla2xxx/Kconfig @@ -22,6 +22,10 @@ config SCSI_QLA_FC Upon request, the driver caches the firmware image until the driver is unloaded. + Firmware images can be retrieved from: + + ftp://ftp.qlogic.com/outgoing/linux/firmware/ + NOTE: The original method of building firmware-loader modules has been deprecated as the firmware-images will be removed from the kernel sources. -- GitLab From 79f89a4296ff22f09baf538d4ff2a6d0c3097a73 Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Fri, 13 Jan 2006 17:05:58 -0800 Subject: [PATCH 234/465] [SCSI] qla2xxx: Disable port-type RSCN handling via driver state-machine. Given the semantic changes in both the device-model and fc-transport APIs, the driver's handling of port-type RSCNs via a series of ADISCs and PLOGIs can cause series of badness ranging from unexpectedly device loss to devices not being discovered. In the interim, disable (via a module-parameter) this feature and allow RSCN management to continue to occur within the driver's DPC thread. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_gbl.h | 1 + drivers/scsi/qla2xxx/qla_init.c | 3 ++- drivers/scsi/qla2xxx/qla_isr.c | 3 ++- drivers/scsi/qla2xxx/qla_os.c | 6 ++++++ 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 7872c11f06e..32be4c14ccc 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -62,6 +62,7 @@ extern int qlport_down_retry; extern int ql2xplogiabsentdevice; extern int ql2xloginretrycount; extern int ql2xfdmienable; +extern int ql2xprocessrscn; extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 8635bd1ae8a..a91fea69ad6 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -2653,7 +2653,8 @@ qla2x00_device_resync(scsi_qla_host_t *ha) switch (format) { case 0: - if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && + if (ql2xprocessrscn && + !IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) && !IS_QLA6322(ha) && !IS_QLA24XX(ha) && !IS_QLA25XX(ha) && ha->flags.init_done) { diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 8a539dd4875..f63af081d4f 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -519,7 +519,8 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) * us, create a new entry in our rscn fcports list and handle * the event like an RSCN. */ - if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) && + if (ql2xprocessrscn && + !IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) && !IS_QLA6322(ha) && !IS_QLA24XX(ha) && !IS_QLA25XX(ha) && ha->flags.init_done && mb[1] != 0xffff && ((ha->operating_mode == P2P && mb[1] != 0) || diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 24304300d7b..4916847d84e 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -71,6 +71,12 @@ MODULE_PARM_DESC(ql2xfdmienable, "Enables FDMI registratons " "Default is 0 - no FDMI. 1 - perfom FDMI."); +int ql2xprocessrscn; +module_param(ql2xprocessrscn, int, S_IRUGO|S_IRUSR); +MODULE_PARM_DESC(ql2xprocessrscn, + "Option to enable port RSCN handling via a series of less" + "fabric intrusive ADISCs and PLOGIs."); + /* * SCSI host template entry points */ -- GitLab From fc091e03820bf67e543362bd40959701a71d0c27 Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Fri, 13 Jan 2006 17:06:04 -0800 Subject: [PATCH 235/465] [SCSI] qla2xxx: Update version number to 8.01.04-k. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index f7937f7f9c6..d537192a1ed 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,9 +7,9 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.01.03-k" +#define QLA2XXX_VERSION "8.01.04-k" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 1 -#define QLA_DRIVER_PATCH_VER 3 +#define QLA_DRIVER_PATCH_VER 4 #define QLA_DRIVER_BETA_VER 0 -- GitLab From 7b4ee73e28052e53aac2fef1c91029666d8b2d70 Mon Sep 17 00:00:00 2001 From: Evgeniy Date: Sat, 14 Jan 2006 11:42:06 +0300 Subject: [PATCH 236/465] [PATCH] ufs cleanup Here is update of ufs cleanup patch, brought on by the recently fixed ubh_get_usb_second() bug that made some ugly code rather painfully obvious. It also includes - fix compilation warnings which appears if debug mode turn on - remove unnecessary duplication of code to support UFS2 I tested it on ufs1 and ufs2 file-systems. Signed-off-by: Evgeniy Dushistov Signed-off-by: Linus Torvalds --- fs/ufs/balloc.c | 19 +++++++++-------- fs/ufs/ialloc.c | 4 ++-- fs/ufs/inode.c | 11 +++++----- fs/ufs/super.c | 57 +++++++++++++++++++++++-------------------------- fs/ufs/util.h | 28 ++++++++++++++++-------- 5 files changed, 64 insertions(+), 55 deletions(-) diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index a9f4421ddb6..3ada9dcf55b 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c @@ -49,7 +49,7 @@ void ufs_free_fragments (struct inode * inode, unsigned fragment, unsigned count sb = inode->i_sb; uspi = UFS_SB(sb)->s_uspi; - usb1 = ubh_get_usb_first(USPI_UBH); + usb1 = ubh_get_usb_first(uspi); UFSD(("ENTER, fragment %u, count %u\n", fragment, count)) @@ -81,8 +81,9 @@ void ufs_free_fragments (struct inode * inode, unsigned fragment, unsigned count for (i = bit; i < end_bit; i++) { if (ubh_isclr (UCPI_UBH, ucpi->c_freeoff, i)) ubh_setbit (UCPI_UBH, ucpi->c_freeoff, i); - else ufs_error (sb, "ufs_free_fragments", - "bit already cleared for fragment %u", i); + else + ufs_error (sb, "ufs_free_fragments", + "bit already cleared for fragment %u", i); } DQUOT_FREE_BLOCK (inode, count); @@ -143,7 +144,7 @@ void ufs_free_blocks (struct inode * inode, unsigned fragment, unsigned count) { sb = inode->i_sb; uspi = UFS_SB(sb)->s_uspi; - usb1 = ubh_get_usb_first(USPI_UBH); + usb1 = ubh_get_usb_first(uspi); UFSD(("ENTER, fragment %u, count %u\n", fragment, count)) @@ -247,7 +248,7 @@ unsigned ufs_new_fragments (struct inode * inode, __fs32 * p, unsigned fragment, sb = inode->i_sb; uspi = UFS_SB(sb)->s_uspi; - usb1 = ubh_get_usb_first(USPI_UBH); + usb1 = ubh_get_usb_first(uspi); *err = -ENOSPC; lock_super (sb); @@ -407,7 +408,7 @@ ufs_add_fragments (struct inode * inode, unsigned fragment, sb = inode->i_sb; uspi = UFS_SB(sb)->s_uspi; - usb1 = ubh_get_usb_first (USPI_UBH); + usb1 = ubh_get_usb_first (uspi); count = newcount - oldcount; cgno = ufs_dtog(fragment); @@ -490,7 +491,7 @@ static unsigned ufs_alloc_fragments (struct inode * inode, unsigned cgno, sb = inode->i_sb; uspi = UFS_SB(sb)->s_uspi; - usb1 = ubh_get_usb_first(USPI_UBH); + usb1 = ubh_get_usb_first(uspi); oldcg = cgno; /* @@ -606,7 +607,7 @@ static unsigned ufs_alloccg_block (struct inode * inode, sb = inode->i_sb; uspi = UFS_SB(sb)->s_uspi; - usb1 = ubh_get_usb_first(USPI_UBH); + usb1 = ubh_get_usb_first(uspi); ucg = ubh_get_ucg(UCPI_UBH); if (goal == 0) { @@ -663,7 +664,7 @@ static unsigned ufs_bitmap_search (struct super_block * sb, UFSD(("ENTER, cg %u, goal %u, count %u\n", ucpi->c_cgx, goal, count)) uspi = UFS_SB(sb)->s_uspi; - usb1 = ubh_get_usb_first (USPI_UBH); + usb1 = ubh_get_usb_first (uspi); ucg = ubh_get_ucg(UCPI_UBH); if (goal) diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c index 0938945b9cb..c7a47ed4f43 100644 --- a/fs/ufs/ialloc.c +++ b/fs/ufs/ialloc.c @@ -72,7 +72,7 @@ void ufs_free_inode (struct inode * inode) sb = inode->i_sb; uspi = UFS_SB(sb)->s_uspi; - usb1 = ubh_get_usb_first(USPI_UBH); + usb1 = ubh_get_usb_first(uspi); ino = inode->i_ino; @@ -167,7 +167,7 @@ struct inode * ufs_new_inode(struct inode * dir, int mode) ufsi = UFS_I(inode); sbi = UFS_SB(sb); uspi = sbi->s_uspi; - usb1 = ubh_get_usb_first(USPI_UBH); + usb1 = ubh_get_usb_first(uspi); lock_super (sb); diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 55f4aa16e3f..e0c04e36a05 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -61,7 +61,7 @@ static int ufs_block_to_path(struct inode *inode, sector_t i_block, sector_t off int n = 0; - UFSD(("ptrs=uspi->s_apb = %d,double_blocks=%d \n",ptrs,double_blocks)); + UFSD(("ptrs=uspi->s_apb = %d,double_blocks=%ld \n",ptrs,double_blocks)); if (i_block < 0) { ufs_warning(inode->i_sb, "ufs_block_to_path", "block < 0"); } else if (i_block < direct_blocks) { @@ -104,7 +104,7 @@ u64 ufs_frag_map(struct inode *inode, sector_t frag) unsigned flags = UFS_SB(sb)->s_flags; u64 temp = 0L; - UFSD((": frag = %lu depth = %d\n",frag,depth)); + UFSD((": frag = %llu depth = %d\n", (unsigned long long)frag, depth)); UFSD((": uspi->s_fpbshift = %d ,uspi->s_apbmask = %x, mask=%llx\n",uspi->s_fpbshift,uspi->s_apbmask,mask)); if (depth == 0) @@ -365,9 +365,10 @@ repeat: sync_dirty_buffer(bh); inode->i_ctime = CURRENT_TIME_SEC; mark_inode_dirty(inode); + UFSD(("result %u\n", tmp + blockoff)); out: brelse (bh); - UFSD(("EXIT, result %u\n", tmp + blockoff)) + UFSD(("EXIT\n")); return result; } @@ -386,7 +387,7 @@ static int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buf if (!create) { phys64 = ufs_frag_map(inode, fragment); - UFSD(("phys64 = %lu \n",phys64)); + UFSD(("phys64 = %llu \n",phys64)); if (phys64) map_bh(bh_result, sb, phys64); return 0; @@ -401,7 +402,7 @@ static int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buf lock_kernel(); - UFSD(("ENTER, ino %lu, fragment %u\n", inode->i_ino, fragment)) + UFSD(("ENTER, ino %lu, fragment %llu\n", inode->i_ino, (unsigned long long)fragment)) if (fragment < 0) goto abort_negative; if (fragment > diff --git a/fs/ufs/super.c b/fs/ufs/super.c index e9a42c711a9..d4aacee593f 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -221,7 +221,7 @@ void ufs_error (struct super_block * sb, const char * function, va_list args; uspi = UFS_SB(sb)->s_uspi; - usb1 = ubh_get_usb_first(USPI_UBH); + usb1 = ubh_get_usb_first(uspi); if (!(sb->s_flags & MS_RDONLY)) { usb1->fs_clean = UFS_FSBAD; @@ -253,7 +253,7 @@ void ufs_panic (struct super_block * sb, const char * function, va_list args; uspi = UFS_SB(sb)->s_uspi; - usb1 = ubh_get_usb_first(USPI_UBH); + usb1 = ubh_get_usb_first(uspi); if (!(sb->s_flags & MS_RDONLY)) { usb1->fs_clean = UFS_FSBAD; @@ -420,21 +420,18 @@ static int ufs_read_cylinder_structures (struct super_block *sb) { if (i + uspi->s_fpb > blks) size = (blks - i) * uspi->s_fsize; - if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) { + if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) ubh = ubh_bread(sb, fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_csaddr) + i, size); - if (!ubh) - goto failed; - ubh_ubhcpymem (space, ubh, size); - sbi->s_csp[ufs_fragstoblks(i)]=(struct ufs_csum *)space; - } - else { + else ubh = ubh_bread(sb, uspi->s_csaddr + i, size); - if (!ubh) - goto failed; - ubh_ubhcpymem(space, ubh, size); - sbi->s_csp[ufs_fragstoblks(i)]=(struct ufs_csum *)space; - } + + if (!ubh) + goto failed; + + ubh_ubhcpymem (space, ubh, size); + sbi->s_csp[ufs_fragstoblks(i)]=(struct ufs_csum *)space; + space += size; ubh_brelse (ubh); ubh = NULL; @@ -539,6 +536,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) struct inode *inode; unsigned block_size, super_block_size; unsigned flags; + unsigned super_block_offset; uspi = NULL; ubh = NULL; @@ -586,10 +584,11 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) if (!uspi) goto failed; + super_block_offset=UFS_SBLOCK; + /* Keep 2Gig file limit. Some UFS variants need to override this but as I don't know which I'll let those in the know loosen the rules */ - switch (sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) { case UFS_MOUNT_UFSTYPE_44BSD: UFSD(("ufstype=44bsd\n")) @@ -601,7 +600,8 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD; break; case UFS_MOUNT_UFSTYPE_UFS2: - UFSD(("ufstype=ufs2\n")) + UFSD(("ufstype=ufs2\n")); + super_block_offset=SBLOCK_UFS2; uspi->s_fsize = block_size = 512; uspi->s_fmask = ~(512 - 1); uspi->s_fshift = 9; @@ -725,19 +725,16 @@ again: /* * read ufs super block from device */ - if ( (flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) { - ubh = ubh_bread_uspi(uspi, sb, uspi->s_sbbase + SBLOCK_UFS2/block_size, super_block_size); - } - else { - ubh = ubh_bread_uspi(uspi, sb, uspi->s_sbbase + UFS_SBLOCK/block_size, super_block_size); - } + + ubh = ubh_bread_uspi(uspi, sb, uspi->s_sbbase + super_block_offset/block_size, super_block_size); + if (!ubh) goto failed; - usb1 = ubh_get_usb_first(USPI_UBH); - usb2 = ubh_get_usb_second(USPI_UBH); - usb3 = ubh_get_usb_third(USPI_UBH); + usb1 = ubh_get_usb_first(uspi); + usb2 = ubh_get_usb_second(uspi); + usb3 = ubh_get_usb_third(uspi); usb = (struct ufs_super_block *) ((struct ufs_buffer_head *)uspi)->bh[0]->b_data ; @@ -1006,8 +1003,8 @@ static void ufs_write_super (struct super_block *sb) { UFSD(("ENTER\n")) flags = UFS_SB(sb)->s_flags; uspi = UFS_SB(sb)->s_uspi; - usb1 = ubh_get_usb_first(USPI_UBH); - usb3 = ubh_get_usb_third(USPI_UBH); + usb1 = ubh_get_usb_first(uspi); + usb3 = ubh_get_usb_third(uspi); if (!(sb->s_flags & MS_RDONLY)) { usb1->fs_time = cpu_to_fs32(sb, get_seconds()); @@ -1049,8 +1046,8 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) uspi = UFS_SB(sb)->s_uspi; flags = UFS_SB(sb)->s_flags; - usb1 = ubh_get_usb_first(USPI_UBH); - usb3 = ubh_get_usb_third(USPI_UBH); + usb1 = ubh_get_usb_first(uspi); + usb3 = ubh_get_usb_third(uspi); /* * Allow the "check" option to be passed as a remount option. @@ -1124,7 +1121,7 @@ static int ufs_statfs (struct super_block *sb, struct kstatfs *buf) lock_kernel(); uspi = UFS_SB(sb)->s_uspi; - usb1 = ubh_get_usb_first (USPI_UBH); + usb1 = ubh_get_usb_first (uspi); usb = (struct ufs_super_block *) ((struct ufs_buffer_head *)uspi)->bh[0]->b_data ; diff --git a/fs/ufs/util.h b/fs/ufs/util.h index e45ad537987..48d6d9bcc15 100644 --- a/fs/ufs/util.h +++ b/fs/ufs/util.h @@ -249,18 +249,28 @@ extern void _ubh_memcpyubh_(struct ufs_sb_private_info *, struct ufs_buffer_head /* - * macros to get important structures from ufs_buffer_head + * macros and inline function to get important structures from ufs_sb_private_info */ -#define ubh_get_usb_first(ubh) \ - ((struct ufs_super_block_first *)((ubh)->bh[0]->b_data)) -#define ubh_get_usb_second(ubh) \ - ((struct ufs_super_block_second *)((ubh)->\ - bh[UFS_SECTOR_SIZE >> uspi->s_fshift]->b_data + (UFS_SECTOR_SIZE & ~uspi->s_fmask))) +static inline void *get_usb_offset(struct ufs_sb_private_info *uspi, + unsigned int offset) +{ + unsigned int index; + + index = offset >> uspi->s_fshift; + offset &= ~uspi->s_fmask; + return uspi->s_ubh.bh[index]->b_data + offset; +} + +#define ubh_get_usb_first(uspi) \ + ((struct ufs_super_block_first *)get_usb_offset((uspi), 0)) + +#define ubh_get_usb_second(uspi) \ + ((struct ufs_super_block_second *)get_usb_offset((uspi), UFS_SECTOR_SIZE)) + +#define ubh_get_usb_third(uspi) \ + ((struct ufs_super_block_third *)get_usb_offset((uspi), 2*UFS_SECTOR_SIZE)) -#define ubh_get_usb_third(ubh) \ - ((struct ufs_super_block_third *)((ubh)-> \ - bh[UFS_SECTOR_SIZE*2 >> uspi->s_fshift]->b_data + (UFS_SECTOR_SIZE*2 & ~uspi->s_fmask))) #define ubh_get_ucg(ubh) \ ((struct ufs_cylinder_group *)((ubh)->bh[0]->b_data)) -- GitLab From e1b114ee90040af5108973abd1a82babc4905868 Mon Sep 17 00:00:00 2001 From: Xose Vazquez Perez Date: Sat, 14 Jan 2006 12:57:41 +0100 Subject: [PATCH 237/465] [PATCH] docs: update some updated code docs Based on comments from Randy Dunlap on my previous commit 5b0ed2c64d8fdafb5fcfb3baabdd288628b1ff9b Signed-off-by: Linus Torvalds --- Documentation/SubmittingDrivers | 2 +- Documentation/SubmittingPatches | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/SubmittingDrivers b/Documentation/SubmittingDrivers index dd311cff1cc..6bd30fdd078 100644 --- a/Documentation/SubmittingDrivers +++ b/Documentation/SubmittingDrivers @@ -143,7 +143,7 @@ KernelNewbies: http://kernelnewbies.org/ Linux USB project: - http://linux-usb.sourceforge.net/ + http://www.linux-usb.org/ How to NOT write kernel driver by arjanv@redhat.com http://people.redhat.com/arjanv/olspaper.pdf diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches index 6198e5ebcf6..c2c85bcb3d4 100644 --- a/Documentation/SubmittingPatches +++ b/Documentation/SubmittingPatches @@ -478,10 +478,11 @@ Andrew Morton, "The perfect patch" (tpp). Jeff Garzik, "Linux kernel patch submission format." -Greg Kroah, "How to piss off a kernel subsystem maintainer". +Greg Kroah-Hartman "How to piss off a kernel subsystem maintainer". + NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!. -- GitLab From 3824ba7df91745da6ebac703c87c3b801c34fdd0 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 14 Jan 2006 03:08:16 +0100 Subject: [PATCH 238/465] [PATCH] remove unused tmp_buf_sem's tmp_buf_sem sems to be a common name for something completely unused... Signed-off-by: Adrian Bunk Acked-by: Greg Kroah-Hartman ("usb portion") Signed-off-by: Linus Torvalds --- arch/ia64/hp/sim/simserial.c | 1 - arch/ppc/4xx_io/serial_sicc.c | 1 - drivers/char/amiserial.c | 1 - drivers/char/esp.c | 1 - drivers/char/generic_serial.c | 1 - drivers/char/riscom8.c | 1 - drivers/char/serial167.c | 1 - drivers/char/specialix.c | 3 --- drivers/char/synclink.c | 1 - drivers/sbus/char/aurora.c | 1 - drivers/serial/68328serial.c | 1 - drivers/usb/serial/pl2303.c | 2 -- 12 files changed, 15 deletions(-) diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 27f23fa5ca1..626cdc83668 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -108,7 +108,6 @@ static struct async_struct *IRQ_ports[NR_IRQS]; static struct console *console; static unsigned char *tmp_buf; -static DECLARE_MUTEX(tmp_buf_sem); extern struct console *console_drivers; /* from kernel/printk.c */ diff --git a/arch/ppc/4xx_io/serial_sicc.c b/arch/ppc/4xx_io/serial_sicc.c index ebc4db8fcc6..8ace2a1f3b4 100644 --- a/arch/ppc/4xx_io/serial_sicc.c +++ b/arch/ppc/4xx_io/serial_sicc.c @@ -215,7 +215,6 @@ static struct tty_driver *siccnormal_driver; * memory if large numbers of serial ports are open. */ static u_char *tmp_buf; -static DECLARE_MUTEX(tmp_buf_sem); #define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 667a21c72ed..7ac365b5d9e 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c @@ -129,7 +129,6 @@ static struct serial_state rs_table[1]; * memory if large numbers of serial ports are open. */ static unsigned char *tmp_buf; -static DECLARE_MUTEX(tmp_buf_sem); #include diff --git a/drivers/char/esp.c b/drivers/char/esp.c index e469f641c72..dd5dc8fa490 100644 --- a/drivers/char/esp.c +++ b/drivers/char/esp.c @@ -160,7 +160,6 @@ static void rs_wait_until_sent(struct tty_struct *, int); * memory if large numbers of serial ports are open. */ static unsigned char *tmp_buf; -static DECLARE_MUTEX(tmp_buf_sem); static inline int serial_paranoia_check(struct esp_struct *info, char *name, const char *routine) diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c index 204a7302a4a..e38a5f0e07b 100644 --- a/drivers/char/generic_serial.c +++ b/drivers/char/generic_serial.c @@ -34,7 +34,6 @@ #define DEBUG static char * tmp_buf; -static DECLARE_MUTEX(tmp_buf_sem); static int gs_debug; diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 050e70ee592..119e629656b 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c @@ -82,7 +82,6 @@ static struct riscom_board * IRQ_to_board[16]; static struct tty_driver *riscom_driver; static unsigned char * tmp_buf; -static DECLARE_MUTEX(tmp_buf_sem); static unsigned long baud_table[] = { 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index f36342ae8e7..037c940ac71 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c @@ -129,7 +129,6 @@ struct cyclades_port cy_port[] = { * memory if large numbers of serial ports are open. */ static unsigned char *tmp_buf = 0; -DECLARE_MUTEX(tmp_buf_sem); /* * This is used to look up the divisor speeds and the timeouts diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 0a574bdbce3..5343e9fc6ab 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c @@ -184,7 +184,6 @@ static int sx_poll = HZ; static struct tty_driver *specialix_driver; static unsigned char * tmp_buf; -static DECLARE_MUTEX(tmp_buf_sem); static unsigned long baud_table[] = { 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, @@ -2556,8 +2555,6 @@ static int __init specialix_init_module(void) func_enter(); - init_MUTEX(&tmp_buf_sem); /* Init de the semaphore - pvdl */ - if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) { for(i = 0; i < SX_NBOARD; i++) { sx_board[i].base = iobase[i]; diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 9f1b466c4f8..ede688a4e14 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -951,7 +951,6 @@ static void* mgsl_get_text_ptr(void) * memory if large numbers of serial ports are open. */ static unsigned char *tmp_buf; -static DECLARE_MUTEX(tmp_buf_sem); static inline int mgsl_paranoia_check(struct mgsl_struct *info, char *name, const char *routine) diff --git a/drivers/sbus/char/aurora.c b/drivers/sbus/char/aurora.c index 92e6c5639dd..015db40ad8a 100644 --- a/drivers/sbus/char/aurora.c +++ b/drivers/sbus/char/aurora.c @@ -92,7 +92,6 @@ static struct Aurora_port aurora_port[AURORA_TNPORTS] = { /* no longer used. static struct Aurora_board * IRQ_to_board[16] = { NULL, } ;*/ static unsigned char * tmp_buf = NULL; -static DECLARE_MUTEX(tmp_buf_sem); DECLARE_TASK_QUEUE(tq_aurora); diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index 4dd5c3f9816..8cbf0fc5a22 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c @@ -143,7 +143,6 @@ static int m68328_console_cbaud = DEFAULT_CBAUD; * memory if large numbers of serial ports are open. */ static unsigned char tmp_buf[SERIAL_XMIT_SIZE]; /* This is cheating */ -DECLARE_MUTEX(tmp_buf_sem); static inline int serial_paranoia_check(struct m68k_serial *info, char *name, const char *routine) diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 9ffff193823..0eb883f44ad 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -43,8 +43,6 @@ static int debug; #define PL2303_BUF_SIZE 1024 #define PL2303_TMP_BUF_SIZE 1024 -static DECLARE_MUTEX(pl2303_tmp_buf_sem); - struct pl2303_buf { unsigned int buf_size; char *buf_buf; -- GitLab From 3f471126ee53feb5e9b210ea2f525ed3bb9b7a7f Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sat, 14 Jan 2006 19:30:04 +0000 Subject: [PATCH 239/465] [ARM] 3262/4: allow ptraced syscalls to be overriden Patch from Nicolas Pitre This is needed by strace to properly handle the tracing of some system calls. It could be useful for other applications as well. Based on an earlier patch from Daniel Jacobowitz. Signed-off-by: Nicolas Pitre Signed-off-by: Daniel Jacobowitz Signed-off-by: Russell King --- arch/arm/kernel/entry-common.S | 3 +++ arch/arm/kernel/ptrace.c | 15 ++++++++++++--- include/asm-arm/ptrace.h | 3 +++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 8826d9803ae..2b92ce85f97 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -214,11 +214,13 @@ ENTRY(vector_swi) * context switches, and waiting for our parent to respond. */ __sys_trace: + mov r2, scno add r1, sp, #S_OFF mov r0, #0 @ trace entry [IP = 0] bl syscall_trace adr lr, __sys_trace_return @ return address + mov scno, r0 @ syscall number (possibly new) add r1, sp, #S_R0 + S_OFF @ pointer to regs cmp scno, #NR_syscalls @ check upper syscall limit ldmccia r1, {r0 - r3} @ have to reload r0 - r3 @@ -227,6 +229,7 @@ __sys_trace: __sys_trace_return: str r0, [sp, #S_R0 + S_OFF]! @ save returned r0 + mov r2, scno mov r1, sp mov r0, #1 @ trace exit [IP = 1] bl syscall_trace diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index e591f72bcde..7b6256bb590 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -766,6 +766,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) (unsigned long __user *) data); break; + case PTRACE_SET_SYSCALL: + ret = 0; + child->ptrace_message = data; + break; + default: ret = ptrace_request(child, request, addr, data); break; @@ -774,14 +779,14 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) return ret; } -asmlinkage void syscall_trace(int why, struct pt_regs *regs) +asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno) { unsigned long ip; if (!test_thread_flag(TIF_SYSCALL_TRACE)) - return; + return scno; if (!(current->ptrace & PT_PTRACED)) - return; + return scno; /* * Save IP. IP is used to denote syscall entry/exit: @@ -790,6 +795,8 @@ asmlinkage void syscall_trace(int why, struct pt_regs *regs) ip = regs->ARM_ip; regs->ARM_ip = why; + current->ptrace_message = scno; + /* the 0x80 provides a way for the tracing parent to distinguish between a syscall stop and SIGTRAP delivery */ ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) @@ -804,4 +811,6 @@ asmlinkage void syscall_trace(int why, struct pt_regs *regs) current->exit_code = 0; } regs->ARM_ip = ip; + + return current->ptrace_message; } diff --git a/include/asm-arm/ptrace.h b/include/asm-arm/ptrace.h index f40948d5444..77adb7fa169 100644 --- a/include/asm-arm/ptrace.h +++ b/include/asm-arm/ptrace.h @@ -23,6 +23,9 @@ #define PTRACE_OLDSETOPTIONS 21 #define PTRACE_GET_THREAD_AREA 22 + +#define PTRACE_SET_SYSCALL 23 + /* * PSR bits */ -- GitLab From 7c7dce9209161eb260cdf9e9172f72c3a02379e6 Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Sat, 14 Jan 2006 15:29:55 -0500 Subject: [PATCH 240/465] [PATCH] Fix double decrement of mqueue_mnt->mnt_count in sys_mq_open Fixed the refcounting on failure exits in sys_mq_open() and cleaned the logics up. Rules are actually pretty simple - dentry_open() expects vfsmount and dentry to be pinned down and it either transfers them into created struct file or drops them. Old code had been very confused in that area - if dentry_open() had failed either in do_open() or do_create(), we ended up dentry and mqueue_mnt dropped twice, once by dentry_open() cleanup and then by sys_mq_open(). Fix consists of making the rules for do_create() and do_open() same as for dentry_open() and updating the sys_mq_open() accordingly; that actually leads to more straightforward code and less work on normal path. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- ipc/mqueue.c | 59 +++++++++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 4e776f9c80e..59302fc3643 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -599,15 +599,16 @@ static int mq_attr_ok(struct mq_attr *attr) static struct file *do_create(struct dentry *dir, struct dentry *dentry, int oflag, mode_t mode, struct mq_attr __user *u_attr) { - struct file *filp; struct mq_attr attr; int ret; - if (u_attr != NULL) { + if (u_attr) { + ret = -EFAULT; if (copy_from_user(&attr, u_attr, sizeof(attr))) - return ERR_PTR(-EFAULT); + goto out; + ret = -EINVAL; if (!mq_attr_ok(&attr)) - return ERR_PTR(-EINVAL); + goto out; /* store for use during create */ dentry->d_fsdata = &attr; } @@ -616,13 +617,14 @@ static struct file *do_create(struct dentry *dir, struct dentry *dentry, ret = vfs_create(dir->d_inode, dentry, mode, NULL); dentry->d_fsdata = NULL; if (ret) - return ERR_PTR(ret); + goto out; - filp = dentry_open(dentry, mqueue_mnt, oflag); - if (!IS_ERR(filp)) - dget(dentry); + return dentry_open(dentry, mqueue_mnt, oflag); - return filp; +out: + dput(dentry); + mntput(mqueue_mnt); + return ERR_PTR(ret); } /* Opens existing queue */ @@ -630,20 +632,20 @@ static struct file *do_open(struct dentry *dentry, int oflag) { static int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE, MAY_READ | MAY_WRITE }; - struct file *filp; - if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) + if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) { + dput(dentry); + mntput(mqueue_mnt); return ERR_PTR(-EINVAL); + } - if (permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE], NULL)) + if (permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE], NULL)) { + dput(dentry); + mntput(mqueue_mnt); return ERR_PTR(-EACCES); + } - filp = dentry_open(dentry, mqueue_mnt, oflag); - - if (!IS_ERR(filp)) - dget(dentry); - - return filp; + return dentry_open(dentry, mqueue_mnt, oflag); } asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, @@ -671,17 +673,20 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, if (oflag & O_CREAT) { if (dentry->d_inode) { /* entry already exists */ - filp = (oflag & O_EXCL) ? ERR_PTR(-EEXIST) : - do_open(dentry, oflag); + error = -EEXIST; + if (oflag & O_EXCL) + goto out; + filp = do_open(dentry, oflag); } else { filp = do_create(mqueue_mnt->mnt_root, dentry, oflag, mode, u_attr); } - } else - filp = (dentry->d_inode) ? do_open(dentry, oflag) : - ERR_PTR(-ENOENT); - - dput(dentry); + } else { + error = -ENOENT; + if (!dentry->d_inode) + goto out; + filp = do_open(dentry, oflag); + } if (IS_ERR(filp)) { error = PTR_ERR(filp); @@ -692,8 +697,10 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, fd_install(fd, filp); goto out_upsem; -out_putfd: +out: + dput(dentry); mntput(mqueue_mnt); +out_putfd: put_unused_fd(fd); out_err: fd = error; -- GitLab From 9c782e3b2083c33b5a14c9955cf15f32ea88116b Mon Sep 17 00:00:00 2001 From: Alex Shepard Date: Sun, 15 Jan 2006 01:57:00 +0100 Subject: [PATCH 241/465] Spelling fix in IPW2100 and IPW2200 Kconfig entries s/remvoed/removed/ Signed-off-by: Alex Shepard Signed-off-by: Adrian Bunk --- drivers/net/wireless/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index c1a6e69f790..e90687495cc 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -160,7 +160,7 @@ config IPW2100 . If you want to compile the driver as a module ( = code which can be - inserted in and remvoed from the running kernel whenever you want), + inserted in and removed from the running kernel whenever you want), say M here and read . The module will be called ipw2100.ko. @@ -213,7 +213,7 @@ config IPW2200 . If you want to compile the driver as a module ( = code which can be - inserted in and remvoed from the running kernel whenever you want), + inserted in and removed from the running kernel whenever you want), say M here and read . The module will be called ipw2200.ko. -- GitLab From b480146fd19b99b16263467216622effcd93fd96 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 15 Jan 2006 01:57:47 +0100 Subject: [PATCH 242/465] ftape: remove some outdated information from Kconfig files This patch removes some outdated information about the ftape driver like pointers to no longer existing webpages from Kconfig files. Signed-off-by: Adrian Bunk --- drivers/char/Kconfig | 10 ---------- drivers/char/ftape/Kconfig | 12 +----------- 2 files changed, 1 insertion(+), 21 deletions(-) diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index d6fcd0a36f9..4135d8c5bca 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -881,16 +881,6 @@ config FTAPE module. To compile this driver as a module, choose M here: the module will be called ftape. - Note that the Ftape-HOWTO is out of date (sorry) and documents the - older version 2.08 of this software but still contains useful - information. There is a web page with more recent documentation at - . This page - always contains the latest release of the ftape driver and useful - information (backup software, ftape related patches and - documentation, FAQ). Note that the file system interface has - changed quite a bit compared to previous versions of ftape. Please - read . - source "drivers/char/ftape/Kconfig" endmenu diff --git a/drivers/char/ftape/Kconfig b/drivers/char/ftape/Kconfig index 7d3ecb56a1b..0d65189a7ae 100644 --- a/drivers/char/ftape/Kconfig +++ b/drivers/char/ftape/Kconfig @@ -25,17 +25,7 @@ config ZFTAPE support", above) then `zft-compressor' will be loaded automatically by zftape when needed. - Despite its name, zftape does NOT use compression by default. The - file contains a short description of - the most important changes in the file system interface compared to - previous versions of ftape. The ftape home page - contains - further information. - - IMPORTANT NOTE: zftape can read archives created by previous - versions of ftape and provide file mark support (i.e. fast skipping - between tape archives) but previous version of ftape will lack file - mark support when reading archives produced by zftape. + Despite its name, zftape does NOT use compression by default. config ZFT_DFLT_BLK_SZ int "Default block size" -- GitLab From a8e82ef97a1d1227575698935ec86ae4d02c372c Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 15 Jan 2006 01:58:57 +0100 Subject: [PATCH 243/465] drivers/net/{,wireless/}Kconfig: remove dead URL shadow.cabi.net does no longer exist. Signed-off-by: Adrian Bunk --- drivers/net/Kconfig | 4 ---- drivers/net/wireless/Kconfig | 4 ---- 2 files changed, 8 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 5c15f3e9ea0..de46e75efb4 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2676,10 +2676,6 @@ config SHAPER Class-Based Queueing (CBQ) scheduling support which you get if you say Y to "QoS and/or fair queueing" above. - To set up and configure shaper devices, you need the shapecfg - program, available from in the - shaper package. - To compile this driver as a module, choose M here: the module will be called shaper. If unsure, say N. diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index e90687495cc..233a4f60808 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -24,10 +24,6 @@ config NET_RADIO the tools from . - Some user-level drivers for scarab devices which don't require - special kernel support are available from - . - # Note : the cards are obsolete (can't buy them anymore), but the drivers # are not, as people are still using them... comment "Obsolete Wireless cards support (pre-802.11)" -- GitLab From 575c96871832e91983248aebb02fc072e5fd17c9 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 15 Jan 2006 02:00:17 +0100 Subject: [PATCH 244/465] spelling: s/appropiate/appropriate/ Signed-off-by: Adrian Bunk --- Documentation/cachetlb.txt | 2 +- Documentation/ioctl/hdio.txt | 2 +- Documentation/laptop-mode.txt | 2 +- Documentation/networking/sk98lin.txt | 2 +- Documentation/x86_64/boot-options.txt | 2 +- drivers/s390/scsi/zfcp_erp.c | 2 +- drivers/scsi/gdth.c | 2 +- sound/oss/opl3sa2.c | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Documentation/cachetlb.txt b/Documentation/cachetlb.txt index 7eb715e07ed..4ae418889b8 100644 --- a/Documentation/cachetlb.txt +++ b/Documentation/cachetlb.txt @@ -136,7 +136,7 @@ changes occur: 8) void lazy_mmu_prot_update(pte_t pte) This interface is called whenever the protection on any user PTEs change. This interface provides a notification - to architecture specific code to take appropiate action. + to architecture specific code to take appropriate action. Next, we have the cache flushing interfaces. In general, when Linux diff --git a/Documentation/ioctl/hdio.txt b/Documentation/ioctl/hdio.txt index 9a7aea0636a..11c9be49f37 100644 --- a/Documentation/ioctl/hdio.txt +++ b/Documentation/ioctl/hdio.txt @@ -946,7 +946,7 @@ HDIO_SCAN_HWIF register and (re)scan interface This ioctl initializes the addresses and irq for a disk controller, probes for drives, and creates /proc/ide - interfaces as appropiate. + interfaces as appropriate. diff --git a/Documentation/laptop-mode.txt b/Documentation/laptop-mode.txt index f42e4c08935..b18e2167590 100644 --- a/Documentation/laptop-mode.txt +++ b/Documentation/laptop-mode.txt @@ -357,7 +357,7 @@ MAX_AGE=${MAX_AGE:-'600'} # Read-ahead, in kilobytes READAHEAD=${READAHEAD:-'4096'} -# Shall we remount journaled fs. with appropiate commit interval? (1=yes) +# Shall we remount journaled fs. with appropriate commit interval? (1=yes) DO_REMOUNTS=${DO_REMOUNTS:-'1'} # And shall we add the "noatime" option to that as well? (1=yes) diff --git a/Documentation/networking/sk98lin.txt b/Documentation/networking/sk98lin.txt index f9d979ee952..7837c53fd5f 100644 --- a/Documentation/networking/sk98lin.txt +++ b/Documentation/networking/sk98lin.txt @@ -91,7 +91,7 @@ To use the driver as a module, proceed as follows: with (M) 5. Execute the command "make modules". 6. Execute the command "make modules_install". - The appropiate modules will be installed. + The appropriate modules will be installed. 7. Reboot your system. diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt index 72ab9b99b22..9c5fc15d03d 100644 --- a/Documentation/x86_64/boot-options.txt +++ b/Documentation/x86_64/boot-options.txt @@ -198,6 +198,6 @@ Debugging Misc - noreplacement Don't replace instructions with more appropiate ones + noreplacement Don't replace instructions with more appropriate ones for the CPU. This may be useful on asymmetric MP systems where some CPU have less capabilities than the others. diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 7bdb00b5aeb..c065cb836c9 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -3403,7 +3403,7 @@ zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action) /** * zfcp_erp_action_cleanup * - * Register unit with scsi stack if appropiate and fix reference counts. + * Register unit with scsi stack if appropriate and fix reference counts. * Note: Temporary units are not registered with scsi stack. */ static void diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index a6deb016584..bd3ffdf6c80 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -328,7 +328,7 @@ * hdr_channel:x x - number of virtual bus for host drives * shared_access:Y disable driver reserve/release protocol to * access a shared resource from several nodes, - * appropiate controller firmware required + * appropriate controller firmware required * shared_access:N enable driver reserve/release protocol * probe_eisa_isa:Y scan for EISA/ISA controllers * probe_eisa_isa:N do not scan for EISA/ISA controllers diff --git a/sound/oss/opl3sa2.c b/sound/oss/opl3sa2.c index 5cecdbcbea9..0e161c6a047 100644 --- a/sound/oss/opl3sa2.c +++ b/sound/oss/opl3sa2.c @@ -530,7 +530,7 @@ static void __init attach_opl3sa2_mss(struct address_info* hw_config, struct res if (hw_config->slots[0] != -1) { /* Did the MSS driver install? */ if(num_mixers == (initial_mixers + 1)) { - /* The MSS mixer is installed, reroute mixers appropiately */ + /* The MSS mixer is installed, reroute mixers appropriately */ AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_CD); AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_SYNTH); AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_LINE); -- GitLab From 750c902ef4a1956cecbc8fb590ce2dad5b02eab9 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 15 Jan 2006 02:01:39 +0100 Subject: [PATCH 245/465] SOFTWARE_SUSPEND: fix a typo in the dependencies This patch fixes a typo in the dependencies of SOFTWARE_SUSPEND. This patch is based on a report by Jean-Luc Leger . Signed-off-by: Adrian Bunk Acked-by: Pavel Machek --- kernel/power/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 5ec248cb7f4..9fd8d4f0359 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig @@ -38,7 +38,7 @@ config PM_DEBUG config SOFTWARE_SUSPEND bool "Software Suspend" - depends on PM && SWAP && (X86 && (!SMP || SUSPEND_SMP)) || ((FVR || PPC32) && !SMP) + depends on PM && SWAP && (X86 && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP) ---help--- Enable the possibility of suspending the machine. It doesn't need APM. -- GitLab From fad6a94ee6b33ca5e6184e8b08634a6a2319d0cb Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 15 Jan 2006 02:09:54 +0100 Subject: [PATCH 246/465] Documentation/hpet.txt typo Fix a typo. Requested by Petr Vandrovec. Signed-off-by: Randy Dunlap Signed-off-by: Adrian Bunk --- Documentation/hpet.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/hpet.txt b/Documentation/hpet.txt index e52457581f4..b7a3dc38dd5 100644 --- a/Documentation/hpet.txt +++ b/Documentation/hpet.txt @@ -2,7 +2,7 @@ The High Precision Event Timer (HPET) hardware is the future replacement for the 8254 and Real Time Clock (RTC) periodic timer functionality. -Each HPET can have up two 32 timers. It is possible to configure the +Each HPET can have up to 32 timers. It is possible to configure the first two timers as legacy replacements for 8254 and RTC periodic timers. A specification done by Intel and Microsoft can be found at . -- GitLab From 3235798804ee75f09d45aee5003197930de57689 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sun, 15 Jan 2006 02:12:54 +0100 Subject: [PATCH 247/465] Fix "stuct", "strut", "struc" typos Signed-off-by: Alexey Dobriyan Signed-off-by: Adrian Bunk --- Documentation/DocBook/videobook.tmpl | 4 ++-- Documentation/input/ff.txt | 2 +- Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl | 2 +- drivers/net/wan/lmc/lmc_main.c | 2 +- drivers/scsi/FlashPoint.c | 2 +- include/asm-v850/ptrace.h | 2 +- include/linux/pfkeyv2.h | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Documentation/DocBook/videobook.tmpl b/Documentation/DocBook/videobook.tmpl index 3ec6c875588..fdff984a516 100644 --- a/Documentation/DocBook/videobook.tmpl +++ b/Documentation/DocBook/videobook.tmpl @@ -229,7 +229,7 @@ int __init myradio_init(struct video_init *v) static int users = 0; -static int radio_open(stuct video_device *dev, int flags) +static int radio_open(struct video_device *dev, int flags) { if(users) return -EBUSY; @@ -949,7 +949,7 @@ int __init mycamera_init(struct video_init *v) static int users = 0; -static int camera_open(stuct video_device *dev, int flags) +static int camera_open(struct video_device *dev, int flags) { if(users) return -EBUSY; diff --git a/Documentation/input/ff.txt b/Documentation/input/ff.txt index efa7dd6751f..c7e10eaff20 100644 --- a/Documentation/input/ff.txt +++ b/Documentation/input/ff.txt @@ -120,7 +120,7 @@ to the unique id assigned by the driver. This data is required for performing some operations (removing an effect, controlling the playback). This if field must be set to -1 by the user in order to tell the driver to allocate a new effect. -See for a description of the ff_effect stuct. You should also +See for a description of the ff_effect struct. You should also find help in a few sketches, contained in files shape.fig and interactive.fig. You need xfig to visualize these files. diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index 4963d83d151..e651ed8d1e6 100644 --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl @@ -5577,7 +5577,7 @@ struct _snd_pcm_runtime { lmc_lock, flags); if(sc->check != 0xBEAFCAFE){ - printk("LMC: Corrupt net_device stuct, breaking out\n"); + printk("LMC: Corrupt net_device struct, breaking out\n"); spin_unlock_irqrestore(&sc->lmc_lock, flags); return; } diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c index 5beed4f6d98..8d64f0bed62 100644 --- a/drivers/scsi/FlashPoint.c +++ b/drivers/scsi/FlashPoint.c @@ -149,7 +149,7 @@ typedef SCCBMGR_INFO * PSCCBMGR_INFO; #define PCI_BUS_CARD 0x03 #define VESA_BUS_CARD 0x04 -/* SCCB struc used for both SCCB and UCB manager compiles! +/* SCCB struct used for both SCCB and UCB manager compiles! * The UCB Manager treats the SCCB as it's 'native hardware structure' */ diff --git a/include/asm-v850/ptrace.h b/include/asm-v850/ptrace.h index 7bf72bb5078..4f35cf2cd64 100644 --- a/include/asm-v850/ptrace.h +++ b/include/asm-v850/ptrace.h @@ -92,7 +92,7 @@ struct pt_regs /* The number of bytes used to store each register. */ #define _PT_REG_SIZE 4 -/* Offset of a general purpose register in a stuct pt_regs. */ +/* Offset of a general purpose register in a struct pt_regs. */ #define PT_GPR(num) ((num) * _PT_REG_SIZE) /* Offsets of various special registers & fields in a struct pt_regs. */ diff --git a/include/linux/pfkeyv2.h b/include/linux/pfkeyv2.h index 6351c4055ac..bac0fb389cf 100644 --- a/include/linux/pfkeyv2.h +++ b/include/linux/pfkeyv2.h @@ -104,7 +104,7 @@ struct sadb_prop { /* followed by: struct sadb_comb sadb_combs[(sadb_prop_len + sizeof(uint64_t) - sizeof(struct sadb_prop)) / - sizeof(strut sadb_comb)]; */ + sizeof(struct sadb_comb)]; */ struct sadb_comb { uint8_t sadb_comb_auth; -- GitLab From f1c3ddff84981bbe3bedd60a6330057e8f1f8ef5 Mon Sep 17 00:00:00 2001 From: Horms Date: Sun, 15 Jan 2006 02:18:28 +0100 Subject: [PATCH 248/465] MAINTAINERS: better list for "POSIX CLOCKS and TIMERS" POSIX CLOCKS and TIMERS disscussion is more appropriate on linux-kernel than linux-net. As suggested by the maintainer, George Anzinger. Signed-off-by: Horms Acked-by: George Anzinger Signed-off-by: Adrian Bunk --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 71693c5c313..10941b10006 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2053,7 +2053,7 @@ S: Maintained POSIX CLOCKS and TIMERS P: George Anzinger M: george@mvista.com -L: netdev@vger.kernel.org +L: linux-kernel@vger.kernel.org S: Supported POWERPC 4xx EMAC DRIVER -- GitLab From 46a9f65f8bb39778646b83220d9619aff1490bcd Mon Sep 17 00:00:00 2001 From: Domen Puncer Date: Sun, 15 Jan 2006 02:20:28 +0100 Subject: [PATCH 249/465] remove unused LOCAL_END_REQUEST Remove the last occurence of LOCAL_END_REQUEST. Signed-off-by: Domen Puncer Signed-off-by: Adrian Bunk --- drivers/block/floppy.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 374621a512e..d23b54332d7 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -242,7 +242,6 @@ static int allowed_drive_mask = 0x33; static int irqdma_allocated; -#define LOCAL_END_REQUEST #define DEVICE_NAME "floppy" #include -- GitLab From 014c2544e6fd09d702c908d95fe32c082376e15c Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 15 Jan 2006 02:37:08 +0100 Subject: [PATCH 250/465] return statement cleanup - kill pointless parentheses This patch removes pointless parentheses from return statements. Signed-off-by: Jesper Juhl Signed-off-by: Adrian Bunk --- arch/um/include/sysdep-i386/checksum.h | 4 +- drivers/char/stallion.c | 128 ++++++++++++------------- fs/efs/super.c | 5 +- fs/xfs/quota/xfs_qm.c | 114 +++++++++++----------- fs/xfs/xfs_dir_leaf.c | 96 +++++++++---------- fs/xfs/xfs_fsops.c | 4 +- fs/xfs/xfs_log.c | 52 +++++----- fs/xfs/xfs_mount.c | 66 ++++++------- fs/xfs/xfs_trans_item.c | 22 ++--- fs/xfs/xfs_vnodeops.c | 59 ++++++------ 10 files changed, 275 insertions(+), 275 deletions(-) diff --git a/arch/um/include/sysdep-i386/checksum.h b/arch/um/include/sysdep-i386/checksum.h index 764ba4db478..7d3d202d7ff 100644 --- a/arch/um/include/sysdep-i386/checksum.h +++ b/arch/um/include/sysdep-i386/checksum.h @@ -36,7 +36,7 @@ unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char * int len, int sum) { memcpy(dst, src, len); - return(csum_partial(dst, len, sum)); + return csum_partial(dst, len, sum); } /* @@ -104,7 +104,7 @@ static inline unsigned short ip_fast_csum(unsigned char * iph, : "=r" (sum), "=r" (iph), "=r" (ihl) : "1" (iph), "2" (ihl) : "memory"); - return(sum); + return sum; } /* diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 0e20780d4a2..bdaab699210 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c @@ -738,7 +738,7 @@ static int __init stallion_module_init(void) stl_init(); restore_flags(flags); - return(0); + return 0; } /*****************************************************************************/ @@ -889,7 +889,7 @@ static unsigned long stl_atol(char *str) } val = (val * base) + c; } - return(val); + return val; } /*****************************************************************************/ @@ -908,7 +908,7 @@ static int stl_parsebrd(stlconf_t *confp, char **argp) #endif if ((argp[0] == (char *) NULL) || (*argp[0] == 0)) - return(0); + return 0; for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++) *sp = TOLOWER(*sp); @@ -935,7 +935,7 @@ static int stl_parsebrd(stlconf_t *confp, char **argp) } if ((argp[i] != (char *) NULL) && (*argp[i] != 0)) confp->irq = stl_atol(argp[i]); - return(1); + return 1; } /*****************************************************************************/ @@ -946,7 +946,7 @@ static int stl_parsebrd(stlconf_t *confp, char **argp) static void *stl_memalloc(int len) { - return((void *) kmalloc(len, GFP_KERNEL)); + return (void *) kmalloc(len, GFP_KERNEL); } /*****************************************************************************/ @@ -963,12 +963,12 @@ static stlbrd_t *stl_allocbrd(void) if (brdp == (stlbrd_t *) NULL) { printk("STALLION: failed to allocate memory (size=%d)\n", sizeof(stlbrd_t)); - return((stlbrd_t *) NULL); + return (stlbrd_t *) NULL; } memset(brdp, 0, sizeof(stlbrd_t)); brdp->magic = STL_BOARDMAGIC; - return(brdp); + return brdp; } /*****************************************************************************/ @@ -988,10 +988,10 @@ static int stl_open(struct tty_struct *tty, struct file *filp) minordev = tty->index; brdnr = MINOR2BRD(minordev); if (brdnr >= stl_nrbrds) - return(-ENODEV); + return -ENODEV; brdp = stl_brds[brdnr]; if (brdp == (stlbrd_t *) NULL) - return(-ENODEV); + return -ENODEV; minordev = MINOR2PORT(minordev); for (portnr = -1, panelnr = 0; (panelnr < STL_MAXPANELS); panelnr++) { if (brdp->panels[panelnr] == (stlpanel_t *) NULL) @@ -1003,11 +1003,11 @@ static int stl_open(struct tty_struct *tty, struct file *filp) minordev -= brdp->panels[panelnr]->nrports; } if (portnr < 0) - return(-ENODEV); + return -ENODEV; portp = brdp->panels[panelnr]->ports[portnr]; if (portp == (stlport_t *) NULL) - return(-ENODEV); + return -ENODEV; /* * On the first open of the device setup the port hardware, and @@ -1021,7 +1021,7 @@ static int stl_open(struct tty_struct *tty, struct file *filp) if (portp->tx.buf == (char *) NULL) { portp->tx.buf = (char *) stl_memalloc(STL_TXBUFSIZE); if (portp->tx.buf == (char *) NULL) - return(-ENOMEM); + return -ENOMEM; portp->tx.head = portp->tx.buf; portp->tx.tail = portp->tx.buf; } @@ -1043,8 +1043,8 @@ static int stl_open(struct tty_struct *tty, struct file *filp) if (portp->flags & ASYNC_CLOSING) { interruptible_sleep_on(&portp->close_wait); if (portp->flags & ASYNC_HUP_NOTIFY) - return(-EAGAIN); - return(-ERESTARTSYS); + return -EAGAIN; + return -ERESTARTSYS; } /* @@ -1054,11 +1054,11 @@ static int stl_open(struct tty_struct *tty, struct file *filp) */ if (!(filp->f_flags & O_NONBLOCK)) { if ((rc = stl_waitcarrier(portp, filp)) != 0) - return(rc); + return rc; } portp->flags |= ASYNC_NORMAL_ACTIVE; - return(0); + return 0; } /*****************************************************************************/ @@ -1115,7 +1115,7 @@ static int stl_waitcarrier(stlport_t *portp, struct file *filp) portp->openwaitcnt--; restore_flags(flags); - return(rc); + return rc; } /*****************************************************************************/ @@ -1211,12 +1211,12 @@ static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count if ((tty == (struct tty_struct *) NULL) || (stl_tmpwritebuf == (char *) NULL)) - return(0); + return 0; portp = tty->driver_data; if (portp == (stlport_t *) NULL) - return(0); + return 0; if (portp->tx.buf == (char *) NULL) - return(0); + return 0; /* * If copying direct from user space we must cater for page faults, @@ -1255,7 +1255,7 @@ static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count clear_bit(ASYI_TXLOW, &portp->istate); stl_startrxtx(portp, -1, 1); - return(count); + return count; } /*****************************************************************************/ @@ -1336,16 +1336,16 @@ static int stl_writeroom(struct tty_struct *tty) #endif if (tty == (struct tty_struct *) NULL) - return(0); + return 0; portp = tty->driver_data; if (portp == (stlport_t *) NULL) - return(0); + return 0; if (portp->tx.buf == (char *) NULL) - return(0); + return 0; head = portp->tx.head; tail = portp->tx.tail; - return((head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1)); + return ((head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1)); } /*****************************************************************************/ @@ -1370,19 +1370,19 @@ static int stl_charsinbuffer(struct tty_struct *tty) #endif if (tty == (struct tty_struct *) NULL) - return(0); + return 0; portp = tty->driver_data; if (portp == (stlport_t *) NULL) - return(0); + return 0; if (portp->tx.buf == (char *) NULL) - return(0); + return 0; head = portp->tx.head; tail = portp->tx.tail; size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head)); if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate)) size = 1; - return(size); + return size; } /*****************************************************************************/ @@ -1447,7 +1447,7 @@ static int stl_setserial(stlport_t *portp, struct serial_struct __user *sp) (sio.close_delay != portp->close_delay) || ((sio.flags & ~ASYNC_USR_MASK) != (portp->flags & ~ASYNC_USR_MASK))) - return(-EPERM); + return -EPERM; } portp->flags = (portp->flags & ~ASYNC_USR_MASK) | @@ -1457,7 +1457,7 @@ static int stl_setserial(stlport_t *portp, struct serial_struct __user *sp) portp->closing_wait = sio.closing_wait; portp->custom_divisor = sio.custom_divisor; stl_setport(portp, portp->tty->termios); - return(0); + return 0; } /*****************************************************************************/ @@ -1467,12 +1467,12 @@ static int stl_tiocmget(struct tty_struct *tty, struct file *file) stlport_t *portp; if (tty == (struct tty_struct *) NULL) - return(-ENODEV); + return -ENODEV; portp = tty->driver_data; if (portp == (stlport_t *) NULL) - return(-ENODEV); + return -ENODEV; if (tty->flags & (1 << TTY_IO_ERROR)) - return(-EIO); + return -EIO; return stl_getsignals(portp); } @@ -1484,12 +1484,12 @@ static int stl_tiocmset(struct tty_struct *tty, struct file *file, int rts = -1, dtr = -1; if (tty == (struct tty_struct *) NULL) - return(-ENODEV); + return -ENODEV; portp = tty->driver_data; if (portp == (stlport_t *) NULL) - return(-ENODEV); + return -ENODEV; if (tty->flags & (1 << TTY_IO_ERROR)) - return(-EIO); + return -EIO; if (set & TIOCM_RTS) rts = 1; @@ -1517,15 +1517,15 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd #endif if (tty == (struct tty_struct *) NULL) - return(-ENODEV); + return -ENODEV; portp = tty->driver_data; if (portp == (stlport_t *) NULL) - return(-ENODEV); + return -ENODEV; if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) { if (tty->flags & (1 << TTY_IO_ERROR)) - return(-EIO); + return -EIO; } rc = 0; @@ -1566,7 +1566,7 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd break; } - return(rc); + return rc; } /*****************************************************************************/ @@ -1872,7 +1872,7 @@ static int stl_portinfo(stlport_t *portp, int portnr, char *pos) pos[(MAXLINE - 2)] = '+'; pos[(MAXLINE - 1)] = '\n'; - return(MAXLINE); + return MAXLINE; } /*****************************************************************************/ @@ -1957,7 +1957,7 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof stl_readdone: *start = page; - return(pos - page); + return (pos - page); } /*****************************************************************************/ @@ -2349,7 +2349,7 @@ static inline int stl_initeio(stlbrd_t *brdp) } else { rc = 0; } - return(rc); + return rc; } /*****************************************************************************/ @@ -3116,7 +3116,7 @@ static int __init stl_init(void) return -1; } - return(0); + return 0; } /*****************************************************************************/ @@ -3132,7 +3132,7 @@ static int __init stl_init(void) static int stl_cd1400getreg(stlport_t *portp, int regnr) { outb((regnr + portp->uartaddr), portp->ioaddr); - return(inb(portp->ioaddr + EREG_DATA)); + return inb(portp->ioaddr + EREG_DATA); } static void stl_cd1400setreg(stlport_t *portp, int regnr, int value) @@ -3146,9 +3146,9 @@ static int stl_cd1400updatereg(stlport_t *portp, int regnr, int value) outb((regnr + portp->uartaddr), portp->ioaddr); if (inb(portp->ioaddr + EREG_DATA) != value) { outb(value, portp->ioaddr + EREG_DATA); - return(1); + return 1; } - return(0); + return 0; } /*****************************************************************************/ @@ -3206,7 +3206,7 @@ static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp) } BRDDISABLE(panelp->brdnr); - return(chipmask); + return chipmask; } /*****************************************************************************/ @@ -3557,7 +3557,7 @@ static int stl_cd1400getsignals(stlport_t *portp) #else sigs |= TIOCM_DSR; #endif - return(sigs); + return sigs; } /*****************************************************************************/ @@ -3830,9 +3830,9 @@ static int stl_cd1400datastate(stlport_t *portp) #endif if (portp == (stlport_t *) NULL) - return(0); + return 0; - return(test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0); + return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0; } /*****************************************************************************/ @@ -3912,20 +3912,20 @@ static inline int stl_cd1400breakisr(stlport_t *portp, int ioaddr) outb((SRER + portp->uartaddr), ioaddr); outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)), (ioaddr + EREG_DATA)); - return(1); + return 1; } else if (portp->brklen > 1) { outb((TDR + portp->uartaddr), ioaddr); outb(ETC_CMD, (ioaddr + EREG_DATA)); outb(ETC_STOPBREAK, (ioaddr + EREG_DATA)); portp->brklen = -1; - return(1); + return 1; } else { outb((COR2 + portp->uartaddr), ioaddr); outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC), (ioaddr + EREG_DATA)); portp->brklen = 0; } - return(0); + return 0; } /*****************************************************************************/ @@ -4166,7 +4166,7 @@ static void stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr) static int stl_sc26198getreg(stlport_t *portp, int regnr) { outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR)); - return(inb(portp->ioaddr + XP_DATA)); + return inb(portp->ioaddr + XP_DATA); } static void stl_sc26198setreg(stlport_t *portp, int regnr, int value) @@ -4180,9 +4180,9 @@ static int stl_sc26198updatereg(stlport_t *portp, int regnr, int value) outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR)); if (inb(portp->ioaddr + XP_DATA) != value) { outb(value, (portp->ioaddr + XP_DATA)); - return(1); + return 1; } - return(0); + return 0; } /*****************************************************************************/ @@ -4194,7 +4194,7 @@ static int stl_sc26198updatereg(stlport_t *portp, int regnr, int value) static int stl_sc26198getglobreg(stlport_t *portp, int regnr) { outb(regnr, (portp->ioaddr + XP_ADDR)); - return(inb(portp->ioaddr + XP_DATA)); + return inb(portp->ioaddr + XP_DATA); } #if 0 @@ -4252,7 +4252,7 @@ static int stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp) } BRDDISABLE(panelp->brdnr); - return(chipmask); + return chipmask; } /*****************************************************************************/ @@ -4546,7 +4546,7 @@ static int stl_sc26198getsignals(stlport_t *portp) sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR; sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS; sigs |= TIOCM_DSR; - return(sigs); + return sigs; } /*****************************************************************************/ @@ -4828,9 +4828,9 @@ static int stl_sc26198datastate(stlport_t *portp) #endif if (portp == (stlport_t *) NULL) - return(0); + return 0; if (test_bit(ASYI_TXBUSY, &portp->istate)) - return(1); + return 1; save_flags(flags); cli(); @@ -4839,7 +4839,7 @@ static int stl_sc26198datastate(stlport_t *portp) BRDDISABLE(portp->brdnr); restore_flags(flags); - return((sr & SR_TXEMPTY) ? 0 : 1); + return (sr & SR_TXEMPTY) ? 0 : 1; } /*****************************************************************************/ diff --git a/fs/efs/super.c b/fs/efs/super.c index d8d5ea9a999..afc4891feb3 100644 --- a/fs/efs/super.c +++ b/fs/efs/super.c @@ -222,12 +222,13 @@ static efs_block_t efs_validate_vh(struct volume_header *vh) { sblock); #endif } - return(sblock); + return sblock; } static int efs_validate_super(struct efs_sb_info *sb, struct efs_super *super) { - if (!IS_EFS_MAGIC(be32_to_cpu(super->fs_magic))) return -1; + if (!IS_EFS_MAGIC(be32_to_cpu(super->fs_magic))) + return -1; sb->fs_magic = be32_to_cpu(super->fs_magic); sb->total_blocks = be32_to_cpu(super->fs_size); diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 7dcdd0640c3..8d588602010 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c @@ -497,7 +497,7 @@ xfs_qm_dqflush_all( int error; if (mp->m_quotainfo == NULL) - return (0); + return 0; niters = 0; again: xfs_qm_mplist_lock(mp); @@ -528,7 +528,7 @@ again: error = xfs_qm_dqflush(dqp, flags); xfs_dqunlock(dqp); if (error) - return (error); + return error; xfs_qm_mplist_lock(mp); if (recl != XFS_QI_MPLRECLAIMS(mp)) { @@ -540,7 +540,7 @@ again: xfs_qm_mplist_unlock(mp); /* return ! busy */ - return (0); + return 0; } /* * Release the group dquot pointers the user dquots may be @@ -599,7 +599,7 @@ xfs_qm_dqpurge_int( int nmisses; if (mp->m_quotainfo == NULL) - return (0); + return 0; dqtype = (flags & XFS_QMOPT_UQUOTA) ? XFS_DQ_USER : 0; dqtype |= (flags & XFS_QMOPT_PQUOTA) ? XFS_DQ_PROJ : 0; @@ -796,7 +796,7 @@ xfs_qm_dqattach_one( ASSERT(XFS_DQ_IS_LOCKED(dqp)); } #endif - return (error); + return error; } @@ -897,7 +897,7 @@ xfs_qm_dqattach( (! XFS_NOT_DQATTACHED(mp, ip)) || (ip->i_ino == mp->m_sb.sb_uquotino) || (ip->i_ino == mp->m_sb.sb_gquotino)) - return (0); + return 0; ASSERT((flags & XFS_QMOPT_ILOCKED) == 0 || XFS_ISLOCKED_INODE_EXCL(ip)); @@ -984,7 +984,7 @@ xfs_qm_dqattach( else ASSERT(XFS_ISLOCKED_INODE_EXCL(ip)); #endif - return (error); + return error; } /* @@ -1049,7 +1049,7 @@ xfs_qm_sync( */ if (! XFS_IS_QUOTA_ON(mp)) { xfs_qm_mplist_unlock(mp); - return (0); + return 0; } FOREACH_DQUOT_IN_MP(dqp, mp) { /* @@ -1109,9 +1109,9 @@ xfs_qm_sync( error = xfs_qm_dqflush(dqp, flush_flags); xfs_dqunlock(dqp); if (error && XFS_FORCED_SHUTDOWN(mp)) - return(0); /* Need to prevent umount failure */ + return 0; /* Need to prevent umount failure */ else if (error) - return (error); + return error; xfs_qm_mplist_lock(mp); if (recl != XFS_QI_MPLRECLAIMS(mp)) { @@ -1124,7 +1124,7 @@ xfs_qm_sync( } xfs_qm_mplist_unlock(mp); - return (0); + return 0; } @@ -1146,7 +1146,7 @@ xfs_qm_init_quotainfo( * Tell XQM that we exist as soon as possible. */ if ((error = xfs_qm_hold_quotafs_ref(mp))) { - return (error); + return error; } qinf = mp->m_quotainfo = kmem_zalloc(sizeof(xfs_quotainfo_t), KM_SLEEP); @@ -1158,7 +1158,7 @@ xfs_qm_init_quotainfo( if ((error = xfs_qm_init_quotainos(mp))) { kmem_free(qinf, sizeof(xfs_quotainfo_t)); mp->m_quotainfo = NULL; - return (error); + return error; } spinlock_init(&qinf->qi_pinlock, "xfs_qinf_pin"); @@ -1232,7 +1232,7 @@ xfs_qm_init_quotainfo( qinf->qi_rtbwarnlimit = XFS_QM_RTBWARNLIMIT; } - return (0); + return 0; } @@ -1332,7 +1332,7 @@ xfs_qm_dqget_noattach( */ ASSERT(error != ESRCH); ASSERT(error != ENOENT); - return (error); + return error; } ASSERT(udqp); } @@ -1355,7 +1355,7 @@ xfs_qm_dqget_noattach( xfs_qm_dqrele(udqp); ASSERT(error != ESRCH); ASSERT(error != ENOENT); - return (error); + return error; } ASSERT(gdqp); @@ -1376,7 +1376,7 @@ xfs_qm_dqget_noattach( if (udqp) ASSERT(XFS_DQ_IS_LOCKED(udqp)); if (gdqp) ASSERT(XFS_DQ_IS_LOCKED(gdqp)); #endif - return (0); + return 0; } /* @@ -1404,7 +1404,7 @@ xfs_qm_qino_alloc( XFS_TRANS_PERM_LOG_RES, XFS_CREATE_LOG_COUNT))) { xfs_trans_cancel(tp, 0); - return (error); + return error; } memset(&zerocr, 0, sizeof(zerocr)); memset(&zeroino, 0, sizeof(zeroino)); @@ -1413,7 +1413,7 @@ xfs_qm_qino_alloc( &zerocr, 0, 1, ip, &committed))) { xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); - return (error); + return error; } /* @@ -1461,9 +1461,9 @@ xfs_qm_qino_alloc( if ((error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL))) { xfs_fs_cmn_err(CE_ALERT, mp, "XFS qino_alloc failed!"); - return (error); + return error; } - return (0); + return 0; } @@ -1508,7 +1508,7 @@ xfs_qm_reset_dqcounts( ddq = (xfs_disk_dquot_t *) ((xfs_dqblk_t *)ddq + 1); } - return (0); + return 0; } STATIC int @@ -1557,7 +1557,7 @@ xfs_qm_dqiter_bufs( bno++; firstid += XFS_QM_DQPERBLK(mp); } - return (error); + return error; } /* @@ -1586,7 +1586,7 @@ xfs_qm_dqiterate( * happens only at mount time which is single threaded. */ if (qip->i_d.di_nblocks == 0) - return (0); + return 0; map = kmem_alloc(XFS_DQITER_MAP_SIZE * sizeof(*map), KM_SLEEP); @@ -1655,7 +1655,7 @@ xfs_qm_dqiterate( kmem_free(map, XFS_DQITER_MAP_SIZE * sizeof(*map)); - return (error); + return error; } /* @@ -1715,7 +1715,7 @@ xfs_qm_get_rtblks( ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); if (!(ifp->if_flags & XFS_IFEXTENTS)) { if ((error = xfs_iread_extents(NULL, ip, XFS_DATA_FORK))) - return (error); + return error; } rtblks = 0; nextents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t); @@ -1723,7 +1723,7 @@ xfs_qm_get_rtblks( for (ep = base; ep < &base[nextents]; ep++) rtblks += xfs_bmbt_get_blockcount(ep); *O_rtblks = (xfs_qcnt_t)rtblks; - return (0); + return 0; } /* @@ -1767,7 +1767,7 @@ xfs_qm_dqusage_adjust( */ if ((error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_EXCL, &ip, bno))) { *res = BULKSTAT_RV_NOTHING; - return (error); + return error; } if (ip->i_d.di_mode == 0) { @@ -1785,7 +1785,7 @@ xfs_qm_dqusage_adjust( if ((error = xfs_qm_dqget_noattach(ip, &udqp, &gdqp))) { xfs_iput(ip, XFS_ILOCK_EXCL); *res = BULKSTAT_RV_GIVEUP; - return (error); + return error; } rtblks = 0; @@ -1802,7 +1802,7 @@ xfs_qm_dqusage_adjust( if (gdqp) xfs_qm_dqput(gdqp); *res = BULKSTAT_RV_GIVEUP; - return (error); + return error; } nblks = (xfs_qcnt_t)ip->i_d.di_nblocks - rtblks; } @@ -1847,7 +1847,7 @@ xfs_qm_dqusage_adjust( * Goto next inode. */ *res = BULKSTAT_RV_DIDONE; - return (0); + return 0; } /* @@ -2041,7 +2041,7 @@ xfs_qm_init_quotainos( XFS_QI_UQIP(mp) = uip; XFS_QI_GQIP(mp) = gip; - return (0); + return 0; } @@ -2062,7 +2062,7 @@ xfs_qm_shake_freelist( int nflushes; if (howmany <= 0) - return (0); + return 0; nreclaimed = 0; restarts = 0; @@ -2088,7 +2088,7 @@ xfs_qm_shake_freelist( xfs_dqunlock(dqp); xfs_qm_freelist_unlock(xfs_Gqm); if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS) - return (nreclaimed); + return nreclaimed; XQM_STATS_INC(xqmstats.xs_qm_dqwants); goto tryagain; } @@ -2163,7 +2163,7 @@ xfs_qm_shake_freelist( XFS_DQ_HASH_UNLOCK(hash); xfs_qm_freelist_unlock(xfs_Gqm); if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS) - return (nreclaimed); + return nreclaimed; goto tryagain; } xfs_dqtrace_entry(dqp, "DQSHAKE: UNLINKING"); @@ -2188,7 +2188,7 @@ xfs_qm_shake_freelist( dqp = nextdqp; } xfs_qm_freelist_unlock(xfs_Gqm); - return (nreclaimed); + return nreclaimed; } @@ -2202,9 +2202,9 @@ xfs_qm_shake(int nr_to_scan, gfp_t gfp_mask) int ndqused, nfree, n; if (!kmem_shake_allow(gfp_mask)) - return (0); + return 0; if (!xfs_Gqm) - return (0); + return 0; nfree = xfs_Gqm->qm_dqfreelist.qh_nelems; /* free dquots */ /* incore dquots in all f/s's */ @@ -2213,7 +2213,7 @@ xfs_qm_shake(int nr_to_scan, gfp_t gfp_mask) ASSERT(ndqused >= 0); if (nfree <= ndqused && nfree < ndquot) - return (0); + return 0; ndqused *= xfs_Gqm->qm_dqfree_ratio; /* target # of free dquots */ n = nfree - ndqused - ndquot; /* # over target */ @@ -2257,7 +2257,7 @@ xfs_qm_dqreclaim_one(void) xfs_dqunlock(dqp); xfs_qm_freelist_unlock(xfs_Gqm); if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS) - return (NULL); + return NULL; XQM_STATS_INC(xqmstats.xs_qm_dqwants); goto startagain; } @@ -2333,7 +2333,7 @@ xfs_qm_dqreclaim_one(void) } xfs_qm_freelist_unlock(xfs_Gqm); - return (dqpout); + return dqpout; } @@ -2369,7 +2369,7 @@ xfs_qm_dqalloc_incore( */ memset(&dqp->q_core, 0, sizeof(dqp->q_core)); *O_dqpp = dqp; - return (B_FALSE); + return B_FALSE; } XQM_STATS_INC(xqmstats.xs_qm_dqreclaim_misses); } @@ -2382,7 +2382,7 @@ xfs_qm_dqalloc_incore( *O_dqpp = kmem_zone_zalloc(xfs_Gqm->qm_dqzone, KM_SLEEP); atomic_inc(&xfs_Gqm->qm_totaldquots); - return (B_TRUE); + return B_TRUE; } @@ -2407,13 +2407,13 @@ xfs_qm_write_sb_changes( 0, XFS_DEFAULT_LOG_COUNT))) { xfs_trans_cancel(tp, 0); - return (error); + return error; } xfs_mod_sb(tp, flags); (void) xfs_trans_commit(tp, 0, NULL); - return (0); + return 0; } @@ -2463,7 +2463,7 @@ xfs_qm_vop_dqalloc( if ((error = xfs_qm_dqattach(ip, XFS_QMOPT_DQALLOC | XFS_QMOPT_ILOCKED))) { xfs_iunlock(ip, lockflags); - return (error); + return error; } } @@ -2486,7 +2486,7 @@ xfs_qm_vop_dqalloc( XFS_QMOPT_DOWARN, &uq))) { ASSERT(error != ENOENT); - return (error); + return error; } /* * Get the ilock in the right order. @@ -2517,7 +2517,7 @@ xfs_qm_vop_dqalloc( if (uq) xfs_qm_dqrele(uq); ASSERT(error != ENOENT); - return (error); + return error; } xfs_dqunlock(gq); lockflags = XFS_ILOCK_SHARED; @@ -2565,7 +2565,7 @@ xfs_qm_vop_dqalloc( *O_gdqpp = gq; else if (gq) xfs_qm_dqrele(gq); - return (0); + return 0; } /* @@ -2608,7 +2608,7 @@ xfs_qm_vop_chown( xfs_dqunlock(newdq); *IO_olddq = newdq; - return (prevdq); + return prevdq; } /* @@ -2702,12 +2702,12 @@ xfs_qm_vop_rename_dqattach( ip = i_tab[0]; if (! XFS_IS_QUOTA_ON(ip->i_mount)) - return (0); + return 0; if (XFS_NOT_DQATTACHED(ip->i_mount, ip)) { error = xfs_qm_dqattach(ip, 0); if (error) - return (error); + return error; } for (i = 1; (i < 4 && i_tab[i]); i++) { /* @@ -2717,11 +2717,11 @@ xfs_qm_vop_rename_dqattach( if (XFS_NOT_DQATTACHED(ip->i_mount, ip)) { error = xfs_qm_dqattach(ip, 0); if (error) - return (error); + return error; } } } - return (0); + return 0; } void @@ -2834,7 +2834,7 @@ xfs_qm_dqhashlock_nowait( int locked; locked = mutex_trylock(&((dqp)->q_hash->qh_lock)); - return (locked); + return locked; } int @@ -2844,7 +2844,7 @@ xfs_qm_freelist_lock_nowait( int locked; locked = mutex_trylock(&(xqm->qm_dqfreelist.qh_lock)); - return (locked); + return locked; } STATIC int @@ -2855,5 +2855,5 @@ xfs_qm_mplist_nowait( ASSERT(mp->m_quotainfo); locked = mutex_trylock(&(XFS_QI_MPLLOCK(mp))); - return (locked); + return locked; } diff --git a/fs/xfs/xfs_dir_leaf.c b/fs/xfs/xfs_dir_leaf.c index 950df31efc4..e83074016ab 100644 --- a/fs/xfs/xfs_dir_leaf.c +++ b/fs/xfs/xfs_dir_leaf.c @@ -147,7 +147,7 @@ xfs_dir_shortform_create(xfs_da_args_t *args, xfs_ino_t parent) hdr->count = 0; dp->i_d.di_size = sizeof(*hdr); xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); - return(0); + return 0; } /* @@ -180,7 +180,7 @@ xfs_dir_shortform_addname(xfs_da_args_t *args) if (sfe->namelen == args->namelen && args->name[0] == sfe->name[0] && memcmp(args->name, sfe->name, args->namelen) == 0) - return(XFS_ERROR(EEXIST)); + return XFS_ERROR(EEXIST); sfe = XFS_DIR_SF_NEXTENTRY(sfe); } @@ -198,7 +198,7 @@ xfs_dir_shortform_addname(xfs_da_args_t *args) dp->i_d.di_size += size; xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); - return(0); + return 0; } /* @@ -238,7 +238,7 @@ xfs_dir_shortform_removename(xfs_da_args_t *args) } if (i < 0) { ASSERT(args->oknoent); - return(XFS_ERROR(ENOENT)); + return XFS_ERROR(ENOENT); } if ((base + size) != dp->i_d.di_size) { @@ -251,7 +251,7 @@ xfs_dir_shortform_removename(xfs_da_args_t *args) dp->i_d.di_size -= size; xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); - return(0); + return 0; } /* @@ -390,7 +390,7 @@ xfs_dir_shortform_to_leaf(xfs_da_args_t *iargs) out: kmem_free(tmpbuffer, size); - return(retval); + return retval; } STATIC int @@ -596,7 +596,7 @@ xfs_dir_shortform_replace(xfs_da_args_t *args) /* XXX - replace assert? */ XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sf->hdr.parent); xfs_trans_log_inode(args->trans, dp, XFS_ILOG_DDATA); - return(0); + return 0; } ASSERT(args->namelen != 1 || args->name[0] != '.'); sfe = &sf->list[0]; @@ -608,12 +608,12 @@ xfs_dir_shortform_replace(xfs_da_args_t *args) (char *)&sfe->inumber, sizeof(xfs_ino_t))); XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sfe->inumber); xfs_trans_log_inode(args->trans, dp, XFS_ILOG_DDATA); - return(0); + return 0; } sfe = XFS_DIR_SF_NEXTENTRY(sfe); } ASSERT(args->oknoent); - return(XFS_ERROR(ENOENT)); + return XFS_ERROR(ENOENT); } /* @@ -695,7 +695,7 @@ xfs_dir_leaf_to_shortform(xfs_da_args_t *iargs) out: kmem_free(tmpbuffer, XFS_LBSIZE(dp->i_mount)); - return(retval); + return retval; } /* @@ -715,17 +715,17 @@ xfs_dir_leaf_to_node(xfs_da_args_t *args) retval = xfs_da_grow_inode(args, &blkno); ASSERT(blkno == 1); if (retval) - return(retval); + return retval; retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp1, XFS_DATA_FORK); if (retval) - return(retval); + return retval; ASSERT(bp1 != NULL); retval = xfs_da_get_buf(args->trans, args->dp, 1, -1, &bp2, XFS_DATA_FORK); if (retval) { xfs_da_buf_done(bp1); - return(retval); + return retval; } ASSERT(bp2 != NULL); memcpy(bp2->data, bp1->data, XFS_LBSIZE(dp->i_mount)); @@ -738,7 +738,7 @@ xfs_dir_leaf_to_node(xfs_da_args_t *args) retval = xfs_da_node_create(args, 0, 1, &bp1, XFS_DATA_FORK); if (retval) { xfs_da_buf_done(bp2); - return(retval); + return retval; } node = bp1->data; leaf = bp2->data; @@ -751,7 +751,7 @@ xfs_dir_leaf_to_node(xfs_da_args_t *args) XFS_DA_LOGRANGE(node, &node->btree[0], sizeof(node->btree[0]))); xfs_da_buf_done(bp1); - return(retval); + return retval; } @@ -776,7 +776,7 @@ xfs_dir_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp) ASSERT(dp != NULL); retval = xfs_da_get_buf(args->trans, dp, blkno, -1, &bp, XFS_DATA_FORK); if (retval) - return(retval); + return retval; ASSERT(bp != NULL); leaf = bp->data; memset((char *)leaf, 0, XFS_LBSIZE(dp->i_mount)); @@ -791,7 +791,7 @@ xfs_dir_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp) xfs_da_log_buf(args->trans, bp, 0, XFS_LBSIZE(dp->i_mount) - 1); *bpp = bp; - return(0); + return 0; } /* @@ -813,10 +813,10 @@ xfs_dir_leaf_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk, ASSERT(oldblk->magic == XFS_DIR_LEAF_MAGIC); error = xfs_da_grow_inode(args, &blkno); if (error) - return(error); + return error; error = xfs_dir_leaf_create(args, blkno, &newblk->bp); if (error) - return(error); + return error; newblk->blkno = blkno; newblk->magic = XFS_DIR_LEAF_MAGIC; @@ -826,7 +826,7 @@ xfs_dir_leaf_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk, xfs_dir_leaf_rebalance(state, oldblk, newblk); error = xfs_da_blk_link(state, oldblk, newblk); if (error) - return(error); + return error; /* * Insert the new entry in the correct block. @@ -842,7 +842,7 @@ xfs_dir_leaf_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk, */ oldblk->hashval = xfs_dir_leaf_lasthash(oldblk->bp, NULL); newblk->hashval = xfs_dir_leaf_lasthash(newblk->bp, NULL); - return(error); + return error; } /* @@ -885,7 +885,7 @@ xfs_dir_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args, int index) if (INT_GET(map->size, ARCH_CONVERT) >= tmp) { if (!args->justcheck) xfs_dir_leaf_add_work(bp, args, index, i); - return(0); + return 0; } sum += INT_GET(map->size, ARCH_CONVERT); } @@ -896,7 +896,7 @@ xfs_dir_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args, int index) * no good and we should just give up. */ if (!hdr->holes && (sum < entsize)) - return(XFS_ERROR(ENOSPC)); + return XFS_ERROR(ENOSPC); /* * Compact the entries to coalesce free space. @@ -909,18 +909,18 @@ xfs_dir_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args, int index) (uint)sizeof(xfs_dir_leaf_entry_t) : 0, args->justcheck); if (error) - return(error); + return error; /* * After compaction, the block is guaranteed to have only one * free region, in freemap[0]. If it is not big enough, give up. */ if (INT_GET(hdr->freemap[0].size, ARCH_CONVERT) < (entsize + (uint)sizeof(xfs_dir_leaf_entry_t))) - return(XFS_ERROR(ENOSPC)); + return XFS_ERROR(ENOSPC); if (!args->justcheck) xfs_dir_leaf_add_work(bp, args, index, 0); - return(0); + return 0; } /* @@ -1072,7 +1072,7 @@ xfs_dir_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *bp, int musthave, kmem_free(tmpbuffer, lbsize); if (musthave || justcheck) kmem_free(tmpbuffer2, lbsize); - return(rval); + return rval; } /* @@ -1292,7 +1292,7 @@ xfs_dir_leaf_figure_balance(xfs_da_state_t *state, *countarg = count; *namebytesarg = totallen; - return(foundit); + return foundit; } /*======================================================================== @@ -1334,7 +1334,7 @@ xfs_dir_leaf_toosmall(xfs_da_state_t *state, int *action) INT_GET(leaf->hdr.namebytes, ARCH_CONVERT); if (bytes > (state->blocksize >> 1)) { *action = 0; /* blk over 50%, don't try to join */ - return(0); + return 0; } /* @@ -1353,13 +1353,13 @@ xfs_dir_leaf_toosmall(xfs_da_state_t *state, int *action) error = xfs_da_path_shift(state, &state->altpath, forward, 0, &retval); if (error) - return(error); + return error; if (retval) { *action = 0; } else { *action = 2; } - return(0); + return 0; } /* @@ -1381,7 +1381,7 @@ xfs_dir_leaf_toosmall(xfs_da_state_t *state, int *action) blkno, -1, &bp, XFS_DATA_FORK); if (error) - return(error); + return error; ASSERT(bp != NULL); leaf = (xfs_dir_leafblock_t *)info; @@ -1402,7 +1402,7 @@ xfs_dir_leaf_toosmall(xfs_da_state_t *state, int *action) } if (i >= 2) { *action = 0; - return(0); + return 0; } xfs_da_buf_done(bp); @@ -1419,13 +1419,13 @@ xfs_dir_leaf_toosmall(xfs_da_state_t *state, int *action) 0, &retval); } if (error) - return(error); + return error; if (retval) { *action = 0; } else { *action = 1; } - return(0); + return 0; } /* @@ -1575,8 +1575,8 @@ xfs_dir_leaf_remove(xfs_trans_t *trans, xfs_dabuf_t *bp, int index) tmp += INT_GET(leaf->hdr.count, ARCH_CONVERT) * ((uint)sizeof(xfs_dir_leaf_name_t) - 1); tmp += INT_GET(leaf->hdr.namebytes, ARCH_CONVERT); if (tmp < mp->m_dir_magicpct) - return(1); /* leaf is < 37% full */ - return(0); + return 1; /* leaf is < 37% full */ + return 0; } /* @@ -1732,7 +1732,7 @@ xfs_dir_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args, int *index) if ((probe == INT_GET(leaf->hdr.count, ARCH_CONVERT)) || (INT_GET(entry->hashval, ARCH_CONVERT) != hashval)) { *index = probe; ASSERT(args->oknoent); - return(XFS_ERROR(ENOENT)); + return XFS_ERROR(ENOENT); } /* @@ -1745,14 +1745,14 @@ xfs_dir_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args, int *index) memcmp(args->name, namest->name, args->namelen) == 0) { XFS_DIR_SF_GET_DIRINO(&namest->inumber, &args->inumber); *index = probe; - return(XFS_ERROR(EEXIST)); + return XFS_ERROR(EEXIST); } entry++; probe++; } *index = probe; ASSERT(probe == INT_GET(leaf->hdr.count, ARCH_CONVERT) || args->oknoent); - return(XFS_ERROR(ENOENT)); + return XFS_ERROR(ENOENT); } /*======================================================================== @@ -1890,9 +1890,9 @@ xfs_dir_leaf_order(xfs_dabuf_t *leaf1_bp, xfs_dabuf_t *leaf2_bp) INT_GET(leaf1->entries[ 0 ].hashval, ARCH_CONVERT)) || (INT_GET(leaf2->entries[ INT_GET(leaf2->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT) < INT_GET(leaf1->entries[ INT_GET(leaf1->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT)))) { - return(1); + return 1; } - return(0); + return 0; } /* @@ -1942,7 +1942,7 @@ xfs_dir_leaf_getdents_int( leaf = bp->data; if (INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) != XFS_DIR_LEAF_MAGIC) { *eobp = 1; - return(XFS_ERROR(ENOENT)); /* XXX wrong code */ + return XFS_ERROR(ENOENT); /* XXX wrong code */ } want_entno = XFS_DA_COOKIE_ENTRY(mp, uio->uio_offset); @@ -2000,7 +2000,7 @@ xfs_dir_leaf_getdents_int( * the node code will be setting uio_offset anyway. */ *eobp = 0; - return(0); + return 0; } xfs_dir_trace_g_due("leaf: hash found", dp, uio, entry); @@ -2057,7 +2057,7 @@ xfs_dir_leaf_getdents_int( retval = xfs_da_read_buf(dp->i_transp, dp, thishash, nextda, &bp2, XFS_DATA_FORK); if (retval) - return(retval); + return retval; ASSERT(bp2 != NULL); @@ -2073,7 +2073,7 @@ xfs_dir_leaf_getdents_int( leaf2); xfs_da_brelse(dp->i_transp, bp2); - return(XFS_ERROR(EFSCORRUPTED)); + return XFS_ERROR(EFSCORRUPTED); } nexthash = INT_GET(leaf2->entries[0].hashval, @@ -2139,7 +2139,7 @@ xfs_dir_leaf_getdents_int( xfs_dir_trace_g_du("leaf: E-O-B", dp, uio); - return(retval); + return retval; } } @@ -2149,7 +2149,7 @@ xfs_dir_leaf_getdents_int( xfs_dir_trace_g_du("leaf: E-O-F", dp, uio); - return(0); + return 0; } /* diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 163031c1e39..b4d971b0158 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -501,7 +501,7 @@ xfs_reserve_blocks( if (inval == (__uint64_t *)NULL) { outval->resblks = mp->m_resblks; outval->resblks_avail = mp->m_resblks_avail; - return(0); + return 0; } request = *inval; @@ -537,7 +537,7 @@ xfs_reserve_blocks( outval->resblks = mp->m_resblks; outval->resblks_avail = mp->m_resblks_avail; XFS_SB_UNLOCK(mp, s); - return(0); + return 0; } void diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 3d9a36e7736..9176995160e 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -403,7 +403,7 @@ xfs_log_release_iclog(xfs_mount_t *mp, if (xlog_state_release_iclog(log, iclog)) { xfs_force_shutdown(mp, XFS_LOG_IO_ERROR); - return(EIO); + return EIO; } return 0; @@ -556,7 +556,7 @@ xfs_log_unmount(xfs_mount_t *mp) error = xfs_log_unmount_write(mp); xfs_log_unmount_dealloc(mp); - return (error); + return error; } /* @@ -728,7 +728,7 @@ xfs_log_write(xfs_mount_t * mp, if ((error = xlog_write(mp, reg, nentries, tic, start_lsn, NULL, 0))) { xfs_force_shutdown(mp, XFS_LOG_IO_ERROR); } - return (error); + return error; } /* xfs_log_write */ @@ -836,7 +836,7 @@ xfs_log_need_covered(xfs_mount_t *mp) needed = 1; } LOG_UNLOCK(log, s); - return(needed); + return needed; } /****************************************************************************** @@ -1003,7 +1003,7 @@ xlog_bdstrat_cb(struct xfs_buf *bp) XFS_BUF_ERROR(bp, EIO); XFS_BUF_STALE(bp); xfs_biodone(bp); - return (XFS_ERROR(EIO)); + return XFS_ERROR(EIO); } @@ -1263,7 +1263,7 @@ xlog_commit_record(xfs_mount_t *mp, iclog, XLOG_COMMIT_TRANS))) { xfs_force_shutdown(mp, XFS_LOG_IO_ERROR); } - return (error); + return error; } /* xlog_commit_record */ @@ -1460,7 +1460,7 @@ xlog_sync(xlog_t *log, if ((error = XFS_bwrite(bp))) { xfs_ioerror_alert("xlog_sync", log->l_mp, bp, XFS_BUF_ADDR(bp)); - return (error); + return error; } if (split) { bp = iclog->ic_log->l_xbuf; @@ -1498,10 +1498,10 @@ xlog_sync(xlog_t *log, if ((error = XFS_bwrite(bp))) { xfs_ioerror_alert("xlog_sync (split)", log->l_mp, bp, XFS_BUF_ADDR(bp)); - return (error); + return error; } } - return (0); + return 0; } /* xlog_sync */ @@ -1798,7 +1798,7 @@ xlog_write(xfs_mount_t * mp, for (index = 0; index < nentries; ) { if ((error = xlog_state_get_iclog_space(log, len, &iclog, ticket, &contwr, &log_offset))) - return (error); + return error; ASSERT(log_offset <= iclog->ic_size - 1); ptr = (__psint_t) ((char *)iclog->ic_datap+log_offset); @@ -1903,7 +1903,7 @@ xlog_write(xfs_mount_t * mp, xlog_state_finish_copy(log, iclog, record_cnt, data_cnt); record_cnt = data_cnt = 0; if ((error = xlog_state_release_iclog(log, iclog))) - return (error); + return error; break; /* don't increment index */ } else { /* copied entire region */ index++; @@ -1917,7 +1917,7 @@ xlog_write(xfs_mount_t * mp, ASSERT(flags & XLOG_COMMIT_TRANS); *commit_iclog = iclog; } else if ((error = xlog_state_release_iclog(log, iclog))) - return (error); + return error; if (index == nentries) return 0; /* we are done */ else @@ -1934,7 +1934,7 @@ xlog_write(xfs_mount_t * mp, *commit_iclog = iclog; return 0; } - return (xlog_state_release_iclog(log, iclog)); + return xlog_state_release_iclog(log, iclog); } /* xlog_write */ @@ -2050,7 +2050,7 @@ xlog_get_lowest_lsn( } lsn_log = lsn_log->ic_next; } while (lsn_log != log->l_iclog); - return(lowest_lsn); + return lowest_lsn; } @@ -2402,7 +2402,7 @@ restart: if (iclog->ic_refcnt == 1) { LOG_UNLOCK(log, s); if ((error = xlog_state_release_iclog(log, iclog))) - return (error); + return error; } else { iclog->ic_refcnt--; LOG_UNLOCK(log, s); @@ -2569,7 +2569,7 @@ xlog_regrant_write_log_space(xlog_t *log, XLOG_TIC_RESET_RES(tic); if (tic->t_cnt > 0) - return (0); + return 0; #ifdef DEBUG if (log->l_flags & XLOG_ACTIVE_RECOVERY) @@ -2667,7 +2667,7 @@ redo: xlog_trace_loggrant(log, tic, "xlog_regrant_write_log_space: exit"); xlog_verify_grant_head(log, 1); GRANT_UNLOCK(log, s); - return (0); + return 0; error_return: @@ -2837,7 +2837,7 @@ xlog_state_release_iclog(xlog_t *log, if (sync) { return xlog_sync(log, iclog); } - return (0); + return 0; } /* xlog_state_release_iclog */ @@ -3127,7 +3127,7 @@ try_again: } while (iclog != log->l_iclog); LOG_UNLOCK(log, s); - return (0); + return 0; } /* xlog_state_sync */ @@ -3545,12 +3545,12 @@ xlog_state_ioerror( ic->ic_state = XLOG_STATE_IOERROR; ic = ic->ic_next; } while (ic != iclog); - return (0); + return 0; } /* * Return non-zero, if state transition has already happened. */ - return (1); + return 1; } /* @@ -3587,7 +3587,7 @@ xfs_log_force_umount( log->l_flags & XLOG_ACTIVE_RECOVERY) { mp->m_flags |= XFS_MOUNT_FS_SHUTDOWN; XFS_BUF_DONE(mp->m_sb_bp); - return (0); + return 0; } /* @@ -3596,7 +3596,7 @@ xfs_log_force_umount( */ if (logerror && log->l_iclog->ic_state & XLOG_STATE_IOERROR) { ASSERT(XLOG_FORCED_SHUTDOWN(log)); - return (1); + return 1; } retval = 0; /* @@ -3678,7 +3678,7 @@ xfs_log_force_umount( } #endif /* return non-zero if log IOERROR transition had already happened */ - return (retval); + return retval; } STATIC int @@ -3692,8 +3692,8 @@ xlog_iclogs_empty(xlog_t *log) * any language. */ if (iclog->ic_header.h_num_logops) - return(0); + return 0; iclog = iclog->ic_next; } while (iclog != log->l_iclog); - return(1); + return 1; } diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 6088e14f84e..62188ea392c 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -646,7 +646,7 @@ xfs_mountfs( if (mp->m_sb_bp == NULL) { if ((error = xfs_readsb(mp))) { - return (error); + return error; } } xfs_mount_common(mp, sbp); @@ -889,7 +889,7 @@ xfs_mountfs( * For client case we are done now */ if (mfsi_flags & XFS_MFSI_CLIENT) { - return(0); + return 0; } /* @@ -1182,7 +1182,7 @@ xfs_unmountfs_writesb(xfs_mount_t *mp) xfs_fs_cmn_err(CE_ALERT, mp, "Superblock write error detected while unmounting. Filesystem may not be marked shared readonly"); } xfs_buf_relse(sbp); - return (error); + return error; } /* @@ -1257,19 +1257,19 @@ xfs_mod_incore_sb_unlocked(xfs_mount_t *mp, xfs_sb_field_t field, lcounter += delta; if (lcounter < 0) { ASSERT(0); - return (XFS_ERROR(EINVAL)); + return XFS_ERROR(EINVAL); } mp->m_sb.sb_icount = lcounter; - return (0); + return 0; case XFS_SBS_IFREE: lcounter = (long long)mp->m_sb.sb_ifree; lcounter += delta; if (lcounter < 0) { ASSERT(0); - return (XFS_ERROR(EINVAL)); + return XFS_ERROR(EINVAL); } mp->m_sb.sb_ifree = lcounter; - return (0); + return 0; case XFS_SBS_FDBLOCKS: lcounter = (long long)mp->m_sb.sb_fdblocks; @@ -1296,101 +1296,101 @@ xfs_mod_incore_sb_unlocked(xfs_mount_t *mp, xfs_sb_field_t field, if (rsvd) { lcounter = (long long)mp->m_resblks_avail + delta; if (lcounter < 0) { - return (XFS_ERROR(ENOSPC)); + return XFS_ERROR(ENOSPC); } mp->m_resblks_avail = lcounter; - return (0); + return 0; } else { /* not reserved */ - return (XFS_ERROR(ENOSPC)); + return XFS_ERROR(ENOSPC); } } } mp->m_sb.sb_fdblocks = lcounter; - return (0); + return 0; case XFS_SBS_FREXTENTS: lcounter = (long long)mp->m_sb.sb_frextents; lcounter += delta; if (lcounter < 0) { - return (XFS_ERROR(ENOSPC)); + return XFS_ERROR(ENOSPC); } mp->m_sb.sb_frextents = lcounter; - return (0); + return 0; case XFS_SBS_DBLOCKS: lcounter = (long long)mp->m_sb.sb_dblocks; lcounter += delta; if (lcounter < 0) { ASSERT(0); - return (XFS_ERROR(EINVAL)); + return XFS_ERROR(EINVAL); } mp->m_sb.sb_dblocks = lcounter; - return (0); + return 0; case XFS_SBS_AGCOUNT: scounter = mp->m_sb.sb_agcount; scounter += delta; if (scounter < 0) { ASSERT(0); - return (XFS_ERROR(EINVAL)); + return XFS_ERROR(EINVAL); } mp->m_sb.sb_agcount = scounter; - return (0); + return 0; case XFS_SBS_IMAX_PCT: scounter = mp->m_sb.sb_imax_pct; scounter += delta; if (scounter < 0) { ASSERT(0); - return (XFS_ERROR(EINVAL)); + return XFS_ERROR(EINVAL); } mp->m_sb.sb_imax_pct = scounter; - return (0); + return 0; case XFS_SBS_REXTSIZE: scounter = mp->m_sb.sb_rextsize; scounter += delta; if (scounter < 0) { ASSERT(0); - return (XFS_ERROR(EINVAL)); + return XFS_ERROR(EINVAL); } mp->m_sb.sb_rextsize = scounter; - return (0); + return 0; case XFS_SBS_RBMBLOCKS: scounter = mp->m_sb.sb_rbmblocks; scounter += delta; if (scounter < 0) { ASSERT(0); - return (XFS_ERROR(EINVAL)); + return XFS_ERROR(EINVAL); } mp->m_sb.sb_rbmblocks = scounter; - return (0); + return 0; case XFS_SBS_RBLOCKS: lcounter = (long long)mp->m_sb.sb_rblocks; lcounter += delta; if (lcounter < 0) { ASSERT(0); - return (XFS_ERROR(EINVAL)); + return XFS_ERROR(EINVAL); } mp->m_sb.sb_rblocks = lcounter; - return (0); + return 0; case XFS_SBS_REXTENTS: lcounter = (long long)mp->m_sb.sb_rextents; lcounter += delta; if (lcounter < 0) { ASSERT(0); - return (XFS_ERROR(EINVAL)); + return XFS_ERROR(EINVAL); } mp->m_sb.sb_rextents = lcounter; - return (0); + return 0; case XFS_SBS_REXTSLOG: scounter = mp->m_sb.sb_rextslog; scounter += delta; if (scounter < 0) { ASSERT(0); - return (XFS_ERROR(EINVAL)); + return XFS_ERROR(EINVAL); } mp->m_sb.sb_rextslog = scounter; - return (0); + return 0; default: ASSERT(0); - return (XFS_ERROR(EINVAL)); + return XFS_ERROR(EINVAL); } } @@ -1409,7 +1409,7 @@ xfs_mod_incore_sb(xfs_mount_t *mp, xfs_sb_field_t field, int delta, int rsvd) s = XFS_SB_LOCK(mp); status = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd); XFS_SB_UNLOCK(mp, s); - return (status); + return status; } /* @@ -1470,7 +1470,7 @@ xfs_mod_incore_sb_batch(xfs_mount_t *mp, xfs_mod_sb_t *msb, uint nmsb, int rsvd) } } XFS_SB_UNLOCK(mp, s); - return (status); + return status; } /* @@ -1500,7 +1500,7 @@ xfs_getsb( } XFS_BUF_HOLD(bp); ASSERT(XFS_BUF_ISDONE(bp)); - return (bp); + return bp; } /* diff --git a/fs/xfs/xfs_trans_item.c b/fs/xfs/xfs_trans_item.c index 486147ef0e3..1117d600d74 100644 --- a/fs/xfs/xfs_trans_item.c +++ b/fs/xfs/xfs_trans_item.c @@ -78,7 +78,7 @@ xfs_trans_add_item(xfs_trans_t *tp, xfs_log_item_t *lip) lidp->lid_size = 0; lip->li_desc = lidp; lip->li_mountp = tp->t_mountp; - return (lidp); + return lidp; } /* @@ -119,7 +119,7 @@ xfs_trans_add_item(xfs_trans_t *tp, xfs_log_item_t *lip) lidp->lid_size = 0; lip->li_desc = lidp; lip->li_mountp = tp->t_mountp; - return (lidp); + return lidp; } /* @@ -180,7 +180,7 @@ xfs_trans_find_item(xfs_trans_t *tp, xfs_log_item_t *lip) { ASSERT(lip->li_desc != NULL); - return (lip->li_desc); + return lip->li_desc; } @@ -219,10 +219,10 @@ xfs_trans_first_item(xfs_trans_t *tp) continue; } - return (XFS_LIC_SLOT(licp, i)); + return XFS_LIC_SLOT(licp, i); } cmn_err(CE_WARN, "xfs_trans_first_item() -- no first item"); - return(NULL); + return NULL; } @@ -252,7 +252,7 @@ xfs_trans_next_item(xfs_trans_t *tp, xfs_log_item_desc_t *lidp) continue; } - return (XFS_LIC_SLOT(licp, i)); + return XFS_LIC_SLOT(licp, i); } /* @@ -261,7 +261,7 @@ xfs_trans_next_item(xfs_trans_t *tp, xfs_log_item_desc_t *lidp) * If there is no next chunk, return NULL. */ if (licp->lic_next == NULL) { - return (NULL); + return NULL; } licp = licp->lic_next; @@ -271,7 +271,7 @@ xfs_trans_next_item(xfs_trans_t *tp, xfs_log_item_desc_t *lidp) continue; } - return (XFS_LIC_SLOT(licp, i)); + return XFS_LIC_SLOT(licp, i); } ASSERT(0); /* NOTREACHED */ @@ -425,7 +425,7 @@ xfs_trans_unlock_chunk( } } - return (freed); + return freed; } @@ -478,7 +478,7 @@ xfs_trans_add_busy(xfs_trans_t *tp, xfs_agnumber_t ag, xfs_extlen_t idx) */ lbsp->lbc_ag = ag; lbsp->lbc_idx = idx; - return (lbsp); + return lbsp; } /* @@ -512,7 +512,7 @@ xfs_trans_add_busy(xfs_trans_t *tp, xfs_agnumber_t ag, xfs_extlen_t idx) tp->t_busy_free--; lbsp->lbc_ag = ag; lbsp->lbc_idx = idx; - return (lbsp); + return lbsp; } diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 8076cc981e1..eaab355f5a8 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -338,7 +338,7 @@ xfs_setattr( code = XFS_QM_DQVOPALLOC(mp, ip, uid, gid, projid, qflags, &udqp, &gdqp); if (code) - return (code); + return code; } /* @@ -1027,11 +1027,8 @@ xfs_readlink( } - error_return: - xfs_iunlock(ip, XFS_ILOCK_SHARED); - return error; } @@ -1206,7 +1203,7 @@ xfs_inactive_free_eofblocks( last_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp)); map_len = last_fsb - end_fsb; if (map_len <= 0) - return (0); + return 0; nimaps = 1; xfs_ilock(ip, XFS_ILOCK_SHARED); @@ -1221,7 +1218,7 @@ xfs_inactive_free_eofblocks( * Attach the dquots to the inode up front. */ if ((error = XFS_QM_DQATTACH(mp, ip, 0))) - return (error); + return error; /* * There are blocks after the end of file. @@ -1249,7 +1246,7 @@ xfs_inactive_free_eofblocks( ASSERT(XFS_FORCED_SHUTDOWN(mp)); xfs_trans_cancel(tp, 0); xfs_iunlock(ip, XFS_IOLOCK_EXCL); - return (error); + return error; } xfs_ilock(ip, XFS_ILOCK_EXCL); @@ -1277,7 +1274,7 @@ xfs_inactive_free_eofblocks( } xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); } - return (error); + return error; } /* @@ -1455,7 +1452,7 @@ xfs_inactive_symlink_local( if (error) { xfs_trans_cancel(*tpp, 0); *tpp = NULL; - return (error); + return error; } xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); @@ -1468,7 +1465,7 @@ xfs_inactive_symlink_local( XFS_DATA_FORK); ASSERT(ip->i_df.if_bytes == 0); } - return (0); + return 0; } /* @@ -1494,7 +1491,7 @@ xfs_inactive_attrs( if (error) { *tpp = NULL; xfs_iunlock(ip, XFS_IOLOCK_EXCL); - return (error); /* goto out*/ + return error; /* goto out */ } tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); @@ -1507,7 +1504,7 @@ xfs_inactive_attrs( xfs_trans_cancel(tp, 0); *tpp = NULL; xfs_iunlock(ip, XFS_IOLOCK_EXCL); - return (error); + return error; } xfs_ilock(ip, XFS_ILOCK_EXCL); @@ -1518,7 +1515,7 @@ xfs_inactive_attrs( ASSERT(ip->i_d.di_anextents == 0); *tpp = tp; - return (0); + return 0; } STATIC int @@ -1557,7 +1554,7 @@ xfs_release( (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)))) { if ((error = xfs_inactive_free_eofblocks(mp, ip))) - return (error); + return error; /* Update linux inode block count after free above */ LINVFS_GET_IP(vp)->i_blocks = XFS_FSB_TO_BB(mp, ip->i_d.di_nblocks + ip->i_delayed_blks); @@ -1638,7 +1635,7 @@ xfs_inactive( (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) || (ip->i_delayed_blks != 0)))) { if ((error = xfs_inactive_free_eofblocks(mp, ip))) - return (VN_INACTIVE_CACHE); + return VN_INACTIVE_CACHE; /* Update linux inode block count after free above */ LINVFS_GET_IP(vp)->i_blocks = XFS_FSB_TO_BB(mp, ip->i_d.di_nblocks + ip->i_delayed_blks); @@ -1649,7 +1646,7 @@ xfs_inactive( ASSERT(ip->i_d.di_nlink == 0); if ((error = XFS_QM_DQATTACH(mp, ip, 0))) - return (VN_INACTIVE_CACHE); + return VN_INACTIVE_CACHE; tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); if (truncate) { @@ -1672,7 +1669,7 @@ xfs_inactive( ASSERT(XFS_FORCED_SHUTDOWN(mp)); xfs_trans_cancel(tp, 0); xfs_iunlock(ip, XFS_IOLOCK_EXCL); - return (VN_INACTIVE_CACHE); + return VN_INACTIVE_CACHE; } xfs_ilock(ip, XFS_ILOCK_EXCL); @@ -1693,7 +1690,7 @@ xfs_inactive( xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); - return (VN_INACTIVE_CACHE); + return VN_INACTIVE_CACHE; } } else if ((ip->i_d.di_mode & S_IFMT) == S_IFLNK) { @@ -1707,7 +1704,7 @@ xfs_inactive( if (error) { ASSERT(tp == NULL); - return (VN_INACTIVE_CACHE); + return VN_INACTIVE_CACHE; } xfs_trans_ijoin(tp, ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); @@ -1720,7 +1717,7 @@ xfs_inactive( if (error) { ASSERT(XFS_FORCED_SHUTDOWN(mp)); xfs_trans_cancel(tp, 0); - return (VN_INACTIVE_CACHE); + return VN_INACTIVE_CACHE; } xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); @@ -1742,7 +1739,7 @@ xfs_inactive( * cancelled, and the inode is unlocked. Just get out. */ if (error) - return (VN_INACTIVE_CACHE); + return VN_INACTIVE_CACHE; } else if (ip->i_afp) { xfs_idestroy_fork(ip, XFS_ATTR_FORK); } @@ -2049,8 +2046,8 @@ std_return: abort_return: cancel_flags |= XFS_TRANS_ABORT; /* FALLTHROUGH */ - error_return: + error_return: if (tp != NULL) xfs_trans_cancel(tp, cancel_flags); @@ -2724,9 +2721,9 @@ std_return: abort_return: cancel_flags |= XFS_TRANS_ABORT; /* FALLTHROUGH */ + error_return: xfs_trans_cancel(tp, cancel_flags); - goto std_return; } /* @@ -3199,10 +3196,12 @@ std_return: } return error; - error1: +error1: xfs_bmap_cancel(&free_list); cancel_flags |= XFS_TRANS_ABORT; - error_return: + /* FALLTHROUGH */ + +error_return: xfs_trans_cancel(tp, cancel_flags); goto std_return; } @@ -3618,9 +3617,9 @@ xfs_rwlock( if (locktype == VRWLOCK_WRITE) { xfs_ilock(ip, XFS_IOLOCK_EXCL); } else if (locktype == VRWLOCK_TRY_READ) { - return (xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)); + return xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED); } else if (locktype == VRWLOCK_TRY_WRITE) { - return (xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL)); + return xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL); } else { ASSERT((locktype == VRWLOCK_READ) || (locktype == VRWLOCK_WRITE_DIRECT)); @@ -3868,7 +3867,7 @@ xfs_finish_reclaim( xfs_ifunlock(ip); xfs_iunlock(ip, XFS_ILOCK_EXCL); } - return(1); + return 1; } ip->i_flags |= XFS_IRECLAIM; write_unlock(&ih->ih_lock); @@ -4045,7 +4044,7 @@ xfs_alloc_file_space( offset, end_dmi_offset - offset, 0, NULL); if (error) - return(error); + return error; } /* @@ -4305,7 +4304,7 @@ xfs_free_file_space( offset, end_dmi_offset - offset, AT_DELAY_FLAG(attr_flags), NULL); if (error) - return(error); + return error; } ASSERT(attr_flags & ATTR_NOLOCK ? attr_flags & ATTR_DMI : 1); -- GitLab From 92c3504e6ee0816d4ea1345a6bd276969224890d Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 15 Jan 2006 02:40:08 +0100 Subject: [PATCH 251/465] Spelling fix in init/Kconfig for the help of CONFIG_SWAP Trivial spelling fix s/socalled/so called/ Signed-off-by: Jesper Juhl Signed-off-by: Adrian Bunk --- init/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/init/Kconfig b/init/Kconfig index 25f4d74adf7..7efa729d2cf 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -99,7 +99,7 @@ config SWAP default y help This option allows you to choose whether you want to have support - for socalled swap devices or swap files in your kernel that are + for so called swap devices or swap files in your kernel that are used to provide more virtual memory than the actual RAM present in your computer. If unsure say Y. -- GitLab From 624dffcbcf87b9c501b13256416a82487be962bc Mon Sep 17 00:00:00 2001 From: Christian Kujau Date: Sun, 15 Jan 2006 02:43:54 +0100 Subject: [PATCH 252/465] correct email address of Manfred Spraul I tried to send the forcedeth maintainer an email, but it came back with: "The mail address manfreds@colorfullife.com is not read anymore. Please resent your mail to manfred@ instead of manfreds@." This patch fixes this. Signed-off-by: Adrian Bunk --- arch/i386/kernel/vm86.c | 2 +- fs/sysv/ChangeLog | 2 +- ipc/msg.c | 2 +- ipc/sem.c | 2 +- ipc/util.c | 2 +- ipc/util.h | 2 +- kernel/printk.c | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c index 0c90ae54ddf..f51c894a7da 100644 --- a/arch/i386/kernel/vm86.c +++ b/arch/i386/kernel/vm86.c @@ -4,7 +4,7 @@ * Copyright (C) 1994 Linus Torvalds * * 29 dec 2001 - Fixed oopses caused by unchecked access to the vm86 - * stack - Manfred Spraul + * stack - Manfred Spraul * * 22 mar 2002 - Manfred detected the stackfaults, but didn't handle * them correctly. Now the emulation will be in a diff --git a/fs/sysv/ChangeLog b/fs/sysv/ChangeLog index 18e3487debd..f403f8b91b8 100644 --- a/fs/sysv/ChangeLog +++ b/fs/sysv/ChangeLog @@ -54,7 +54,7 @@ Fri Jan 4 2002 Alexander Viro (sysv_read_super): Likewise. (v7_read_super): Likewise. -Sun Dec 30 2001 Manfred Spraul +Sun Dec 30 2001 Manfred Spraul * dir.c (dir_commit_chunk): Do not set dir->i_version. (sysv_readdir): Likewise. diff --git a/ipc/msg.c b/ipc/msg.c index a91b64763b8..fbf757064a3 100644 --- a/ipc/msg.c +++ b/ipc/msg.c @@ -12,7 +12,7 @@ * * mostly rewritten, threaded and wake-one semantics added * MSGMAX limit removed, sysctl's added - * (c) 1999 Manfred Spraul + * (c) 1999 Manfred Spraul */ #include diff --git a/ipc/sem.c b/ipc/sem.c index 46bb8a678de..31fd4027d2b 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -56,7 +56,7 @@ * /proc/sysvipc/sem support (c) 1999 Dragos Acostachioaie * * SMP-threaded, sysctl's added - * (c) 1999 Manfred Spraul + * (c) 1999 Manfred Spraul * Enforced range limit on SEM_UNDO * (c) 2001 Red Hat Inc * Lockless wakeup diff --git a/ipc/util.c b/ipc/util.c index 38b9a0af3bd..862621980b0 100644 --- a/ipc/util.c +++ b/ipc/util.c @@ -7,7 +7,7 @@ * Occurs in several places in the IPC code. * Chris Evans, * Nov 1999 - ipc helper functions, unified SMP locking - * Manfred Spraul + * Manfred Spraul * Oct 2002 - One lock per IPC id. RCU ipc_free for lock-free grow_ary(). * Mingming Cao */ diff --git a/ipc/util.h b/ipc/util.h index fc9a28be079..efaff3ee7de 100644 --- a/ipc/util.h +++ b/ipc/util.h @@ -2,7 +2,7 @@ * linux/ipc/util.h * Copyright (C) 1999 Christoph Rohland * - * ipc helper functions (c) 1999 Manfred Spraul + * ipc helper functions (c) 1999 Manfred Spraul */ #ifndef _IPC_UTIL_H diff --git a/kernel/printk.c b/kernel/printk.c index 2251be80cd2..13ced0f7828 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -11,7 +11,7 @@ * Ted Ts'o, 2/11/93. * Modified for sysctl support, 1/8/97, Chris Horn. * Fixed SMP synchronization, 08/08/99, Manfred Spraul - * manfreds@colorfullife.com + * manfred@colorfullife.com * Rewrote bits to get rid of console_lock * 01Mar01 Andrew Morton */ -- GitLab From fb453d4b0b51ea71c9eb8192c61b768afeb7ee8a Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 15 Jan 2006 02:46:48 +0100 Subject: [PATCH 253/465] MAINTAINERS: CIFS: add linux-cifs-client@lists.samba.org list Add linux-cifs-client@lists.samba.org to CIFS entry in MAINTAINERS Signed-off-by: Jesper Juhl Signed-off-by: Adrian Bunk --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 10941b10006..873c3f7cf0f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -549,6 +549,7 @@ S: Maintained COMMON INTERNET FILE SYSTEM (CIFS) P: Steve French M: sfrench@samba.org +L: linux-cifs-client@lists.samba.org L: samba-technical@lists.samba.org W: http://us1.samba.org/samba/Linux_CIFS_client.html T: git kernel.org:/pub/scm/linux/kernel/git/sfrench/cifs-2.6.git -- GitLab From 9216ad8cb7849d88b6d8e9f097718de4f25d4121 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sun, 15 Jan 2006 13:00:08 +1100 Subject: [PATCH 254/465] powerpc/32: Generate miboot images with ARCH=powerpc Miboot images are apparently still used on some old 32-bit powermacs, so build them with ARCH=powerpc if we're 32-bit and powermac support is enabled. Signed-off-by: Paul Mackerras --- arch/powerpc/boot/Makefile | 29 +++++++++++++++++++++++------ arch/powerpc/boot/dummy.c | 4 ++++ 2 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 arch/powerpc/boot/dummy.c diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 788dec4c7ef..840ae595a61 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -27,6 +27,7 @@ BOOTCFLAGS := $(HOSTCFLAGS) -fno-builtin -nostdinc -isystem \ BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc OBJCOPYFLAGS := contents,alloc,load,readonly,data OBJCOPY_COFF_ARGS := -O aixcoff-rs6000 --set-start 0x500000 +OBJCOPY_MIB_ARGS := -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c zlibheader := infblock.h infcodes.h inffast.h inftrees.h infutil.h @@ -90,11 +91,11 @@ gz-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.gz, $(section))) hostprogs-y := addnote addRamDisk hack-coff targets += zImage.vmode zImage.initrd.vmode zImage zImage.initrd \ - zImage.coff zImage.initrd.coff \ + zImage.coff zImage.initrd.coff miboot.image miboot.initrd.image \ $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \ $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \ $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \ - vmlinux.initrd + vmlinux.initrd dummy.o extra-y := initrd.o quiet_cmd_ramdisk = RAMDISK $@ @@ -116,6 +117,10 @@ quiet_cmd_addsection = ADDSEC $@ quiet_cmd_addnote = ADDNOTE $@ cmd_addnote = $(obj)/addnote $@ +quiet_cmd_gen-miboot = GEN $@ + cmd_gen-miboot = $(OBJCOPY) $(OBJCOPY_MIB_ARGS) \ + --add-section=$1=$(word 2, $^) $< $@ + quiet_cmd_gencoff = COFF $@ cmd_gencoff = $(OBJCOPY) $(OBJCOPY_COFF_ARGS) $@ && \ $(obj)/hack-coff $@ @@ -141,19 +146,25 @@ $(obj)/zImage.initrd.vmode $(obj)/zImage.initrd.coff: obj-boot += $(call obj-sec $(obj)/zImage.initrd.vmode: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(srctree)/$(src)/zImage.lds $(call cmd,bootld,$(obj-boot),zImage.lds) -# For 32-bit powermacs, build the COFF images as well as the ELF images. +# For 32-bit powermacs, build the COFF and miboot images +# as well as the ELF images. coffimage-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/zImage.coff coffrdimg-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/zImage.initrd.coff +mibootimg-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/miboot.image +mibrdimg-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/miboot.initrd.image -$(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote $(coffimage-y-y) +$(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote $(coffimage-y-y) \ + $(mibootimg-y-y) @cp -f $< $@ $(call if_changed,addnote) -$(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote $(coffrdimg-y-y) +$(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote \ + $(coffrdimg-y-y) $(mibrdimg-y-y) @cp -f $< $@ $(call if_changed,addnote) -$(obj)/zImage.coff: $(call obj-sec, $(required)) $(obj-boot) $(srctree)/$(src)/zImage.coff.lds $(obj)/hack-coff +$(obj)/zImage.coff: $(call obj-sec, $(required)) $(obj-boot) \ + $(srctree)/$(src)/zImage.coff.lds $(obj)/hack-coff $(call cmd,bootld,$(obj-boot),zImage.coff.lds) $(call cmd,gencoff) @@ -162,6 +173,12 @@ $(obj)/zImage.initrd.coff: $(call obj-sec, $(required) $(initrd)) $(obj-boot) \ $(call cmd,bootld,$(obj-boot),zImage.coff.lds) $(call cmd,gencoff) +$(obj)/miboot.image: $(obj)/dummy.o $(obj)/vmlinux.gz + $(call cmd,gen-miboot,image) + +$(obj)/miboot.initrd.image: $(obj)/miboot.image $(images)/ramdisk.image.gz + $(call cmd,gen-miboot,initrd) + #----------------------------------------------------------- # build u-boot images #----------------------------------------------------------- diff --git a/arch/powerpc/boot/dummy.c b/arch/powerpc/boot/dummy.c new file mode 100644 index 00000000000..31dbf45bf99 --- /dev/null +++ b/arch/powerpc/boot/dummy.c @@ -0,0 +1,4 @@ +int main(void) +{ + return 0; +} -- GitLab From 8385a6a3acfbb4b68150c25cfe9084b6c4f501cf Mon Sep 17 00:00:00 2001 From: Haren Myneni Date: Fri, 13 Jan 2006 19:15:36 -0800 Subject: [PATCH 255/465] [PATCH] powerpc: Fix kdump copy regs and dynamic allocate per-cpu crash notes - This contains the arch specific changes for the following the kdump generic fixes which were already accepted in the upstream. . Capturing CPU registers (for the case of 'panic' and invoking the dump using 'sysrq-trigger') from a function (stack frame) which will be not be available during the kdump boot. Hence, might result in invalid stack trace. . Dynamically allocating per cpu ELF notes section instead of statically for NR_CPUS. - Fix the compiler warning in prom_init.c. Signed-off-by: Haren Myneni Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/crash.c | 77 ++--------------------------- arch/powerpc/kernel/prom_init.c | 3 +- include/asm-powerpc/kexec.h | 85 ++++++++++++++++++++++++++++----- 3 files changed, 80 insertions(+), 85 deletions(-) diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c index 5f248e3fdf8..8c21d378f5d 100644 --- a/arch/powerpc/kernel/crash.c +++ b/arch/powerpc/kernel/crash.c @@ -84,7 +84,10 @@ static void crash_save_this_cpu(struct pt_regs *regs, int cpu) * squirrelled away. ELF notes happen to provide * all of that that no need to invent something new. */ - buf = &crash_notes[cpu][0]; + buf = (u32*)per_cpu_ptr(crash_notes, cpu); + if (!buf) + return; + memset(&prstatus, 0, sizeof(prstatus)); prstatus.pr_pid = current->pid; elf_core_copy_regs(&prstatus.pr_reg, regs); @@ -93,76 +96,6 @@ static void crash_save_this_cpu(struct pt_regs *regs, int cpu) final_note(buf); } -/* FIXME Merge this with xmon_save_regs ?? */ -static inline void crash_get_current_regs(struct pt_regs *regs) -{ - unsigned long tmp1, tmp2; - - __asm__ __volatile__ ( - "std 0,0(%2)\n" - "std 1,8(%2)\n" - "std 2,16(%2)\n" - "std 3,24(%2)\n" - "std 4,32(%2)\n" - "std 5,40(%2)\n" - "std 6,48(%2)\n" - "std 7,56(%2)\n" - "std 8,64(%2)\n" - "std 9,72(%2)\n" - "std 10,80(%2)\n" - "std 11,88(%2)\n" - "std 12,96(%2)\n" - "std 13,104(%2)\n" - "std 14,112(%2)\n" - "std 15,120(%2)\n" - "std 16,128(%2)\n" - "std 17,136(%2)\n" - "std 18,144(%2)\n" - "std 19,152(%2)\n" - "std 20,160(%2)\n" - "std 21,168(%2)\n" - "std 22,176(%2)\n" - "std 23,184(%2)\n" - "std 24,192(%2)\n" - "std 25,200(%2)\n" - "std 26,208(%2)\n" - "std 27,216(%2)\n" - "std 28,224(%2)\n" - "std 29,232(%2)\n" - "std 30,240(%2)\n" - "std 31,248(%2)\n" - "mfmsr %0\n" - "std %0, 264(%2)\n" - "mfctr %0\n" - "std %0, 280(%2)\n" - "mflr %0\n" - "std %0, 288(%2)\n" - "bl 1f\n" - "1: mflr %1\n" - "std %1, 256(%2)\n" - "mtlr %0\n" - "mfxer %0\n" - "std %0, 296(%2)\n" - : "=&r" (tmp1), "=&r" (tmp2) - : "b" (regs)); -} - -/* We may have saved_regs from where the error came from - * or it is NULL if via a direct panic(). - */ -static void crash_save_self(struct pt_regs *saved_regs) -{ - struct pt_regs regs; - int cpu; - - cpu = smp_processor_id(); - if (saved_regs) - memcpy(®s, saved_regs, sizeof(regs)); - else - crash_get_current_regs(®s); - crash_save_this_cpu(®s, cpu); -} - #ifdef CONFIG_SMP static atomic_t waiting_for_crash_ipi; @@ -260,5 +193,5 @@ void default_machine_crash_shutdown(struct pt_regs *regs) */ crashing_cpu = smp_processor_id(); crash_kexec_prepare_cpus(); - crash_save_self(regs); + crash_save_this_cpu(regs, crashing_cpu); } diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index d963a12ec64..7881ec96ef1 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -605,7 +605,8 @@ static void __init early_cmdline_parse(void) opt = strstr(RELOC(prom_cmd_line), RELOC("crashkernel=")); if (opt) { opt += 12; - RELOC(prom_crashk_size) = prom_memparse(opt, &opt); + RELOC(prom_crashk_size) = + prom_memparse(opt, (const char **)&opt); if (ALIGN(RELOC(prom_crashk_size), 0x1000000) != RELOC(prom_crashk_size)) { diff --git a/include/asm-powerpc/kexec.h b/include/asm-powerpc/kexec.h index fffdf690b84..640a6459f2f 100644 --- a/include/asm-powerpc/kexec.h +++ b/include/asm-powerpc/kexec.h @@ -31,12 +31,80 @@ #define KEXEC_ARCH KEXEC_ARCH_PPC #endif -#define HAVE_ARCH_COPY_OLDMEM_PAGE - -#ifndef __ASSEMBLY__ - #ifdef CONFIG_KEXEC +#ifdef __powerpc64__ +/* + * This function is responsible for capturing register states if coming + * via panic or invoking dump using sysrq-trigger. + */ +static inline void crash_setup_regs(struct pt_regs *newregs, + struct pt_regs *oldregs) +{ + if (oldregs) + memcpy(newregs, oldregs, sizeof(*newregs)); + else { + /* FIXME Merge this with xmon_save_regs ?? */ + unsigned long tmp1, tmp2; + __asm__ __volatile__ ( + "std 0,0(%2)\n" + "std 1,8(%2)\n" + "std 2,16(%2)\n" + "std 3,24(%2)\n" + "std 4,32(%2)\n" + "std 5,40(%2)\n" + "std 6,48(%2)\n" + "std 7,56(%2)\n" + "std 8,64(%2)\n" + "std 9,72(%2)\n" + "std 10,80(%2)\n" + "std 11,88(%2)\n" + "std 12,96(%2)\n" + "std 13,104(%2)\n" + "std 14,112(%2)\n" + "std 15,120(%2)\n" + "std 16,128(%2)\n" + "std 17,136(%2)\n" + "std 18,144(%2)\n" + "std 19,152(%2)\n" + "std 20,160(%2)\n" + "std 21,168(%2)\n" + "std 22,176(%2)\n" + "std 23,184(%2)\n" + "std 24,192(%2)\n" + "std 25,200(%2)\n" + "std 26,208(%2)\n" + "std 27,216(%2)\n" + "std 28,224(%2)\n" + "std 29,232(%2)\n" + "std 30,240(%2)\n" + "std 31,248(%2)\n" + "mfmsr %0\n" + "std %0, 264(%2)\n" + "mfctr %0\n" + "std %0, 280(%2)\n" + "mflr %0\n" + "std %0, 288(%2)\n" + "bl 1f\n" + "1: mflr %1\n" + "std %1, 256(%2)\n" + "mtlr %0\n" + "mfxer %0\n" + "std %0, 296(%2)\n" + : "=&r" (tmp1), "=&r" (tmp2) + : "b" (newregs)); + } +} +#else +/* + * Provide a dummy definition to avoid build failures. Will remain + * empty till crash dump support is enabled. + */ +static inline void crash_setup_regs(struct pt_regs *newregs, + struct pt_regs *oldregs) { } +#endif /* !__powerpc64 __ */ + +#ifndef __ASSEMBLY__ #define MAX_NOTE_BYTES 1024 #ifdef __powerpc64__ @@ -53,14 +121,7 @@ extern void default_machine_kexec(struct kimage *image); extern int default_machine_kexec_prepare(struct kimage *image); extern void default_machine_crash_shutdown(struct pt_regs *regs); -#endif /* !CONFIG_KEXEC */ - -/* - * Provide a dummy definition to avoid build failures. Will remain - * empty till crash dump support is enabled. - */ -static inline void crash_setup_regs(struct pt_regs *newregs, - struct pt_regs *oldregs) { } #endif /* ! __ASSEMBLY__ */ +#endif /* CONFIG_KEXEC */ #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_KEXEC_H */ -- GitLab From 4c882b019160ebd7e954ba787f6353ed69281fd7 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sat, 14 Jan 2006 16:35:35 +1100 Subject: [PATCH 256/465] [PATCH] powerpc: Fix Maple build The changes to the device node structure broke Maple build. This fixes it. Unfortunately I coudn't test as my Maple board appears to be dead. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/maple/pci.c | 1 - arch/powerpc/platforms/maple/setup.c | 85 ++++++++++++++++------------ arch/powerpc/platforms/maple/time.c | 23 ++++++-- 3 files changed, 68 insertions(+), 41 deletions(-) diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c index f40451da037..7d4099a34f9 100644 --- a/arch/powerpc/platforms/maple/pci.c +++ b/arch/powerpc/platforms/maple/pci.c @@ -316,7 +316,6 @@ static int __init add_bridge(struct device_node *dev) char* disp_name; int *bus_range; int primary = 1; - struct property *of_prop; DBG("Adding PCI host bridge %s\n", dev->full_name); diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index a1cb4d23672..ec5c1e10c40 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c @@ -71,38 +71,60 @@ #define DBG(fmt...) #endif +static unsigned long maple_find_nvram_base(void) +{ + struct device_node *rtcs; + unsigned long result = 0; + + /* find NVRAM device */ + rtcs = of_find_compatible_node(NULL, "nvram", "AMD8111"); + if (rtcs) { + struct resource r; + if (of_address_to_resource(rtcs, 0, &r)) { + printk(KERN_EMERG "Maple: Unable to translate NVRAM" + " address\n"); + goto bail; + } + if (!(r.flags & IORESOURCE_IO)) { + printk(KERN_EMERG "Maple: NVRAM address isn't PIO!\n"); + goto bail; + } + result = r.start; + } else + printk(KERN_EMERG "Maple: Unable to find NVRAM\n"); + bail: + of_node_put(rtcs); + return result; +} + static void maple_restart(char *cmd) { unsigned int maple_nvram_base; unsigned int maple_nvram_offset; unsigned int maple_nvram_command; - struct device_node *rtcs; + struct device_node *sp; - /* find NVRAM device */ - rtcs = find_compatible_devices("nvram", "AMD8111"); - if (rtcs && rtcs->addrs) { - maple_nvram_base = rtcs->addrs[0].address; - } else { - printk(KERN_EMERG "Maple: Unable to find NVRAM\n"); - printk(KERN_EMERG "Maple: Manual Restart Required\n"); - return; - } + maple_nvram_base = maple_find_nvram_base(); + if (maple_nvram_base == 0) + goto fail; /* find service processor device */ - rtcs = find_devices("service-processor"); - if (!rtcs) { + sp = of_find_node_by_name(NULL, "service-processor"); + if (!sp) { printk(KERN_EMERG "Maple: Unable to find Service Processor\n"); - printk(KERN_EMERG "Maple: Manual Restart Required\n"); - return; + goto fail; } - maple_nvram_offset = *(unsigned int*) get_property(rtcs, + maple_nvram_offset = *(unsigned int*) get_property(sp, "restart-addr", NULL); - maple_nvram_command = *(unsigned int*) get_property(rtcs, + maple_nvram_command = *(unsigned int*) get_property(sp, "restart-value", NULL); + of_node_put(sp); /* send command */ outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset); for (;;) ; + fail: + printk(KERN_EMERG "Maple: Manual Restart Required\n"); } static void maple_power_off(void) @@ -110,33 +132,29 @@ static void maple_power_off(void) unsigned int maple_nvram_base; unsigned int maple_nvram_offset; unsigned int maple_nvram_command; - struct device_node *rtcs; + struct device_node *sp; - /* find NVRAM device */ - rtcs = find_compatible_devices("nvram", "AMD8111"); - if (rtcs && rtcs->addrs) { - maple_nvram_base = rtcs->addrs[0].address; - } else { - printk(KERN_EMERG "Maple: Unable to find NVRAM\n"); - printk(KERN_EMERG "Maple: Manual Power-Down Required\n"); - return; - } + maple_nvram_base = maple_find_nvram_base(); + if (maple_nvram_base == 0) + goto fail; /* find service processor device */ - rtcs = find_devices("service-processor"); - if (!rtcs) { + sp = of_find_node_by_name(NULL, "service-processor"); + if (!sp) { printk(KERN_EMERG "Maple: Unable to find Service Processor\n"); - printk(KERN_EMERG "Maple: Manual Power-Down Required\n"); - return; + goto fail; } - maple_nvram_offset = *(unsigned int*) get_property(rtcs, + maple_nvram_offset = *(unsigned int*) get_property(sp, "power-off-addr", NULL); - maple_nvram_command = *(unsigned int*) get_property(rtcs, + maple_nvram_command = *(unsigned int*) get_property(sp, "power-off-value", NULL); + of_node_put(sp); /* send command */ outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset); for (;;) ; + fail: + printk(KERN_EMERG "Maple: Manual Power-Down Required\n"); } static void maple_halt(void) @@ -179,9 +197,6 @@ void __init maple_setup_arch(void) */ static void __init maple_init_early(void) { - unsigned int default_speed; - u64 physport; - DBG(" -> maple_init_early\n"); /* Initialize hash table, from now on, we can take hash faults diff --git a/arch/powerpc/platforms/maple/time.c b/arch/powerpc/platforms/maple/time.c index 15846cc938a..50bc4eb8535 100644 --- a/arch/powerpc/platforms/maple/time.c +++ b/arch/powerpc/platforms/maple/time.c @@ -168,11 +168,24 @@ unsigned long __init maple_get_boot_time(void) struct rtc_time tm; struct device_node *rtcs; - rtcs = find_compatible_devices("rtc", "pnpPNP,b00"); - if (rtcs && rtcs->addrs) { - maple_rtc_addr = rtcs->addrs[0].address; - printk(KERN_INFO "Maple: Found RTC at 0x%x\n", maple_rtc_addr); - } else { + rtcs = of_find_compatible_node(NULL, "rtc", "pnpPNP,b00"); + if (rtcs) { + struct resource r; + if (of_address_to_resource(rtcs, 0, &r)) { + printk(KERN_EMERG "Maple: Unable to translate RTC" + " address\n"); + goto bail; + } + if (!(r.flags & IORESOURCE_IO)) { + printk(KERN_EMERG "Maple: RTC address isn't PIO!\n"); + goto bail; + } + maple_rtc_addr = r.start; + printk(KERN_INFO "Maple: Found RTC at IO 0x%x\n", + maple_rtc_addr); + } + bail: + if (maple_rtc_addr == 0) { maple_rtc_addr = RTC_PORT(0); /* legacy address */ printk(KERN_INFO "Maple: No device node for RTC, assuming " "legacy address (0x%x)\n", maple_rtc_addr); -- GitLab From faf3a98918aa5f14a29e0d246e194be58b9357f0 Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Sat, 14 Jan 2006 13:20:37 -0800 Subject: [PATCH 257/465] [PATCH] autofs4 oops fix We forgot to initialise a couple of nameidata fields. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/autofs4/root.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index e93a7ae467c..62d8d4acb8b 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -195,6 +195,8 @@ static int autofs4_dir_open(struct inode *inode, struct file *file) if (!empty) d_invalidate(dentry); + nd.dentry = dentry; + nd.mnt = mnt; nd.flags = LOOKUP_DIRECTORY; status = (dentry->d_op->d_revalidate)(dentry, &nd); -- GitLab From 7170be5f586b59bdcdab082778a5d9203ba7b667 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Sat, 14 Jan 2006 13:20:38 -0800 Subject: [PATCH 258/465] [PATCH] convert /proc/devices to use seq_file interface A Christoph suggested that the /proc/devices file be converted to use the seq_file interface. This patch does that. I've obxerved one or two installation that had sufficiently large sans that they overran the 4k limit on /proc/devices. Signed-off-by: Neil Horman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- block/genhd.c | 106 +++++++++++++++++++++++------ fs/char_dev.c | 96 +++++++++++++++++++------- fs/proc/proc_misc.c | 160 +++++++++++++++++++++++++++++++++++++++++--- include/linux/fs.h | 11 +++ 4 files changed, 320 insertions(+), 53 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index f1ed83f3f08..db57546a709 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -38,34 +38,100 @@ static inline int major_to_index(int major) return major % MAX_PROBE_HASH; } -#ifdef CONFIG_PROC_FS -/* get block device names in somewhat random order */ -int get_blkdev_list(char *p, int used) +struct blkdev_info { + int index; + struct blk_major_name *bd; +}; + +/* + * iterate over a list of blkdev_info structures. allows + * the major_names array to be iterated over from outside this file + * must be called with the block_subsys_sem held + */ +void *get_next_blkdev(void *dev) +{ + struct blkdev_info *info; + + if (dev == NULL) { + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (!info) + goto out; + info->index=0; + info->bd = major_names[info->index]; + if (info->bd) + goto out; + } else { + info = dev; + } + + while (info->index < ARRAY_SIZE(major_names)) { + if (info->bd) + info->bd = info->bd->next; + if (info->bd) + goto out; + /* + * No devices on this chain, move to the next + */ + info->index++; + info->bd = (info->index < ARRAY_SIZE(major_names)) ? + major_names[info->index] : NULL; + if (info->bd) + goto out; + } + +out: + return info; +} + +void *acquire_blkdev_list(void) +{ + down(&block_subsys_sem); + return get_next_blkdev(NULL); +} + +void release_blkdev_list(void *dev) +{ + up(&block_subsys_sem); + kfree(dev); +} + + +/* + * Count the number of records in the blkdev_list. + * must be called with the block_subsys_sem held + */ +int count_blkdev_list(void) { struct blk_major_name *n; - int i, len; + int i, count; - len = snprintf(p, (PAGE_SIZE-used), "\nBlock devices:\n"); + count = 0; - down(&block_subsys_sem); for (i = 0; i < ARRAY_SIZE(major_names); i++) { - for (n = major_names[i]; n; n = n->next) { - /* - * If the curent string plus the 5 extra characters - * in the line would run us off the page, then we're done - */ - if ((len + used + strlen(n->name) + 5) >= PAGE_SIZE) - goto page_full; - len += sprintf(p+len, "%3d %s\n", - n->major, n->name); - } + for (n = major_names[i]; n; n = n->next) + count++; } -page_full: - up(&block_subsys_sem); - return len; + return count; } -#endif + +/* + * extract the major and name values from a blkdev_info struct + * passed in as a void to *dev. Must be called with + * block_subsys_sem held + */ +int get_blkdev_info(void *dev, int *major, char **name) +{ + struct blkdev_info *info = dev; + + if (info->bd == NULL) + return 1; + + *major = info->bd->major; + *name = info->bd->name; + return 0; +} + int register_blkdev(unsigned int major, const char *name) { diff --git a/fs/char_dev.c b/fs/char_dev.c index 3b1b1eefdbb..21195c48163 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c @@ -35,7 +35,7 @@ static struct char_device_struct { unsigned int major; unsigned int baseminor; int minorct; - const char *name; + char name[64]; struct file_operations *fops; struct cdev *cdev; /* will die */ } *chrdevs[MAX_PROBE_HASH]; @@ -46,34 +46,84 @@ static inline int major_to_index(int major) return major % MAX_PROBE_HASH; } -/* get char device names in somewhat random order */ -int get_chrdev_list(char *page) -{ +struct chrdev_info { + int index; struct char_device_struct *cd; - int i, len; +}; - len = sprintf(page, "Character devices:\n"); +void *get_next_chrdev(void *dev) +{ + struct chrdev_info *info; + if (dev == NULL) { + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (!info) + goto out; + info->index=0; + info->cd = chrdevs[info->index]; + if (info->cd) + goto out; + } else { + info = dev; + } + + while (info->index < ARRAY_SIZE(chrdevs)) { + if (info->cd) + info->cd = info->cd->next; + if (info->cd) + goto out; + /* + * No devices on this chain, move to the next + */ + info->index++; + info->cd = (info->index < ARRAY_SIZE(chrdevs)) ? + chrdevs[info->index] : NULL; + if (info->cd) + goto out; + } + +out: + return info; +} + +void *acquire_chrdev_list(void) +{ down(&chrdevs_lock); + return get_next_chrdev(NULL); +} + +void release_chrdev_list(void *dev) +{ + up(&chrdevs_lock); + kfree(dev); +} + + +int count_chrdev_list(void) +{ + struct char_device_struct *cd; + int i, count; + + count = 0; + for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) { - for (cd = chrdevs[i]; cd; cd = cd->next) { - /* - * if the current name, plus the 5 extra characters - * in the device line for this entry - * would run us off the page, we're done - */ - if ((len+strlen(cd->name) + 5) >= PAGE_SIZE) - goto page_full; - - - len += sprintf(page+len, "%3d %s\n", - cd->major, cd->name); - } + for (cd = chrdevs[i]; cd; cd = cd->next) + count++; } -page_full: - up(&chrdevs_lock); - return len; + return count; +} + +int get_chrdev_info(void *dev, int *major, char **name) +{ + struct chrdev_info *info = dev; + + if (info->cd == NULL) + return 1; + + *major = info->cd->major; + *name = info->cd->name; + return 0; } /* @@ -121,7 +171,7 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor, cd->major = major; cd->baseminor = baseminor; cd->minorct = minorct; - cd->name = name; + strncpy(cd->name,name, 64); i = major_to_index(major); diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index 63bf6c00fa0..8f8014285a3 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -62,7 +63,6 @@ */ extern int get_hardware_list(char *); extern int get_stram_list(char *); -extern int get_chrdev_list(char *); extern int get_filesystem_list(char *); extern int get_exec_domain_list(char *); extern int get_dma_list(char *); @@ -248,6 +248,154 @@ static int cpuinfo_open(struct inode *inode, struct file *file) { return seq_open(file, &cpuinfo_op); } + +enum devinfo_states { + CHR_HDR, + CHR_LIST, + BLK_HDR, + BLK_LIST, + DEVINFO_DONE +}; + +struct devinfo_state { + void *chrdev; + void *blkdev; + unsigned int num_records; + unsigned int cur_record; + enum devinfo_states state; +}; + +static void *devinfo_start(struct seq_file *f, loff_t *pos) +{ + struct devinfo_state *info = f->private; + + if (*pos) { + if ((info) && (*pos <= info->num_records)) + return info; + return NULL; + } + info = kmalloc(sizeof(*info), GFP_KERNEL); + f->private = info; + info->chrdev = acquire_chrdev_list(); + info->blkdev = acquire_blkdev_list(); + info->state = CHR_HDR; + info->num_records = count_chrdev_list(); + info->num_records += count_blkdev_list(); + info->num_records += 2; /* Character and Block headers */ + *pos = 1; + info->cur_record = *pos; + return info; +} + +static void *devinfo_next(struct seq_file *f, void *v, loff_t *pos) +{ + int idummy; + char *ndummy; + struct devinfo_state *info = f->private; + + switch (info->state) { + case CHR_HDR: + info->state = CHR_LIST; + (*pos)++; + /*fallthrough*/ + case CHR_LIST: + if (get_chrdev_info(info->chrdev,&idummy,&ndummy)) { + /* + * The character dev list is complete + */ + info->state = BLK_HDR; + } else { + info->chrdev = get_next_chrdev(info->chrdev); + } + (*pos)++; + break; + case BLK_HDR: + info->state = BLK_LIST; + (*pos)++; + break; + case BLK_LIST: + if (get_blkdev_info(info->blkdev,&idummy,&ndummy)) { + /* + * The block dev list is complete + */ + info->state = DEVINFO_DONE; + } else { + info->blkdev = get_next_blkdev(info->blkdev); + } + (*pos)++; + break; + case DEVINFO_DONE: + (*pos)++; + info->cur_record = *pos; + info = NULL; + break; + default: + break; + } + if (info) + info->cur_record = *pos; + return info; +} + +static void devinfo_stop(struct seq_file *f, void *v) +{ + struct devinfo_state *info = f->private; + + if (info) { + release_chrdev_list(info->chrdev); + release_blkdev_list(info->blkdev); + f->private = NULL; + kfree(info); + } +} + +static int devinfo_show(struct seq_file *f, void *arg) +{ + int major; + char *name; + struct devinfo_state *info = f->private; + + switch(info->state) { + case CHR_HDR: + seq_printf(f,"Character devices:\n"); + /* fallthrough */ + case CHR_LIST: + if (!get_chrdev_info(info->chrdev,&major,&name)) + seq_printf(f,"%3d %s\n",major,name); + break; + case BLK_HDR: + seq_printf(f,"\nBlock devices:\n"); + /* fallthrough */ + case BLK_LIST: + if (!get_blkdev_info(info->blkdev,&major,&name)) + seq_printf(f,"%3d %s\n",major,name); + break; + default: + break; + } + + return 0; +} + +static struct seq_operations devinfo_op = { + .start = devinfo_start, + .next = devinfo_next, + .stop = devinfo_stop, + .show = devinfo_show, +}; + +static int devinfo_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &devinfo_op); +} + +static struct file_operations proc_devinfo_operations = { + .open = devinfo_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + static struct file_operations proc_cpuinfo_operations = { .open = cpuinfo_open, .read = seq_read, @@ -450,14 +598,6 @@ static struct file_operations proc_stat_operations = { .release = single_release, }; -static int devices_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len = get_chrdev_list(page); - len += get_blkdev_list(page+len, len); - return proc_calc_metrics(page, start, off, count, eof, len); -} - /* * /proc/interrupts */ @@ -582,7 +722,6 @@ void __init proc_misc_init(void) #ifdef CONFIG_STRAM_PROC {"stram", stram_read_proc}, #endif - {"devices", devices_read_proc}, {"filesystems", filesystems_read_proc}, {"cmdline", cmdline_read_proc}, {"locks", locks_read_proc}, @@ -598,6 +737,7 @@ void __init proc_misc_init(void) entry = create_proc_entry("kmsg", S_IRUSR, &proc_root); if (entry) entry->proc_fops = &proc_kmsg_operations; + create_seq_entry("devices", 0, &proc_devinfo_operations); create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations); create_seq_entry("partitions", 0, &proc_partitions_operations); create_seq_entry("stat", 0, &proc_stat_operations); diff --git a/include/linux/fs.h b/include/linux/fs.h index d1e370d25f7..552cedfa606 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1383,6 +1383,12 @@ extern int register_chrdev(unsigned int, const char *, extern int unregister_chrdev(unsigned int, const char *); extern void unregister_chrdev_region(dev_t, unsigned); extern int chrdev_open(struct inode *, struct file *); +extern int get_chrdev_list(char *); +extern void *acquire_chrdev_list(void); +extern int count_chrdev_list(void); +extern void *get_next_chrdev(void *); +extern int get_chrdev_info(void *, int *, char **); +extern void release_chrdev_list(void *); /* fs/block_dev.c */ #define BDEVNAME_SIZE 32 /* Largest string for a blockdev identifier */ @@ -1391,6 +1397,11 @@ extern const char *bdevname(struct block_device *bdev, char *buffer); extern struct block_device *lookup_bdev(const char *); extern struct block_device *open_bdev_excl(const char *, int, void *); extern void close_bdev_excl(struct block_device *); +extern void *acquire_blkdev_list(void); +extern int count_blkdev_list(void); +extern void *get_next_blkdev(void *); +extern int get_blkdev_info(void *, int *, char **); +extern void release_blkdev_list(void *); extern void init_special_inode(struct inode *, umode_t, dev_t); -- GitLab From 2d0cfb527944c2cfee2cffab14f52d483e329fcf Mon Sep 17 00:00:00 2001 From: Patrick Gefre Date: Sat, 14 Jan 2006 13:20:40 -0800 Subject: [PATCH 259/465] [PATCH] Altix: ioc3 serial support Add driver support for a 2 port PCI IOC3-based serial card on Altix boxes: This is a re-submission. On the original submission I was asked to organize the code so that the MIPS ioc3 ethernet and serial parts could be used with this driver. Stanislaw Skowronek was kind enough to provide the shim layer for this - thanks Stanislaw. This patch includes the shim layer and the Altix PCI ioc3 serial driver. The MIPS merged ioc3 ethernet and serial support is forthcoming. Signed-off-by: Patrick Gefre Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ia64/configs/gensparse_defconfig | 2 + arch/ia64/configs/sn2_defconfig | 2 + drivers/serial/Kconfig | 9 +- drivers/serial/Makefile | 1 + drivers/serial/ioc3_serial.c | 2197 +++++++++++++++++++++++++ drivers/sn/Kconfig | 14 + drivers/sn/Makefile | 1 + drivers/sn/ioc3.c | 851 ++++++++++ include/asm-ia64/sn/ioc3.h | 241 +++ include/linux/ioc3.h | 93 ++ 10 files changed, 3410 insertions(+), 1 deletion(-) create mode 100644 drivers/serial/ioc3_serial.c create mode 100644 drivers/sn/ioc3.c create mode 100644 include/asm-ia64/sn/ioc3.h create mode 100644 include/linux/ioc3.h diff --git a/arch/ia64/configs/gensparse_defconfig b/arch/ia64/configs/gensparse_defconfig index 80f8663bc6d..1d07d8072ec 100644 --- a/arch/ia64/configs/gensparse_defconfig +++ b/arch/ia64/configs/gensparse_defconfig @@ -701,6 +701,7 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_SERIAL_SGI_L1_CONSOLE=y # CONFIG_SERIAL_JSM is not set CONFIG_SERIAL_SGI_IOC4=y +CONFIG_SERIAL_SGI_IOC3=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -1046,6 +1047,7 @@ CONFIG_INFINIBAND_IPOIB=m # SN Devices # CONFIG_SGI_IOC4=y +CONFIG_SGI_IOC3=y # # File systems diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig index ff8bb3770c9..3cb503b659e 100644 --- a/arch/ia64/configs/sn2_defconfig +++ b/arch/ia64/configs/sn2_defconfig @@ -659,6 +659,7 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_SERIAL_SGI_L1_CONSOLE=y # CONFIG_SERIAL_JSM is not set CONFIG_SERIAL_SGI_IOC4=y +CONFIG_SERIAL_SGI_IOC3=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -899,6 +900,7 @@ CONFIG_INFINIBAND_SRP=m # SN Devices # CONFIG_SGI_IOC4=y +CONFIG_SGI_IOC3=y # # File systems diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 843717275d4..e0685a52051 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -190,7 +190,6 @@ config SERIAL_8250_BOCA To compile this driver as a module, choose M here: the module will be called 8250_boca. - config SERIAL_8250_HUB6 tristate "Support Hub6 cards" depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS @@ -917,4 +916,12 @@ config SERIAL_SGI_IOC4 and wish to use the serial ports on this card, say Y. Otherwise, say N. +config SERIAL_SGI_IOC3 + tristate "SGI Altix IOC3 serial support" + depends on (IA64_GENERIC || IA64_SGI_SN2) && SGI_IOC3 + select SERIAL_CORE + help + If you have an SGI Altix with an IOC3 serial card, + say Y or M. Otherwise, say N. + endmenu diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 24a583e482b..eaf8e01db19 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -56,4 +56,5 @@ obj-$(CONFIG_SERIAL_JSM) += jsm/ obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o +obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o obj-$(CONFIG_SERIAL_AT91) += at91_serial.o diff --git a/drivers/serial/ioc3_serial.c b/drivers/serial/ioc3_serial.c new file mode 100644 index 00000000000..8097cd91f16 --- /dev/null +++ b/drivers/serial/ioc3_serial.c @@ -0,0 +1,2197 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2005 Silicon Graphics, Inc. All Rights Reserved. + */ + +/* + * This file contains a module version of the ioc3 serial driver. This + * includes all the support functions needed (support functions, etc.) + * and the serial driver itself. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Interesting things about the ioc3 + */ + +#define LOGICAL_PORTS 2 /* rs232(0) and rs422(1) */ +#define PORTS_PER_CARD 2 +#define LOGICAL_PORTS_PER_CARD (PORTS_PER_CARD * LOGICAL_PORTS) +#define MAX_CARDS 8 +#define MAX_LOGICAL_PORTS (LOGICAL_PORTS_PER_CARD * MAX_CARDS) + +/* determine given the sio_ir what port it applies to */ +#define GET_PORT_FROM_SIO_IR(_x) (_x & SIO_IR_SA) ? 0 : 1 + + +/* + * we have 2 logical ports (rs232, rs422) for each physical port + * evens are rs232, odds are rs422 + */ +#define GET_PHYSICAL_PORT(_x) ((_x) >> 1) +#define GET_LOGICAL_PORT(_x) ((_x) & 1) +#define IS_PHYSICAL_PORT(_x) !((_x) & 1) +#define IS_RS232(_x) !((_x) & 1) + +static unsigned int Num_of_ioc3_cards; +static unsigned int Submodule_slot; + +/* defining this will get you LOTS of great debug info */ +//#define DEBUG_INTERRUPTS +#define DPRINT_CONFIG(_x...) ; +//#define DPRINT_CONFIG(_x...) printk _x +#define NOT_PROGRESS() ; +//#define NOT_PROGRESS() printk("%s : fails %d\n", __FUNCTION__, __LINE__) + +/* number of characters we want to transmit to the lower level at a time */ +#define MAX_CHARS 256 +#define FIFO_SIZE (MAX_CHARS-1) /* it's a uchar */ + +/* Device name we're using */ +#define DEVICE_NAME "ttySIOC" +#define DEVICE_MAJOR 204 +#define DEVICE_MINOR 116 + +/* flags for next_char_state */ +#define NCS_BREAK 0x1 +#define NCS_PARITY 0x2 +#define NCS_FRAMING 0x4 +#define NCS_OVERRUN 0x8 + +/* cause we need SOME parameters ... */ +#define MIN_BAUD_SUPPORTED 1200 +#define MAX_BAUD_SUPPORTED 115200 + +/* protocol types supported */ +#define PROTO_RS232 0 +#define PROTO_RS422 1 + +/* Notification types */ +#define N_DATA_READY 0x01 +#define N_OUTPUT_LOWAT 0x02 +#define N_BREAK 0x04 +#define N_PARITY_ERROR 0x08 +#define N_FRAMING_ERROR 0x10 +#define N_OVERRUN_ERROR 0x20 +#define N_DDCD 0x40 +#define N_DCTS 0x80 + +#define N_ALL_INPUT (N_DATA_READY | N_BREAK \ + | N_PARITY_ERROR | N_FRAMING_ERROR \ + | N_OVERRUN_ERROR | N_DDCD | N_DCTS) + +#define N_ALL_OUTPUT N_OUTPUT_LOWAT + +#define N_ALL_ERRORS (N_PARITY_ERROR | N_FRAMING_ERROR \ + | N_OVERRUN_ERROR) + +#define N_ALL (N_DATA_READY | N_OUTPUT_LOWAT | N_BREAK \ + | N_PARITY_ERROR | N_FRAMING_ERROR \ + | N_OVERRUN_ERROR | N_DDCD | N_DCTS) + +#define SER_CLK_SPEED(prediv) ((22000000 << 1) / prediv) +#define SER_DIVISOR(x, clk) (((clk) + (x) * 8) / ((x) * 16)) +#define DIVISOR_TO_BAUD(div, clk) ((clk) / 16 / (div)) + +/* Some masks */ +#define LCR_MASK_BITS_CHAR (UART_LCR_WLEN5 | UART_LCR_WLEN6 \ + | UART_LCR_WLEN7 | UART_LCR_WLEN8) +#define LCR_MASK_STOP_BITS (UART_LCR_STOP) + +#define PENDING(_a, _p) (readl(&(_p)->vma->sio_ir) & (_a)->ic_enable) + +#define RING_BUF_SIZE 4096 +#define BUF_SIZE_BIT SBBR_L_SIZE +#define PROD_CONS_MASK PROD_CONS_PTR_4K + +#define TOTAL_RING_BUF_SIZE (RING_BUF_SIZE * 4) + +/* driver specific - one per card */ +struct ioc3_card { + struct { + /* uart ports are allocated here */ + struct uart_port icp_uart_port[LOGICAL_PORTS]; + /* the ioc3_port used for this port */ + struct ioc3_port *icp_port; + } ic_port[PORTS_PER_CARD]; + /* currently enabled interrupts */ + uint32_t ic_enable; +}; + +/* Local port info for each IOC3 serial port */ +struct ioc3_port { + /* handy reference material */ + struct uart_port *ip_port; + struct ioc3_card *ip_card; + struct ioc3_driver_data *ip_idd; + struct ioc3_submodule *ip_is; + + /* pci mem addresses for this port */ + struct ioc3_serialregs __iomem *ip_serial_regs; + struct ioc3_uartregs __iomem *ip_uart_regs; + + /* Ring buffer page for this port */ + dma_addr_t ip_dma_ringbuf; + /* vaddr of ring buffer */ + struct ring_buffer *ip_cpu_ringbuf; + + /* Rings for this port */ + struct ring *ip_inring; + struct ring *ip_outring; + + /* Hook to port specific values */ + struct port_hooks *ip_hooks; + + spinlock_t ip_lock; + + /* Various rx/tx parameters */ + int ip_baud; + int ip_tx_lowat; + int ip_rx_timeout; + + /* Copy of notification bits */ + int ip_notify; + + /* Shadow copies of various registers so we don't need to PIO + * read them constantly + */ + uint32_t ip_sscr; + uint32_t ip_tx_prod; + uint32_t ip_rx_cons; + unsigned char ip_flags; +}; + +/* tx low water mark. We need to notify the driver whenever tx is getting + * close to empty so it can refill the tx buffer and keep things going. + * Let's assume that if we interrupt 1 ms before the tx goes idle, we'll + * have no trouble getting in more chars in time (I certainly hope so). + */ +#define TX_LOWAT_LATENCY 1000 +#define TX_LOWAT_HZ (1000000 / TX_LOWAT_LATENCY) +#define TX_LOWAT_CHARS(baud) (baud / 10 / TX_LOWAT_HZ) + +/* Flags per port */ +#define INPUT_HIGH 0x01 + /* used to signify that we have turned off the rx_high + * temporarily - we need to drain the fifo and don't + * want to get blasted with interrupts. + */ +#define DCD_ON 0x02 + /* DCD state is on */ +#define LOWAT_WRITTEN 0x04 +#define READ_ABORTED 0x08 + /* the read was aborted - used to avaoid infinate looping + * in the interrupt handler + */ +#define INPUT_ENABLE 0x10 + +/* Since each port has different register offsets and bitmasks + * for everything, we'll store those that we need in tables so we + * don't have to be constantly checking the port we are dealing with. + */ +struct port_hooks { + uint32_t intr_delta_dcd; + uint32_t intr_delta_cts; + uint32_t intr_tx_mt; + uint32_t intr_rx_timer; + uint32_t intr_rx_high; + uint32_t intr_tx_explicit; + uint32_t intr_clear; + uint32_t intr_all; + char rs422_select_pin; +}; + +static struct port_hooks hooks_array[PORTS_PER_CARD] = { + /* values for port A */ + { + .intr_delta_dcd = SIO_IR_SA_DELTA_DCD, + .intr_delta_cts = SIO_IR_SA_DELTA_CTS, + .intr_tx_mt = SIO_IR_SA_TX_MT, + .intr_rx_timer = SIO_IR_SA_RX_TIMER, + .intr_rx_high = SIO_IR_SA_RX_HIGH, + .intr_tx_explicit = SIO_IR_SA_TX_EXPLICIT, + .intr_clear = (SIO_IR_SA_TX_MT | SIO_IR_SA_RX_FULL + | SIO_IR_SA_RX_HIGH + | SIO_IR_SA_RX_TIMER + | SIO_IR_SA_DELTA_DCD + | SIO_IR_SA_DELTA_CTS + | SIO_IR_SA_INT + | SIO_IR_SA_TX_EXPLICIT + | SIO_IR_SA_MEMERR), + .intr_all = SIO_IR_SA, + .rs422_select_pin = GPPR_UARTA_MODESEL_PIN, + }, + + /* values for port B */ + { + .intr_delta_dcd = SIO_IR_SB_DELTA_DCD, + .intr_delta_cts = SIO_IR_SB_DELTA_CTS, + .intr_tx_mt = SIO_IR_SB_TX_MT, + .intr_rx_timer = SIO_IR_SB_RX_TIMER, + .intr_rx_high = SIO_IR_SB_RX_HIGH, + .intr_tx_explicit = SIO_IR_SB_TX_EXPLICIT, + .intr_clear = (SIO_IR_SB_TX_MT | SIO_IR_SB_RX_FULL + | SIO_IR_SB_RX_HIGH + | SIO_IR_SB_RX_TIMER + | SIO_IR_SB_DELTA_DCD + | SIO_IR_SB_DELTA_CTS + | SIO_IR_SB_INT + | SIO_IR_SB_TX_EXPLICIT + | SIO_IR_SB_MEMERR), + .intr_all = SIO_IR_SB, + .rs422_select_pin = GPPR_UARTB_MODESEL_PIN, + } +}; + +struct ring_entry { + union { + struct { + uint32_t alldata; + uint32_t allsc; + } all; + struct { + char data[4]; /* data bytes */ + char sc[4]; /* status/control */ + } s; + } u; +}; + +/* Test the valid bits in any of the 4 sc chars using "allsc" member */ +#define RING_ANY_VALID \ + ((uint32_t)(RXSB_MODEM_VALID | RXSB_DATA_VALID) * 0x01010101) + +#define ring_sc u.s.sc +#define ring_data u.s.data +#define ring_allsc u.all.allsc + +/* Number of entries per ring buffer. */ +#define ENTRIES_PER_RING (RING_BUF_SIZE / (int) sizeof(struct ring_entry)) + +/* An individual ring */ +struct ring { + struct ring_entry entries[ENTRIES_PER_RING]; +}; + +/* The whole enchilada */ +struct ring_buffer { + struct ring TX_A; + struct ring RX_A; + struct ring TX_B; + struct ring RX_B; +}; + +/* Get a ring from a port struct */ +#define RING(_p, _wh) &(((struct ring_buffer *)((_p)->ip_cpu_ringbuf))->_wh) + +/* for Infinite loop detection */ +#define MAXITER 10000000 + + +/** + * set_baud - Baud rate setting code + * @port: port to set + * @baud: baud rate to use + */ +static int set_baud(struct ioc3_port *port, int baud) +{ + int divisor; + int actual_baud; + int diff; + int lcr, prediv; + struct ioc3_uartregs __iomem *uart; + + for (prediv = 6; prediv < 64; prediv++) { + divisor = SER_DIVISOR(baud, SER_CLK_SPEED(prediv)); + if (!divisor) + continue; /* invalid divisor */ + actual_baud = DIVISOR_TO_BAUD(divisor, SER_CLK_SPEED(prediv)); + + diff = actual_baud - baud; + if (diff < 0) + diff = -diff; + + /* if we're within 1% we've found a match */ + if (diff * 100 <= actual_baud) + break; + } + + /* if the above loop completed, we didn't match + * the baud rate. give up. + */ + if (prediv == 64) { + NOT_PROGRESS(); + return 1; + } + + uart = port->ip_uart_regs; + lcr = readb(&uart->iu_lcr); + + writeb(lcr | UART_LCR_DLAB, &uart->iu_lcr); + writeb((unsigned char)divisor, &uart->iu_dll); + writeb((unsigned char)(divisor >> 8), &uart->iu_dlm); + writeb((unsigned char)prediv, &uart->iu_scr); + writeb((unsigned char)lcr, &uart->iu_lcr); + + return 0; +} + +/** + * get_ioc3_port - given a uart port, return the control structure + * @the_port: uart port to find + */ +static struct ioc3_port *get_ioc3_port(struct uart_port *the_port) +{ + struct ioc3_driver_data *idd = dev_get_drvdata(the_port->dev); + struct ioc3_card *card_ptr = idd->data[Submodule_slot]; + int ii, jj; + + if (!card_ptr) { + NOT_PROGRESS(); + return NULL; + } + for (ii = 0; ii < PORTS_PER_CARD; ii++) { + for (jj = 0; jj < LOGICAL_PORTS; jj++) { + if (the_port == &card_ptr->ic_port[ii].icp_uart_port[jj]) + return card_ptr->ic_port[ii].icp_port; + } + } + NOT_PROGRESS(); + return NULL; +} + +/** + * port_init - Initialize the sio and ioc3 hardware for a given port + * called per port from attach... + * @port: port to initialize + */ +static int inline port_init(struct ioc3_port *port) +{ + uint32_t sio_cr; + struct port_hooks *hooks = port->ip_hooks; + struct ioc3_uartregs __iomem *uart; + int reset_loop_counter = 0xfffff; + struct ioc3_driver_data *idd = port->ip_idd; + + /* Idle the IOC3 serial interface */ + writel(SSCR_RESET, &port->ip_serial_regs->sscr); + + /* Wait until any pending bus activity for this port has ceased */ + do { + sio_cr = readl(&idd->vma->sio_cr); + if (reset_loop_counter-- <= 0) { + printk(KERN_WARNING + "IOC3 unable to come out of reset" + " scr 0x%x\n", sio_cr); + return -1; + } + } while (!(sio_cr & SIO_CR_ARB_DIAG_IDLE) && + (((sio_cr &= SIO_CR_ARB_DIAG) == SIO_CR_ARB_DIAG_TXA) + || sio_cr == SIO_CR_ARB_DIAG_TXB + || sio_cr == SIO_CR_ARB_DIAG_RXA + || sio_cr == SIO_CR_ARB_DIAG_RXB)); + + /* Finish reset sequence */ + writel(0, &port->ip_serial_regs->sscr); + + /* Once RESET is done, reload cached tx_prod and rx_cons values + * and set rings to empty by making prod == cons + */ + port->ip_tx_prod = readl(&port->ip_serial_regs->stcir) & PROD_CONS_MASK; + writel(port->ip_tx_prod, &port->ip_serial_regs->stpir); + port->ip_rx_cons = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK; + writel(port->ip_rx_cons | SRCIR_ARM, &port->ip_serial_regs->srcir); + + /* Disable interrupts for this 16550 */ + uart = port->ip_uart_regs; + writeb(0, &uart->iu_lcr); + writeb(0, &uart->iu_ier); + + /* Set the default baud */ + set_baud(port, port->ip_baud); + + /* Set line control to 8 bits no parity */ + writeb(UART_LCR_WLEN8 | 0, &uart->iu_lcr); + /* UART_LCR_STOP == 1 stop */ + + /* Enable the FIFOs */ + writeb(UART_FCR_ENABLE_FIFO, &uart->iu_fcr); + /* then reset 16550 FIFOs */ + writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, + &uart->iu_fcr); + + /* Clear modem control register */ + writeb(0, &uart->iu_mcr); + + /* Clear deltas in modem status register */ + writel(0, &port->ip_serial_regs->shadow); + + /* Only do this once per port pair */ + if (port->ip_hooks == &hooks_array[0]) { + unsigned long ring_pci_addr; + uint32_t __iomem *sbbr_l, *sbbr_h; + + sbbr_l = &idd->vma->sbbr_l; + sbbr_h = &idd->vma->sbbr_h; + ring_pci_addr = (unsigned long __iomem)port->ip_dma_ringbuf; + DPRINT_CONFIG(("%s: ring_pci_addr 0x%p\n", + __FUNCTION__, (void *)ring_pci_addr)); + + writel((unsigned int)((uint64_t) ring_pci_addr >> 32), sbbr_h); + writel((unsigned int)ring_pci_addr | BUF_SIZE_BIT, sbbr_l); + } + + /* Set the receive timeout value to 10 msec */ + writel(SRTR_HZ / 100, &port->ip_serial_regs->srtr); + + /* Set rx threshold, enable DMA */ + /* Set high water mark at 3/4 of full ring */ + port->ip_sscr = (ENTRIES_PER_RING * 3 / 4); + + /* uart experiences pauses at high baud rate reducing actual + * throughput by 10% or so unless we enable high speed polling + * XXX when this hardware bug is resolved we should revert to + * normal polling speed + */ + port->ip_sscr |= SSCR_HIGH_SPD; + + writel(port->ip_sscr, &port->ip_serial_regs->sscr); + + /* Disable and clear all serial related interrupt bits */ + port->ip_card->ic_enable &= ~hooks->intr_clear; + ioc3_disable(port->ip_is, idd, hooks->intr_clear); + ioc3_ack(port->ip_is, idd, hooks->intr_clear); + return 0; +} + +/** + * enable_intrs - enable interrupts + * @port: port to enable + * @mask: mask to use + */ +static void enable_intrs(struct ioc3_port *port, uint32_t mask) +{ + if ((port->ip_card->ic_enable & mask) != mask) { + port->ip_card->ic_enable |= mask; + ioc3_enable(port->ip_is, port->ip_idd, mask); + } +} + +/** + * local_open - local open a port + * @port: port to open + */ +static inline int local_open(struct ioc3_port *port) +{ + int spiniter = 0; + + port->ip_flags = INPUT_ENABLE; + + /* Pause the DMA interface if necessary */ + if (port->ip_sscr & SSCR_DMA_EN) { + writel(port->ip_sscr | SSCR_DMA_PAUSE, + &port->ip_serial_regs->sscr); + while ((readl(&port->ip_serial_regs->sscr) + & SSCR_PAUSE_STATE) == 0) { + spiniter++; + if (spiniter > MAXITER) { + NOT_PROGRESS(); + return -1; + } + } + } + + /* Reset the input fifo. If the uart received chars while the port + * was closed and DMA is not enabled, the uart may have a bunch of + * chars hanging around in its rx fifo which will not be discarded + * by rclr in the upper layer. We must get rid of them here. + */ + writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR, + &port->ip_uart_regs->iu_fcr); + + writeb(UART_LCR_WLEN8, &port->ip_uart_regs->iu_lcr); + /* UART_LCR_STOP == 1 stop */ + + /* Re-enable DMA, set default threshold to intr whenever there is + * data available. + */ + port->ip_sscr &= ~SSCR_RX_THRESHOLD; + port->ip_sscr |= 1; /* default threshold */ + + /* Plug in the new sscr. This implicitly clears the DMA_PAUSE + * flag if it was set above + */ + writel(port->ip_sscr, &port->ip_serial_regs->sscr); + port->ip_tx_lowat = 1; + return 0; +} + +/** + * set_rx_timeout - Set rx timeout and threshold values. + * @port: port to use + * @timeout: timeout value in ticks + */ +static inline int set_rx_timeout(struct ioc3_port *port, int timeout) +{ + int threshold; + + port->ip_rx_timeout = timeout; + + /* Timeout is in ticks. Let's figure out how many chars we + * can receive at the current baud rate in that interval + * and set the rx threshold to that amount. There are 4 chars + * per ring entry, so we'll divide the number of chars that will + * arrive in timeout by 4. + * So .... timeout * baud / 10 / HZ / 4, with HZ = 100. + */ + threshold = timeout * port->ip_baud / 4000; + if (threshold == 0) + threshold = 1; /* otherwise we'll intr all the time! */ + + if ((unsigned)threshold > (unsigned)SSCR_RX_THRESHOLD) + return 1; + + port->ip_sscr &= ~SSCR_RX_THRESHOLD; + port->ip_sscr |= threshold; + writel(port->ip_sscr, &port->ip_serial_regs->sscr); + + /* Now set the rx timeout to the given value + * again timeout * SRTR_HZ / HZ + */ + timeout = timeout * SRTR_HZ / 100; + if (timeout > SRTR_CNT) + timeout = SRTR_CNT; + writel(timeout, &port->ip_serial_regs->srtr); + return 0; +} + +/** + * config_port - config the hardware + * @port: port to config + * @baud: baud rate for the port + * @byte_size: data size + * @stop_bits: number of stop bits + * @parenb: parity enable ? + * @parodd: odd parity ? + */ +static inline int +config_port(struct ioc3_port *port, + int baud, int byte_size, int stop_bits, int parenb, int parodd) +{ + char lcr, sizebits; + int spiniter = 0; + + DPRINT_CONFIG(("%s: line %d baud %d byte_size %d stop %d parenb %d " + "parodd %d\n", + __FUNCTION__, ((struct uart_port *)port->ip_port)->line, + baud, byte_size, stop_bits, parenb, parodd)); + + if (set_baud(port, baud)) + return 1; + + switch (byte_size) { + case 5: + sizebits = UART_LCR_WLEN5; + break; + case 6: + sizebits = UART_LCR_WLEN6; + break; + case 7: + sizebits = UART_LCR_WLEN7; + break; + case 8: + sizebits = UART_LCR_WLEN8; + break; + default: + return 1; + } + + /* Pause the DMA interface if necessary */ + if (port->ip_sscr & SSCR_DMA_EN) { + writel(port->ip_sscr | SSCR_DMA_PAUSE, + &port->ip_serial_regs->sscr); + while ((readl(&port->ip_serial_regs->sscr) + & SSCR_PAUSE_STATE) == 0) { + spiniter++; + if (spiniter > MAXITER) + return -1; + } + } + + /* Clear relevant fields in lcr */ + lcr = readb(&port->ip_uart_regs->iu_lcr); + lcr &= ~(LCR_MASK_BITS_CHAR | UART_LCR_EPAR | + UART_LCR_PARITY | LCR_MASK_STOP_BITS); + + /* Set byte size in lcr */ + lcr |= sizebits; + + /* Set parity */ + if (parenb) { + lcr |= UART_LCR_PARITY; + if (!parodd) + lcr |= UART_LCR_EPAR; + } + + /* Set stop bits */ + if (stop_bits) + lcr |= UART_LCR_STOP /* 2 stop bits */ ; + + writeb(lcr, &port->ip_uart_regs->iu_lcr); + + /* Re-enable the DMA interface if necessary */ + if (port->ip_sscr & SSCR_DMA_EN) { + writel(port->ip_sscr, &port->ip_serial_regs->sscr); + } + port->ip_baud = baud; + + /* When we get within this number of ring entries of filling the + * entire ring on tx, place an EXPLICIT intr to generate a lowat + * notification when output has drained. + */ + port->ip_tx_lowat = (TX_LOWAT_CHARS(baud) + 3) / 4; + if (port->ip_tx_lowat == 0) + port->ip_tx_lowat = 1; + + set_rx_timeout(port, 2); + return 0; +} + +/** + * do_write - Write bytes to the port. Returns the number of bytes + * actually written. Called from transmit_chars + * @port: port to use + * @buf: the stuff to write + * @len: how many bytes in 'buf' + */ +static inline int do_write(struct ioc3_port *port, char *buf, int len) +{ + int prod_ptr, cons_ptr, total = 0; + struct ring *outring; + struct ring_entry *entry; + struct port_hooks *hooks = port->ip_hooks; + + BUG_ON(!(len >= 0)); + + prod_ptr = port->ip_tx_prod; + cons_ptr = readl(&port->ip_serial_regs->stcir) & PROD_CONS_MASK; + outring = port->ip_outring; + + /* Maintain a 1-entry red-zone. The ring buffer is full when + * (cons - prod) % ring_size is 1. Rather than do this subtraction + * in the body of the loop, I'll do it now. + */ + cons_ptr = (cons_ptr - (int)sizeof(struct ring_entry)) & PROD_CONS_MASK; + + /* Stuff the bytes into the output */ + while ((prod_ptr != cons_ptr) && (len > 0)) { + int xx; + + /* Get 4 bytes (one ring entry) at a time */ + entry = (struct ring_entry *)((caddr_t) outring + prod_ptr); + + /* Invalidate all entries */ + entry->ring_allsc = 0; + + /* Copy in some bytes */ + for (xx = 0; (xx < 4) && (len > 0); xx++) { + entry->ring_data[xx] = *buf++; + entry->ring_sc[xx] = TXCB_VALID; + len--; + total++; + } + + /* If we are within some small threshold of filling up the + * entire ring buffer, we must place an EXPLICIT intr here + * to generate a lowat interrupt in case we subsequently + * really do fill up the ring and the caller goes to sleep. + * No need to place more than one though. + */ + if (!(port->ip_flags & LOWAT_WRITTEN) && + ((cons_ptr - prod_ptr) & PROD_CONS_MASK) + <= port->ip_tx_lowat * (int)sizeof(struct ring_entry)) { + port->ip_flags |= LOWAT_WRITTEN; + entry->ring_sc[0] |= TXCB_INT_WHEN_DONE; + } + + /* Go on to next entry */ + prod_ptr += sizeof(struct ring_entry); + prod_ptr &= PROD_CONS_MASK; + } + + /* If we sent something, start DMA if necessary */ + if (total > 0 && !(port->ip_sscr & SSCR_DMA_EN)) { + port->ip_sscr |= SSCR_DMA_EN; + writel(port->ip_sscr, &port->ip_serial_regs->sscr); + } + + /* Store the new producer pointer. If tx is disabled, we stuff the + * data into the ring buffer, but we don't actually start tx. + */ + if (!uart_tx_stopped(port->ip_port)) { + writel(prod_ptr, &port->ip_serial_regs->stpir); + + /* If we are now transmitting, enable tx_mt interrupt so we + * can disable DMA if necessary when the tx finishes. + */ + if (total > 0) + enable_intrs(port, hooks->intr_tx_mt); + } + port->ip_tx_prod = prod_ptr; + + return total; +} + +/** + * disable_intrs - disable interrupts + * @port: port to enable + * @mask: mask to use + */ +static inline void disable_intrs(struct ioc3_port *port, uint32_t mask) +{ + if (port->ip_card->ic_enable & mask) { + ioc3_disable(port->ip_is, port->ip_idd, mask); + port->ip_card->ic_enable &= ~mask; + } +} + +/** + * set_notification - Modify event notification + * @port: port to use + * @mask: events mask + * @set_on: set ? + */ +static int set_notification(struct ioc3_port *port, int mask, int set_on) +{ + struct port_hooks *hooks = port->ip_hooks; + uint32_t intrbits, sscrbits; + + BUG_ON(!mask); + + intrbits = sscrbits = 0; + + if (mask & N_DATA_READY) + intrbits |= (hooks->intr_rx_timer | hooks->intr_rx_high); + if (mask & N_OUTPUT_LOWAT) + intrbits |= hooks->intr_tx_explicit; + if (mask & N_DDCD) { + intrbits |= hooks->intr_delta_dcd; + sscrbits |= SSCR_RX_RING_DCD; + } + if (mask & N_DCTS) + intrbits |= hooks->intr_delta_cts; + + if (set_on) { + enable_intrs(port, intrbits); + port->ip_notify |= mask; + port->ip_sscr |= sscrbits; + } else { + disable_intrs(port, intrbits); + port->ip_notify &= ~mask; + port->ip_sscr &= ~sscrbits; + } + + /* We require DMA if either DATA_READY or DDCD notification is + * currently requested. If neither of these is requested and + * there is currently no tx in progress, DMA may be disabled. + */ + if (port->ip_notify & (N_DATA_READY | N_DDCD)) + port->ip_sscr |= SSCR_DMA_EN; + else if (!(port->ip_card->ic_enable & hooks->intr_tx_mt)) + port->ip_sscr &= ~SSCR_DMA_EN; + + writel(port->ip_sscr, &port->ip_serial_regs->sscr); + return 0; +} + +/** + * set_mcr - set the master control reg + * @the_port: port to use + * @mask1: mcr mask + * @mask2: shadow mask + */ +static inline int set_mcr(struct uart_port *the_port, + int mask1, int mask2) +{ + struct ioc3_port *port = get_ioc3_port(the_port); + uint32_t shadow; + int spiniter = 0; + char mcr; + + if (!port) + return -1; + + /* Pause the DMA interface if necessary */ + if (port->ip_sscr & SSCR_DMA_EN) { + writel(port->ip_sscr | SSCR_DMA_PAUSE, + &port->ip_serial_regs->sscr); + while ((readl(&port->ip_serial_regs->sscr) + & SSCR_PAUSE_STATE) == 0) { + spiniter++; + if (spiniter > MAXITER) + return -1; + } + } + shadow = readl(&port->ip_serial_regs->shadow); + mcr = (shadow & 0xff000000) >> 24; + + /* Set new value */ + mcr |= mask1; + shadow |= mask2; + writeb(mcr, &port->ip_uart_regs->iu_mcr); + writel(shadow, &port->ip_serial_regs->shadow); + + /* Re-enable the DMA interface if necessary */ + if (port->ip_sscr & SSCR_DMA_EN) { + writel(port->ip_sscr, &port->ip_serial_regs->sscr); + } + return 0; +} + +/** + * ioc3_set_proto - set the protocol for the port + * @port: port to use + * @proto: protocol to use + */ +static int ioc3_set_proto(struct ioc3_port *port, int proto) +{ + struct port_hooks *hooks = port->ip_hooks; + + switch (proto) { + default: + case PROTO_RS232: + /* Clear the appropriate GIO pin */ + DPRINT_CONFIG(("%s: rs232\n", __FUNCTION__)); + writel(0, (&port->ip_idd->vma->gppr[0] + + hooks->rs422_select_pin)); + break; + + case PROTO_RS422: + /* Set the appropriate GIO pin */ + DPRINT_CONFIG(("%s: rs422\n", __FUNCTION__)); + writel(1, (&port->ip_idd->vma->gppr[0] + + hooks->rs422_select_pin)); + break; + } + return 0; +} + +/** + * transmit_chars - upper level write, called with the_port->lock + * @the_port: port to write + */ +static void transmit_chars(struct uart_port *the_port) +{ + int xmit_count, tail, head; + int result; + char *start; + struct tty_struct *tty; + struct ioc3_port *port = get_ioc3_port(the_port); + struct uart_info *info; + + if (!the_port) + return; + if (!port) + return; + + info = the_port->info; + tty = info->tty; + + if (uart_circ_empty(&info->xmit) || uart_tx_stopped(the_port)) { + /* Nothing to do or hw stopped */ + set_notification(port, N_ALL_OUTPUT, 0); + return; + } + + head = info->xmit.head; + tail = info->xmit.tail; + start = (char *)&info->xmit.buf[tail]; + + /* write out all the data or until the end of the buffer */ + xmit_count = (head < tail) ? (UART_XMIT_SIZE - tail) : (head - tail); + if (xmit_count > 0) { + result = do_write(port, start, xmit_count); + if (result > 0) { + /* booking */ + xmit_count -= result; + the_port->icount.tx += result; + /* advance the pointers */ + tail += result; + tail &= UART_XMIT_SIZE - 1; + info->xmit.tail = tail; + start = (char *)&info->xmit.buf[tail]; + } + } + if (uart_circ_chars_pending(&info->xmit) < WAKEUP_CHARS) + uart_write_wakeup(the_port); + + if (uart_circ_empty(&info->xmit)) { + set_notification(port, N_OUTPUT_LOWAT, 0); + } else { + set_notification(port, N_OUTPUT_LOWAT, 1); + } +} + +/** + * ioc3_change_speed - change the speed of the port + * @the_port: port to change + * @new_termios: new termios settings + * @old_termios: old termios settings + */ +static void +ioc3_change_speed(struct uart_port *the_port, + struct termios *new_termios, struct termios *old_termios) +{ + struct ioc3_port *port = get_ioc3_port(the_port); + unsigned int cflag; + int baud; + int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8; + struct uart_info *info = the_port->info; + + cflag = new_termios->c_cflag; + + switch (cflag & CSIZE) { + case CS5: + new_data = 5; + break; + case CS6: + new_data = 6; + break; + case CS7: + new_data = 7; + break; + case CS8: + new_data = 8; + break; + default: + /* cuz we always need a default ... */ + new_data = 5; + break; + } + if (cflag & CSTOPB) { + new_stop = 1; + } + if (cflag & PARENB) { + new_parity_enable = 1; + if (cflag & PARODD) + new_parity = 1; + } + baud = uart_get_baud_rate(the_port, new_termios, old_termios, + MIN_BAUD_SUPPORTED, MAX_BAUD_SUPPORTED); + DPRINT_CONFIG(("%s: returned baud %d for line %d\n", __FUNCTION__, baud, + the_port->line)); + + if (!the_port->fifosize) + the_port->fifosize = FIFO_SIZE; + uart_update_timeout(the_port, cflag, baud); + + the_port->ignore_status_mask = N_ALL_INPUT; + + info->tty->low_latency = 1; + + if (I_IGNPAR(info->tty)) + the_port->ignore_status_mask &= ~(N_PARITY_ERROR + | N_FRAMING_ERROR); + if (I_IGNBRK(info->tty)) { + the_port->ignore_status_mask &= ~N_BREAK; + if (I_IGNPAR(info->tty)) + the_port->ignore_status_mask &= ~N_OVERRUN_ERROR; + } + if (!(cflag & CREAD)) { + /* ignore everything */ + the_port->ignore_status_mask &= ~N_DATA_READY; + } + + if (cflag & CRTSCTS) { + /* enable hardware flow control */ + port->ip_sscr |= SSCR_HFC_EN; + } + else { + /* disable hardware flow control */ + port->ip_sscr &= ~SSCR_HFC_EN; + } + writel(port->ip_sscr, &port->ip_serial_regs->sscr); + + /* Set the configuration and proper notification call */ + DPRINT_CONFIG(("%s : port 0x%p line %d cflag 0%o " + "config_port(baud %d data %d stop %d penable %d " + " parity %d), notification 0x%x\n", + __FUNCTION__, (void *)port, the_port->line, cflag, baud, + new_data, new_stop, new_parity_enable, new_parity, + the_port->ignore_status_mask)); + + if ((config_port(port, baud, /* baud */ + new_data, /* byte size */ + new_stop, /* stop bits */ + new_parity_enable, /* set parity */ + new_parity)) >= 0) { /* parity 1==odd */ + set_notification(port, the_port->ignore_status_mask, 1); + } +} + +/** + * ic3_startup_local - Start up the serial port - returns >= 0 if no errors + * @the_port: Port to operate on + */ +static inline int ic3_startup_local(struct uart_port *the_port) +{ + struct ioc3_port *port; + + if (!the_port) { + NOT_PROGRESS(); + return -1; + } + + port = get_ioc3_port(the_port); + if (!port) { + NOT_PROGRESS(); + return -1; + } + + local_open(port); + + /* set the protocol */ + ioc3_set_proto(port, IS_RS232(the_port->line) ? PROTO_RS232 : + PROTO_RS422); + return 0; +} + +/* + * ioc3_cb_output_lowat - called when the output low water mark is hit + * @port: port to output + */ +static void ioc3_cb_output_lowat(struct ioc3_port *port) +{ + unsigned long pflags; + + /* the_port->lock is set on the call here */ + if (port->ip_port) { + spin_lock_irqsave(&port->ip_port->lock, pflags); + transmit_chars(port->ip_port); + spin_unlock_irqrestore(&port->ip_port->lock, pflags); + } +} + +/* + * ioc3_cb_post_ncs - called for some basic errors + * @port: port to use + * @ncs: event + */ +static void ioc3_cb_post_ncs(struct uart_port *the_port, int ncs) +{ + struct uart_icount *icount; + + icount = &the_port->icount; + + if (ncs & NCS_BREAK) + icount->brk++; + if (ncs & NCS_FRAMING) + icount->frame++; + if (ncs & NCS_OVERRUN) + icount->overrun++; + if (ncs & NCS_PARITY) + icount->parity++; +} + +/** + * do_read - Read in bytes from the port. Return the number of bytes + * actually read. + * @the_port: port to use + * @buf: place to put the stuff we read + * @len: how big 'buf' is + */ + +static inline int do_read(struct uart_port *the_port, char *buf, int len) +{ + int prod_ptr, cons_ptr, total; + struct ioc3_port *port = get_ioc3_port(the_port); + struct ring *inring; + struct ring_entry *entry; + struct port_hooks *hooks = port->ip_hooks; + int byte_num; + char *sc; + int loop_counter; + + BUG_ON(!(len >= 0)); + BUG_ON(!port); + + /* There is a nasty timing issue in the IOC3. When the rx_timer + * expires or the rx_high condition arises, we take an interrupt. + * At some point while servicing the interrupt, we read bytes from + * the ring buffer and re-arm the rx_timer. However the rx_timer is + * not started until the first byte is received *after* it is armed, + * and any bytes pending in the rx construction buffers are not drained + * to memory until either there are 4 bytes available or the rx_timer + * expires. This leads to a potential situation where data is left + * in the construction buffers forever - 1 to 3 bytes were received + * after the interrupt was generated but before the rx_timer was + * re-armed. At that point as long as no subsequent bytes are received + * the timer will never be started and the bytes will remain in the + * construction buffer forever. The solution is to execute a DRAIN + * command after rearming the timer. This way any bytes received before + * the DRAIN will be drained to memory, and any bytes received after + * the DRAIN will start the TIMER and be drained when it expires. + * Luckily, this only needs to be done when the DMA buffer is empty + * since there is no requirement that this function return all + * available data as long as it returns some. + */ + /* Re-arm the timer */ + + writel(port->ip_rx_cons | SRCIR_ARM, &port->ip_serial_regs->srcir); + + prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK; + cons_ptr = port->ip_rx_cons; + + if (prod_ptr == cons_ptr) { + int reset_dma = 0; + + /* Input buffer appears empty, do a flush. */ + + /* DMA must be enabled for this to work. */ + if (!(port->ip_sscr & SSCR_DMA_EN)) { + port->ip_sscr |= SSCR_DMA_EN; + reset_dma = 1; + } + + /* Potential race condition: we must reload the srpir after + * issuing the drain command, otherwise we could think the rx + * buffer is empty, then take a very long interrupt, and when + * we come back it's full and we wait forever for the drain to + * complete. + */ + writel(port->ip_sscr | SSCR_RX_DRAIN, + &port->ip_serial_regs->sscr); + prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK; + + /* We must not wait for the DRAIN to complete unless there are + * at least 8 bytes (2 ring entries) available to receive the + * data otherwise the DRAIN will never complete and we'll + * deadlock here. + * In fact, to make things easier, I'll just ignore the flush if + * there is any data at all now available. + */ + if (prod_ptr == cons_ptr) { + loop_counter = 0; + while (readl(&port->ip_serial_regs->sscr) & + SSCR_RX_DRAIN) { + loop_counter++; + if (loop_counter > MAXITER) + return -1; + } + + /* SIGH. We have to reload the prod_ptr *again* since + * the drain may have caused it to change + */ + prod_ptr = readl(&port->ip_serial_regs->srpir) + & PROD_CONS_MASK; + } + if (reset_dma) { + port->ip_sscr &= ~SSCR_DMA_EN; + writel(port->ip_sscr, &port->ip_serial_regs->sscr); + } + } + inring = port->ip_inring; + port->ip_flags &= ~READ_ABORTED; + + total = 0; + loop_counter = 0xfffff; /* to avoid hangs */ + + /* Grab bytes from the hardware */ + while ((prod_ptr != cons_ptr) && (len > 0)) { + entry = (struct ring_entry *)((caddr_t) inring + cons_ptr); + + if (loop_counter-- <= 0) { + printk(KERN_WARNING "IOC3 serial: " + "possible hang condition/" + "port stuck on read (line %d).\n", + the_port->line); + break; + } + + /* According to the producer pointer, this ring entry + * must contain some data. But if the PIO happened faster + * than the DMA, the data may not be available yet, so let's + * wait until it arrives. + */ + if ((entry->ring_allsc & RING_ANY_VALID) == 0) { + /* Indicate the read is aborted so we don't disable + * the interrupt thinking that the consumer is + * congested. + */ + port->ip_flags |= READ_ABORTED; + len = 0; + break; + } + + /* Load the bytes/status out of the ring entry */ + for (byte_num = 0; byte_num < 4 && len > 0; byte_num++) { + sc = &(entry->ring_sc[byte_num]); + + /* Check for change in modem state or overrun */ + if ((*sc & RXSB_MODEM_VALID) + && (port->ip_notify & N_DDCD)) { + /* Notify upper layer if DCD dropped */ + if ((port->ip_flags & DCD_ON) + && !(*sc & RXSB_DCD)) { + /* If we have already copied some data, + * return it. We'll pick up the carrier + * drop on the next pass. That way we + * don't throw away the data that has + * already been copied back to + * the caller's buffer. + */ + if (total > 0) { + len = 0; + break; + } + port->ip_flags &= ~DCD_ON; + + /* Turn off this notification so the + * carrier drop protocol won't see it + * again when it does a read. + */ + *sc &= ~RXSB_MODEM_VALID; + + /* To keep things consistent, we need + * to update the consumer pointer so + * the next reader won't come in and + * try to read the same ring entries + * again. This must be done here before + * the dcd change. + */ + + if ((entry->ring_allsc & RING_ANY_VALID) + == 0) { + cons_ptr += (int)sizeof + (struct ring_entry); + cons_ptr &= PROD_CONS_MASK; + } + writel(cons_ptr, + &port->ip_serial_regs->srcir); + port->ip_rx_cons = cons_ptr; + + /* Notify upper layer of carrier drop */ + if ((port->ip_notify & N_DDCD) + && port->ip_port) { + uart_handle_dcd_change + (port->ip_port, 0); + wake_up_interruptible + (&the_port->info-> + delta_msr_wait); + } + + /* If we had any data to return, we + * would have returned it above. + */ + return 0; + } + } + if (*sc & RXSB_MODEM_VALID) { + /* Notify that an input overrun occurred */ + if ((*sc & RXSB_OVERRUN) + && (port->ip_notify & N_OVERRUN_ERROR)) { + ioc3_cb_post_ncs(the_port, NCS_OVERRUN); + } + /* Don't look at this byte again */ + *sc &= ~RXSB_MODEM_VALID; + } + + /* Check for valid data or RX errors */ + if ((*sc & RXSB_DATA_VALID) && + ((*sc & (RXSB_PAR_ERR + | RXSB_FRAME_ERR | RXSB_BREAK)) + && (port->ip_notify & (N_PARITY_ERROR + | N_FRAMING_ERROR + | N_BREAK)))) { + /* There is an error condition on the next byte. + * If we have already transferred some bytes, + * we'll stop here. Otherwise if this is the + * first byte to be read, we'll just transfer + * it alone after notifying the + * upper layer of its status. + */ + if (total > 0) { + len = 0; + break; + } else { + if ((*sc & RXSB_PAR_ERR) && + (port-> + ip_notify & N_PARITY_ERROR)) { + ioc3_cb_post_ncs(the_port, + NCS_PARITY); + } + if ((*sc & RXSB_FRAME_ERR) && + (port-> + ip_notify & N_FRAMING_ERROR)) { + ioc3_cb_post_ncs(the_port, + NCS_FRAMING); + } + if ((*sc & RXSB_BREAK) + && (port->ip_notify & N_BREAK)) { + ioc3_cb_post_ncs + (the_port, NCS_BREAK); + } + len = 1; + } + } + if (*sc & RXSB_DATA_VALID) { + *sc &= ~RXSB_DATA_VALID; + *buf = entry->ring_data[byte_num]; + buf++; + len--; + total++; + } + } + + /* If we used up this entry entirely, go on to the next one, + * otherwise we must have run out of buffer space, so + * leave the consumer pointer here for the next read in case + * there are still unread bytes in this entry. + */ + if ((entry->ring_allsc & RING_ANY_VALID) == 0) { + cons_ptr += (int)sizeof(struct ring_entry); + cons_ptr &= PROD_CONS_MASK; + } + } + + /* Update consumer pointer and re-arm rx timer interrupt */ + writel(cons_ptr, &port->ip_serial_regs->srcir); + port->ip_rx_cons = cons_ptr; + + /* If we have now dipped below the rx high water mark and we have + * rx_high interrupt turned off, we can now turn it back on again. + */ + if ((port->ip_flags & INPUT_HIGH) && (((prod_ptr - cons_ptr) + & PROD_CONS_MASK) < + ((port-> + ip_sscr & + SSCR_RX_THRESHOLD) + << PROD_CONS_PTR_OFF))) { + port->ip_flags &= ~INPUT_HIGH; + enable_intrs(port, hooks->intr_rx_high); + } + return total; +} + +/** + * receive_chars - upper level read. + * @the_port: port to read from + */ +static int receive_chars(struct uart_port *the_port) +{ + struct tty_struct *tty; + unsigned char ch[MAX_CHARS]; + int read_count = 0, read_room, flip = 0; + struct uart_info *info = the_port->info; + struct ioc3_port *port = get_ioc3_port(the_port); + unsigned long pflags; + + /* Make sure all the pointers are "good" ones */ + if (!info) + return 0; + if (!info->tty) + return 0; + + if (!(port->ip_flags & INPUT_ENABLE)) + return 0; + + spin_lock_irqsave(&the_port->lock, pflags); + tty = info->tty; + + read_count = do_read(the_port, ch, MAX_CHARS); + if (read_count > 0) { + flip = 1; + read_room = tty_buffer_request_room(tty, read_count); + tty_insert_flip_string(tty, ch, read_room); + the_port->icount.rx += read_count; + } + spin_unlock_irqrestore(&the_port->lock, pflags); + + if (flip) + tty_flip_buffer_push(tty); + + return read_count; +} + +/** + * ioc3uart_intr_one - lowest level (per port) interrupt handler. + * @is : submodule + * @idd: driver data + * @pending: interrupts to handle + * @regs: pt_regs + */ + +static int inline +ioc3uart_intr_one(struct ioc3_submodule *is, + struct ioc3_driver_data *idd, + unsigned int pending, struct pt_regs *regs) +{ + int port_num = GET_PORT_FROM_SIO_IR(pending); + struct port_hooks *hooks; + unsigned int rx_high_rd_aborted = 0; + unsigned long flags; + struct uart_port *the_port; + struct ioc3_port *port; + int loop_counter; + struct ioc3_card *card_ptr; + unsigned int sio_ir; + + card_ptr = idd->data[is->id]; + port = card_ptr->ic_port[port_num].icp_port; + hooks = port->ip_hooks; + + /* Possible race condition here: The tx_mt interrupt bit may be + * cleared without the intervention of the interrupt handler, + * e.g. by a write. If the top level interrupt handler reads a + * tx_mt, then some other processor does a write, starting up + * output, then we come in here, see the tx_mt and stop DMA, the + * output started by the other processor will hang. Thus we can + * only rely on tx_mt being legitimate if it is read while the + * port lock is held. Therefore this bit must be ignored in the + * passed in interrupt mask which was read by the top level + * interrupt handler since the port lock was not held at the time + * it was read. We can only rely on this bit being accurate if it + * is read while the port lock is held. So we'll clear it for now, + * and reload it later once we have the port lock. + */ + + sio_ir = pending & ~(hooks->intr_tx_mt); + spin_lock_irqsave(&port->ip_lock, flags); + + loop_counter = MAXITER; /* to avoid hangs */ + + do { + uint32_t shadow; + + if (loop_counter-- <= 0) { + printk(KERN_WARNING "IOC3 serial: " + "possible hang condition/" + "port stuck on interrupt (line %d).\n", + ((struct uart_port *)port->ip_port)->line); + break; + } + /* Handle a DCD change */ + if (sio_ir & hooks->intr_delta_dcd) { + ioc3_ack(is, idd, hooks->intr_delta_dcd); + shadow = readl(&port->ip_serial_regs->shadow); + + if ((port->ip_notify & N_DDCD) + && (shadow & SHADOW_DCD) + && (port->ip_port)) { + the_port = port->ip_port; + uart_handle_dcd_change(the_port, + shadow & SHADOW_DCD); + wake_up_interruptible + (&the_port->info->delta_msr_wait); + } else if ((port->ip_notify & N_DDCD) + && !(shadow & SHADOW_DCD)) { + /* Flag delta DCD/no DCD */ + uart_handle_dcd_change(port->ip_port, + shadow & SHADOW_DCD); + port->ip_flags |= DCD_ON; + } + } + + /* Handle a CTS change */ + if (sio_ir & hooks->intr_delta_cts) { + ioc3_ack(is, idd, hooks->intr_delta_cts); + shadow = readl(&port->ip_serial_regs->shadow); + + if ((port->ip_notify & N_DCTS) && (port->ip_port)) { + the_port = port->ip_port; + uart_handle_cts_change(the_port, shadow + & SHADOW_CTS); + wake_up_interruptible + (&the_port->info->delta_msr_wait); + } + } + + /* rx timeout interrupt. Must be some data available. Put this + * before the check for rx_high since servicing this condition + * may cause that condition to clear. + */ + if (sio_ir & hooks->intr_rx_timer) { + ioc3_ack(is, idd, hooks->intr_rx_timer); + if ((port->ip_notify & N_DATA_READY) + && (port->ip_port)) { + receive_chars(port->ip_port); + } + } + + /* rx high interrupt. Must be after rx_timer. */ + else if (sio_ir & hooks->intr_rx_high) { + /* Data available, notify upper layer */ + if ((port->ip_notify & N_DATA_READY) && port->ip_port) { + receive_chars(port->ip_port); + } + + /* We can't ACK this interrupt. If receive_chars didn't + * cause the condition to clear, we'll have to disable + * the interrupt until the data is drained. + * If the read was aborted, don't disable the interrupt + * as this may cause us to hang indefinitely. An + * aborted read generally means that this interrupt + * hasn't been delivered to the cpu yet anyway, even + * though we see it as asserted when we read the sio_ir. + */ + if ((sio_ir = PENDING(card_ptr, idd)) + & hooks->intr_rx_high) { + if (port->ip_flags & READ_ABORTED) { + rx_high_rd_aborted++; + } + else { + card_ptr->ic_enable &= ~hooks->intr_rx_high; + port->ip_flags |= INPUT_HIGH; + } + } + } + + /* We got a low water interrupt: notify upper layer to + * send more data. Must come before tx_mt since servicing + * this condition may cause that condition to clear. + */ + if (sio_ir & hooks->intr_tx_explicit) { + port->ip_flags &= ~LOWAT_WRITTEN; + ioc3_ack(is, idd, hooks->intr_tx_explicit); + if (port->ip_notify & N_OUTPUT_LOWAT) + ioc3_cb_output_lowat(port); + } + + /* Handle tx_mt. Must come after tx_explicit. */ + else if (sio_ir & hooks->intr_tx_mt) { + /* If we are expecting a lowat notification + * and we get to this point it probably means that for + * some reason the tx_explicit didn't work as expected + * (that can legitimately happen if the output buffer is + * filled up in just the right way). + * So send the notification now. + */ + if (port->ip_notify & N_OUTPUT_LOWAT) { + ioc3_cb_output_lowat(port); + + /* We need to reload the sio_ir since the lowat + * call may have caused another write to occur, + * clearing the tx_mt condition. + */ + sio_ir = PENDING(card_ptr, idd); + } + + /* If the tx_mt condition still persists even after the + * lowat call, we've got some work to do. + */ + if (sio_ir & hooks->intr_tx_mt) { + /* If we are not currently expecting DMA input, + * and the transmitter has just gone idle, + * there is no longer any reason for DMA, so + * disable it. + */ + if (!(port->ip_notify + & (N_DATA_READY | N_DDCD))) { + BUG_ON(!(port->ip_sscr + & SSCR_DMA_EN)); + port->ip_sscr &= ~SSCR_DMA_EN; + writel(port->ip_sscr, + &port->ip_serial_regs->sscr); + } + /* Prevent infinite tx_mt interrupt */ + card_ptr->ic_enable &= ~hooks->intr_tx_mt; + } + } + sio_ir = PENDING(card_ptr, idd); + + /* if the read was aborted and only hooks->intr_rx_high, + * clear hooks->intr_rx_high, so we do not loop forever. + */ + + if (rx_high_rd_aborted && (sio_ir == hooks->intr_rx_high)) { + sio_ir &= ~hooks->intr_rx_high; + } + } while (sio_ir & hooks->intr_all); + + spin_unlock_irqrestore(&port->ip_lock, flags); + ioc3_enable(is, idd, card_ptr->ic_enable); + return 0; +} + +/** + * ioc3uart_intr - field all serial interrupts + * @is : submodule + * @idd: driver data + * @pending: interrupts to handle + * @regs: pt_regs + * + */ + +static int ioc3uart_intr(struct ioc3_submodule *is, + struct ioc3_driver_data *idd, + unsigned int pending, struct pt_regs *regs) +{ + int ret = 0; + + /* + * The upper level interrupt handler sends interrupts for both ports + * here. So we need to call for each port with its interrupts. + */ + + if (pending & SIO_IR_SA) + ret |= ioc3uart_intr_one(is, idd, pending & SIO_IR_SA, regs); + if (pending & SIO_IR_SB) + ret |= ioc3uart_intr_one(is, idd, pending & SIO_IR_SB, regs); + + return ret; +} + +/** + * ic3_type + * @port: Port to operate with (we ignore since we only have one port) + * + */ +static const char *ic3_type(struct uart_port *the_port) +{ + if (IS_RS232(the_port->line)) + return "SGI IOC3 Serial [rs232]"; + else + return "SGI IOC3 Serial [rs422]"; +} + +/** + * ic3_tx_empty - Is the transmitter empty? + * @port: Port to operate on + * + */ +static unsigned int ic3_tx_empty(struct uart_port *the_port) +{ + unsigned int ret = 0; + struct ioc3_port *port = get_ioc3_port(the_port); + + if (readl(&port->ip_serial_regs->shadow) & SHADOW_TEMT) + ret = TIOCSER_TEMT; + return ret; +} + +/** + * ic3_stop_tx - stop the transmitter + * @port: Port to operate on + * + */ +static void ic3_stop_tx(struct uart_port *the_port) +{ + struct ioc3_port *port = get_ioc3_port(the_port); + + if (port) + set_notification(port, N_OUTPUT_LOWAT, 0); +} + +/** + * ic3_stop_rx - stop the receiver + * @port: Port to operate on + * + */ +static void ic3_stop_rx(struct uart_port *the_port) +{ + struct ioc3_port *port = get_ioc3_port(the_port); + + if (port) + port->ip_flags &= ~INPUT_ENABLE; +} + +/** + * null_void_function + * @port: Port to operate on + * + */ +static void null_void_function(struct uart_port *the_port) +{ +} + +/** + * ic3_shutdown - shut down the port - free irq and disable + * @port: port to shut down + * + */ +static void ic3_shutdown(struct uart_port *the_port) +{ + unsigned long port_flags; + struct ioc3_port *port; + struct uart_info *info; + + port = get_ioc3_port(the_port); + if (!port) + return; + + info = the_port->info; + wake_up_interruptible(&info->delta_msr_wait); + + spin_lock_irqsave(&the_port->lock, port_flags); + set_notification(port, N_ALL, 0); + spin_unlock_irqrestore(&the_port->lock, port_flags); +} + +/** + * ic3_set_mctrl - set control lines (dtr, rts, etc) + * @port: Port to operate on + * @mctrl: Lines to set/unset + * + */ +static void ic3_set_mctrl(struct uart_port *the_port, unsigned int mctrl) +{ + unsigned char mcr = 0; + + if (mctrl & TIOCM_RTS) + mcr |= UART_MCR_RTS; + if (mctrl & TIOCM_DTR) + mcr |= UART_MCR_DTR; + if (mctrl & TIOCM_OUT1) + mcr |= UART_MCR_OUT1; + if (mctrl & TIOCM_OUT2) + mcr |= UART_MCR_OUT2; + if (mctrl & TIOCM_LOOP) + mcr |= UART_MCR_LOOP; + + set_mcr(the_port, mcr, SHADOW_DTR); +} + +/** + * ic3_get_mctrl - get control line info + * @port: port to operate on + * + */ +static unsigned int ic3_get_mctrl(struct uart_port *the_port) +{ + struct ioc3_port *port = get_ioc3_port(the_port); + uint32_t shadow; + unsigned int ret = 0; + + if (!port) + return 0; + + shadow = readl(&port->ip_serial_regs->shadow); + if (shadow & SHADOW_DCD) + ret |= TIOCM_CD; + if (shadow & SHADOW_DR) + ret |= TIOCM_DSR; + if (shadow & SHADOW_CTS) + ret |= TIOCM_CTS; + return ret; +} + +/** + * ic3_start_tx - Start transmitter. Called with the_port->lock + * @port: Port to operate on + * + */ +static void ic3_start_tx(struct uart_port *the_port) +{ + struct ioc3_port *port = get_ioc3_port(the_port); + + if (port) { + set_notification(port, N_OUTPUT_LOWAT, 1); + enable_intrs(port, port->ip_hooks->intr_tx_mt); + } +} + +/** + * ic3_break_ctl - handle breaks + * @port: Port to operate on + * @break_state: Break state + * + */ +static void ic3_break_ctl(struct uart_port *the_port, int break_state) +{ +} + +/** + * ic3_startup - Start up the serial port - always return 0 (We're always on) + * @port: Port to operate on + * + */ +static int ic3_startup(struct uart_port *the_port) +{ + int retval; + struct ioc3_port *port; + struct ioc3_card *card_ptr; + unsigned long port_flags; + + if (!the_port) { + NOT_PROGRESS(); + return -ENODEV; + } + port = get_ioc3_port(the_port); + if (!port) { + NOT_PROGRESS(); + return -ENODEV; + } + card_ptr = port->ip_card; + port->ip_port = the_port; + + if (!card_ptr) { + NOT_PROGRESS(); + return -ENODEV; + } + + /* Start up the serial port */ + spin_lock_irqsave(&the_port->lock, port_flags); + retval = ic3_startup_local(the_port); + spin_unlock_irqrestore(&the_port->lock, port_flags); + return retval; +} + +/** + * ic3_set_termios - set termios stuff + * @port: port to operate on + * @termios: New settings + * @termios: Old + * + */ +static void +ic3_set_termios(struct uart_port *the_port, + struct termios *termios, struct termios *old_termios) +{ + unsigned long port_flags; + + spin_lock_irqsave(&the_port->lock, port_flags); + ioc3_change_speed(the_port, termios, old_termios); + spin_unlock_irqrestore(&the_port->lock, port_flags); +} + +/** + * ic3_request_port - allocate resources for port - no op.... + * @port: port to operate on + * + */ +static int ic3_request_port(struct uart_port *port) +{ + return 0; +} + +/* Associate the uart functions above - given to serial core */ +static struct uart_ops ioc3_ops = { + .tx_empty = ic3_tx_empty, + .set_mctrl = ic3_set_mctrl, + .get_mctrl = ic3_get_mctrl, + .stop_tx = ic3_stop_tx, + .start_tx = ic3_start_tx, + .stop_rx = ic3_stop_rx, + .enable_ms = null_void_function, + .break_ctl = ic3_break_ctl, + .startup = ic3_startup, + .shutdown = ic3_shutdown, + .set_termios = ic3_set_termios, + .type = ic3_type, + .release_port = null_void_function, + .request_port = ic3_request_port, +}; + +/* + * Boot-time initialization code + */ + +static struct uart_driver ioc3_uart = { + .owner = THIS_MODULE, + .driver_name = "ioc3_serial", + .dev_name = DEVICE_NAME, + .major = DEVICE_MAJOR, + .minor = DEVICE_MINOR, + .nr = MAX_LOGICAL_PORTS +}; + +/** + * ioc3_serial_core_attach - register with serial core + * This is done during pci probing + * @is: submodule struct for this + * @idd: handle for this card + */ +static inline int ioc3_serial_core_attach( struct ioc3_submodule *is, + struct ioc3_driver_data *idd) +{ + struct ioc3_port *port; + struct uart_port *the_port; + struct ioc3_card *card_ptr = idd->data[is->id]; + int ii, phys_port; + struct pci_dev *pdev = idd->pdev; + + DPRINT_CONFIG(("%s: attach pdev 0x%p - card_ptr 0x%p\n", + __FUNCTION__, pdev, (void *)card_ptr)); + + if (!card_ptr) + return -ENODEV; + + /* once around for each logical port on this card */ + for (ii = 0; ii < LOGICAL_PORTS_PER_CARD; ii++) { + phys_port = GET_PHYSICAL_PORT(ii); + the_port = &card_ptr->ic_port[phys_port]. + icp_uart_port[GET_LOGICAL_PORT(ii)]; + port = card_ptr->ic_port[phys_port].icp_port; + port->ip_port = the_port; + + DPRINT_CONFIG(("%s: attach the_port 0x%p / port 0x%p [%d/%d]\n", + __FUNCTION__, (void *)the_port, (void *)port, + phys_port, ii)); + + /* membase, iobase and mapbase just need to be non-0 */ + the_port->membase = (unsigned char __iomem *)1; + the_port->iobase = (pdev->bus->number << 16) | ii; + the_port->line = (Num_of_ioc3_cards << 2) | ii; + the_port->mapbase = 1; + the_port->type = PORT_16550A; + the_port->fifosize = FIFO_SIZE; + the_port->ops = &ioc3_ops; + the_port->irq = idd->irq_io; + the_port->dev = &pdev->dev; + + if (uart_add_one_port(&ioc3_uart, the_port) < 0) { + printk(KERN_WARNING + "%s: unable to add port %d bus %d\n", + __FUNCTION__, the_port->line, pdev->bus->number); + } else { + DPRINT_CONFIG(("IOC3 serial port %d irq %d bus %d\n", + the_port->line, the_port->irq, pdev->bus->number)); + } + + /* all ports are rs232 for now */ + if (IS_PHYSICAL_PORT(ii)) + ioc3_set_proto(port, PROTO_RS232); + } + return 0; +} + +/** + * ioc3uart_remove - register detach function + * @is: submodule struct for this submodule + * @idd: ioc3 driver data for this submodule + */ + +static int ioc3uart_remove(struct ioc3_submodule *is, + struct ioc3_driver_data *idd) +{ + struct ioc3_card *card_ptr = idd->data[is->id]; + struct uart_port *the_port; + struct ioc3_port *port; + int ii; + + if (card_ptr) { + for (ii = 0; ii < LOGICAL_PORTS_PER_CARD; ii++) { + the_port = &card_ptr->ic_port[GET_PHYSICAL_PORT(ii)]. + icp_uart_port[GET_LOGICAL_PORT(ii)]; + if (the_port) + uart_remove_one_port(&ioc3_uart, the_port); + port = card_ptr->ic_port[GET_PHYSICAL_PORT(ii)].icp_port; + if (port && IS_PHYSICAL_PORT(ii) + && (GET_PHYSICAL_PORT(ii) == 0)) { + pci_free_consistent(port->ip_idd->pdev, + TOTAL_RING_BUF_SIZE, + (void *)port->ip_cpu_ringbuf, + port->ip_dma_ringbuf); + kfree(port); + card_ptr->ic_port[GET_PHYSICAL_PORT(ii)]. + icp_port = NULL; + } + } + kfree(card_ptr); + idd->data[is->id] = NULL; + } + return 0; +} + +/** + * ioc3uart_probe - card probe function called from shim driver + * @is: submodule struct for this submodule + * @idd: ioc3 driver data for this card + */ + +static int __devinit +ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd) +{ + struct pci_dev *pdev = idd->pdev; + struct ioc3_card *card_ptr; + int ret = 0; + struct ioc3_port *port; + struct ioc3_port *ports[PORTS_PER_CARD]; + int phys_port; + + DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, is, idd)); + + card_ptr = kmalloc(sizeof(struct ioc3_card), GFP_KERNEL); + if (!card_ptr) { + printk(KERN_WARNING "ioc3_attach_one" + ": unable to get memory for the IOC3\n"); + return -ENOMEM; + } + memset(card_ptr, 0, sizeof(struct ioc3_card)); + idd->data[is->id] = card_ptr; + Submodule_slot = is->id; + + writel(((UARTA_BASE >> 3) << SIO_CR_SER_A_BASE_SHIFT) | + ((UARTB_BASE >> 3) << SIO_CR_SER_B_BASE_SHIFT) | + (0xf << SIO_CR_CMD_PULSE_SHIFT), &idd->vma->sio_cr); + + pci_write_config_dword(pdev, PCI_LAT, 0xff00); + + /* Enable serial port mode select generic PIO pins as outputs */ + ioc3_gpcr_set(idd, GPCR_UARTA_MODESEL | GPCR_UARTB_MODESEL); + + /* Create port structures for each port */ + for (phys_port = 0; phys_port < PORTS_PER_CARD; phys_port++) { + port = kmalloc(sizeof(struct ioc3_port), GFP_KERNEL); + if (!port) { + printk(KERN_WARNING + "IOC3 serial memory not available for port\n"); + goto out4; + } + memset(port, 0, sizeof(struct ioc3_port)); + spin_lock_init(&port->ip_lock); + + /* we need to remember the previous ones, to point back to + * them farther down - setting up the ring buffers. + */ + ports[phys_port] = port; + + /* init to something useful */ + card_ptr->ic_port[phys_port].icp_port = port; + port->ip_is = is; + port->ip_idd = idd; + port->ip_baud = 9600; + port->ip_card = card_ptr; + port->ip_hooks = &hooks_array[phys_port]; + + /* Setup each port */ + if (phys_port == 0) { + port->ip_serial_regs = &idd->vma->port_a; + port->ip_uart_regs = &idd->vma->sregs.uarta; + + DPRINT_CONFIG(("%s : Port A ip_serial_regs 0x%p " + "ip_uart_regs 0x%p\n", + __FUNCTION__, + (void *)port->ip_serial_regs, + (void *)port->ip_uart_regs)); + + /* setup ring buffers */ + port->ip_cpu_ringbuf = pci_alloc_consistent(pdev, + TOTAL_RING_BUF_SIZE, &port->ip_dma_ringbuf); + + BUG_ON(!((((int64_t) port->ip_dma_ringbuf) & + (TOTAL_RING_BUF_SIZE - 1)) == 0)); + port->ip_inring = RING(port, RX_A); + port->ip_outring = RING(port, TX_A); + DPRINT_CONFIG(("%s : Port A ip_cpu_ringbuf 0x%p " + "ip_dma_ringbuf 0x%p, ip_inring 0x%p " + "ip_outring 0x%p\n", + __FUNCTION__, + (void *)port->ip_cpu_ringbuf, + (void *)port->ip_dma_ringbuf, + (void *)port->ip_inring, + (void *)port->ip_outring)); + } + else { + port->ip_serial_regs = &idd->vma->port_b; + port->ip_uart_regs = &idd->vma->sregs.uartb; + + DPRINT_CONFIG(("%s : Port B ip_serial_regs 0x%p " + "ip_uart_regs 0x%p\n", + __FUNCTION__, + (void *)port->ip_serial_regs, + (void *)port->ip_uart_regs)); + + /* share the ring buffers */ + port->ip_dma_ringbuf = + ports[phys_port - 1]->ip_dma_ringbuf; + port->ip_cpu_ringbuf = + ports[phys_port - 1]->ip_cpu_ringbuf; + port->ip_inring = RING(port, RX_B); + port->ip_outring = RING(port, TX_B); + DPRINT_CONFIG(("%s : Port B ip_cpu_ringbuf 0x%p " + "ip_dma_ringbuf 0x%p, ip_inring 0x%p " + "ip_outring 0x%p\n", + __FUNCTION__, + (void *)port->ip_cpu_ringbuf, + (void *)port->ip_dma_ringbuf, + (void *)port->ip_inring, + (void *)port->ip_outring)); + } + + DPRINT_CONFIG(("%s : port %d [addr 0x%p] card_ptr 0x%p", + __FUNCTION__, + phys_port, (void *)port, (void *)card_ptr)); + DPRINT_CONFIG((" ip_serial_regs 0x%p ip_uart_regs 0x%p\n", + (void *)port->ip_serial_regs, + (void *)port->ip_uart_regs)); + + /* Initialize the hardware for IOC3 */ + port_init(port); + + DPRINT_CONFIG(("%s: phys_port %d port 0x%p inring 0x%p " + "outring 0x%p\n", + __FUNCTION__, + phys_port, (void *)port, + (void *)port->ip_inring, + (void *)port->ip_outring)); + + } + + /* register port with the serial core */ + + if ((ret = ioc3_serial_core_attach(is, idd))) + goto out4; + + Num_of_ioc3_cards++; + + return ret; + + /* error exits that give back resources */ +out4: + kfree(card_ptr); + return ret; +} + +static struct ioc3_submodule ioc3uart_submodule = { + .name = "IOC3uart", + .probe = ioc3uart_probe, + .remove = ioc3uart_remove, + /* call .intr for both ports initially */ + .irq_mask = SIO_IR_SA | SIO_IR_SB, + .intr = ioc3uart_intr, + .owner = THIS_MODULE, +}; + +/** + * ioc3_detect - module init called, + */ +static int __devinit ioc3uart_init(void) +{ + int ret; + + /* register with serial core */ + if ((ret = uart_register_driver(&ioc3_uart)) < 0) { + printk(KERN_WARNING + "%s: Couldn't register IOC3 uart serial driver\n", + __FUNCTION__); + return ret; + } + ret = ioc3_register_submodule(&ioc3uart_submodule); + if (ret) + uart_unregister_driver(&ioc3_uart); + return ret; +} + +static void __devexit ioc3uart_exit(void) +{ + ioc3_unregister_submodule(&ioc3uart_submodule); + uart_unregister_driver(&ioc3_uart); +} + +module_init(ioc3uart_init); +module_exit(ioc3uart_exit); + +MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) "); +MODULE_DESCRIPTION("Serial PCI driver module for SGI IOC3 card"); +MODULE_LICENSE("GPL"); diff --git a/drivers/sn/Kconfig b/drivers/sn/Kconfig index 13b8d249da5..d95265b187a 100644 --- a/drivers/sn/Kconfig +++ b/drivers/sn/Kconfig @@ -17,4 +17,18 @@ config SGI_IOC4 If you have an SGI Altix with an IOC4-based I/O controller say Y. Otherwise say N. +config SGI_IOC3 + tristate "SGI IOC3 Base IO support" + depends on (IA64_GENERIC || IA64_SGI_SN2) + default m + ---help--- + This option enables basic support for the SGI IOC3-based Base IO + controller card. This option does not enable any specific + functions on such a card, but provides necessary infrastructure + for other drivers to utilize. + + If you have an SGI Altix with an IOC3-based + I/O controller or a PCI IOC3 serial card say Y. + Otherwise say N. + endmenu diff --git a/drivers/sn/Makefile b/drivers/sn/Makefile index c2a28418537..2cda011597c 100644 --- a/drivers/sn/Makefile +++ b/drivers/sn/Makefile @@ -4,3 +4,4 @@ # obj-$(CONFIG_SGI_IOC4) += ioc4.o +obj-$(CONFIG_SGI_IOC3) += ioc3.o diff --git a/drivers/sn/ioc3.c b/drivers/sn/ioc3.c new file mode 100644 index 00000000000..aaa009f4a7b --- /dev/null +++ b/drivers/sn/ioc3.c @@ -0,0 +1,851 @@ +/* + * SGI IOC3 master driver and IRQ demuxer + * + * Copyright (c) 2005 Stanislaw Skowronek + * Heavily based on similar work by: + * Brent Casavant - IOC4 master driver + * Pat Gefre - IOC3 serial port IRQ demuxer + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IOC3_PCI_SIZE 0x100000 + +static LIST_HEAD(ioc3_devices); +static int ioc3_counter; +static DECLARE_RWSEM(ioc3_devices_rwsem); + +static struct ioc3_submodule *ioc3_submodules[IOC3_MAX_SUBMODULES]; +static struct ioc3_submodule *ioc3_ethernet; +static rwlock_t ioc3_submodules_lock = RW_LOCK_UNLOCKED; + +/* NIC probing code */ + +#define GPCR_MLAN_EN 0x00200000 /* enable MCR to pin 8 */ + +static inline unsigned mcr_pack(unsigned pulse, unsigned sample) +{ + return (pulse << 10) | (sample << 2); +} + +static int nic_wait(struct ioc3_driver_data *idd) +{ + volatile unsigned mcr; + + do { + mcr = (volatile unsigned)idd->vma->mcr; + } while (!(mcr & 2)); + + return mcr & 1; +} + +static int nic_reset(struct ioc3_driver_data *idd) +{ + int presence; + unsigned long flags; + + local_irq_save(flags); + idd->vma->mcr = mcr_pack(500, 65); + presence = nic_wait(idd); + local_irq_restore(flags); + + udelay(500); + + return presence; +} + +static inline int nic_read_bit(struct ioc3_driver_data *idd) +{ + int result; + unsigned long flags; + + local_irq_save(flags); + idd->vma->mcr = mcr_pack(6, 13); + result = nic_wait(idd); + local_irq_restore(flags); + + udelay(500); + + return result; +} + +static inline void nic_write_bit(struct ioc3_driver_data *idd, int bit) +{ + if (bit) + idd->vma->mcr = mcr_pack(6, 110); + else + idd->vma->mcr = mcr_pack(80, 30); + + nic_wait(idd); +} + +static unsigned nic_read_byte(struct ioc3_driver_data *idd) +{ + unsigned result = 0; + int i; + + for (i = 0; i < 8; i++) + result = (result >> 1) | (nic_read_bit(idd) << 7); + + return result; +} + +static void nic_write_byte(struct ioc3_driver_data *idd, int byte) +{ + int i, bit; + + for (i = 8; i; i--) { + bit = byte & 1; + byte >>= 1; + + nic_write_bit(idd, bit); + } +} + +static unsigned long +nic_find(struct ioc3_driver_data *idd, int *last, unsigned long addr) +{ + int a, b, index, disc; + + nic_reset(idd); + + /* Search ROM. */ + nic_write_byte(idd, 0xF0); + + /* Algorithm from ``Book of iButton Standards''. */ + for (index = 0, disc = 0; index < 64; index++) { + a = nic_read_bit(idd); + b = nic_read_bit(idd); + + if (a && b) { + printk(KERN_WARNING "IOC3 NIC search failed.\n"); + *last = 0; + return 0; + } + + if (!a && !b) { + if (index == *last) { + addr |= 1UL << index; + } else if (index > *last) { + addr &= ~(1UL << index); + disc = index; + } else if ((addr & (1UL << index)) == 0) + disc = index; + nic_write_bit(idd, (addr>>index)&1); + continue; + } else { + if (a) + addr |= 1UL << index; + else + addr &= ~(1UL << index); + nic_write_bit(idd, a); + continue; + } + } + *last = disc; + return addr; +} + +static void nic_addr(struct ioc3_driver_data *idd, unsigned long addr) +{ + int index; + + nic_reset(idd); + nic_write_byte(idd, 0xF0); + for (index = 0; index < 64; index++) { + nic_read_bit(idd); + nic_read_bit(idd); + nic_write_bit(idd, (addr>>index)&1); + } +} + +static void crc16_byte(unsigned int *crc, unsigned char db) +{ + int i; + + for(i=0;i<8;i++) { + *crc <<= 1; + if((db^(*crc>>16)) & 1) + *crc ^= 0x8005; + db >>= 1; + } + *crc &= 0xFFFF; +} + +static unsigned int crc16_area(unsigned char *dbs, int size, unsigned int crc) +{ + while(size--) + crc16_byte(&crc, *(dbs++)); + return crc; +} + +static void crc8_byte(unsigned int *crc, unsigned char db) +{ + int i,f; + + for(i=0;i<8;i++) { + f = (*crc ^ db) & 1; + *crc >>= 1; + db >>= 1; + if(f) + *crc ^= 0x8c; + } + *crc &= 0xff; +} + +static unsigned int crc8_addr(unsigned long addr) +{ + int i; + unsigned int crc = 0x00; + + for(i=0;i<8;i++) + crc8_byte(&crc, addr>>(i<<3)); + return crc; +} + +static void +read_redir_page(struct ioc3_driver_data *idd, unsigned long addr, int page, + unsigned char *redir, unsigned char *data) +{ + int loops = 16, i; + + while(redir[page] != 0xFF) { + page = redir[page]^0xFF; + loops--; + if(loops<0) { + printk(KERN_ERR "IOC3: NIC circular redirection\n"); + return; + } + } + loops = 3; + while(loops>0) { + nic_addr(idd, addr); + nic_write_byte(idd, 0xF0); + nic_write_byte(idd, (page << 5) & 0xE0); + nic_write_byte(idd, (page >> 3) & 0x1F); + for(i=0;i<0x20;i++) + data[i] = nic_read_byte(idd); + if(crc16_area(data, 0x20, 0x0000) == 0x800d) + return; + loops--; + } + printk(KERN_ERR "IOC3: CRC error in data page\n"); + for(i=0;i<0x20;i++) + data[i] = 0x00; +} + +static void +read_redir_map(struct ioc3_driver_data *idd, unsigned long addr, + unsigned char *redir) +{ + int i,j,loops = 3,crc_ok; + unsigned int crc; + + while(loops>0) { + crc_ok = 1; + nic_addr(idd, addr); + nic_write_byte(idd, 0xAA); + nic_write_byte(idd, 0x00); + nic_write_byte(idd, 0x01); + for(i=0;i<64;i+=8) { + for(j=0;j<8;j++) + redir[i+j] = nic_read_byte(idd); + crc = crc16_area(redir+i, 8, (i==0)?0x8707:0x0000); + crc16_byte(&crc, nic_read_byte(idd)); + crc16_byte(&crc, nic_read_byte(idd)); + if(crc != 0x800d) + crc_ok = 0; + } + if(crc_ok) + return; + loops--; + } + printk(KERN_ERR "IOC3: CRC error in redirection page\n"); + for(i=0;i<64;i++) + redir[i] = 0xFF; +} + +static void read_nic(struct ioc3_driver_data *idd, unsigned long addr) +{ + unsigned char redir[64]; + unsigned char data[64],part[32]; + int i,j; + + /* read redirections */ + read_redir_map(idd, addr, redir); + /* read data pages */ + read_redir_page(idd, addr, 0, redir, data); + read_redir_page(idd, addr, 1, redir, data+32); + /* assemble the part # */ + j=0; + for(i=0;i<19;i++) + if(data[i+11] != ' ') + part[j++] = data[i+11]; + for(i=0;i<6;i++) + if(data[i+32] != ' ') + part[j++] = data[i+32]; + part[j] = 0; + /* skip Octane power supplies */ + if(!strncmp(part, "060-0035-", 9)) + return; + if(!strncmp(part, "060-0038-", 9)) + return; + strcpy(idd->nic_part, part); + /* assemble the serial # */ + j=0; + for(i=0;i<10;i++) + if(data[i+1] != ' ') + idd->nic_serial[j++] = data[i+1]; + idd->nic_serial[j] = 0; +} + +static void read_mac(struct ioc3_driver_data *idd, unsigned long addr) +{ + int i, loops = 3; + unsigned char data[13]; + + while(loops>0) { + nic_addr(idd, addr); + nic_write_byte(idd, 0xF0); + nic_write_byte(idd, 0x00); + nic_write_byte(idd, 0x00); + nic_read_byte(idd); + for(i=0;i<13;i++) + data[i] = nic_read_byte(idd); + if(crc16_area(data, 13, 0x0000) == 0x800d) { + for(i=10;i>4;i--) + idd->nic_mac[10-i] = data[i]; + return; + } + loops--; + } + printk(KERN_ERR "IOC3: CRC error in MAC address\n"); + for(i=0;i<6;i++) + idd->nic_mac[i] = 0x00; +} + +static void probe_nic(struct ioc3_driver_data *idd) +{ + int save = 0, loops = 3; + unsigned long first, addr; + + idd->vma->gpcr_s = GPCR_MLAN_EN; + + while(loops>0) { + idd->nic_part[0] = 0; + idd->nic_serial[0] = 0; + addr = first = nic_find(idd, &save, 0); + if(!first) + return; + while(1) { + if(crc8_addr(addr)) + break; + else { + switch(addr & 0xFF) { + case 0x0B: + read_nic(idd, addr); + break; + case 0x09: + case 0x89: + case 0x91: + read_mac(idd, addr); + break; + } + } + addr = nic_find(idd, &save, addr); + if(addr == first) + return; + } + loops--; + } + printk(KERN_ERR "IOC3: CRC error in NIC address\n"); +} + +/* Interrupts */ + +static inline void +write_ireg(struct ioc3_driver_data *idd, uint32_t val, int which) +{ + unsigned long flags; + + spin_lock_irqsave(&idd->ir_lock, flags); + switch (which) { + case IOC3_W_IES: + writel(val, &idd->vma->sio_ies); + break; + case IOC3_W_IEC: + writel(val, &idd->vma->sio_iec); + break; + } + spin_unlock_irqrestore(&idd->ir_lock, flags); +} +static inline uint32_t get_pending_intrs(struct ioc3_driver_data *idd) +{ + unsigned long flag; + uint32_t intrs = 0; + + spin_lock_irqsave(&idd->ir_lock, flag); + intrs = readl(&idd->vma->sio_ir); + intrs &= readl(&idd->vma->sio_ies); + spin_unlock_irqrestore(&idd->ir_lock, flag); + return intrs; +} + +static irqreturn_t ioc3_intr_io(int irq, void *arg, struct pt_regs *regs) +{ + unsigned long flags; + struct ioc3_driver_data *idd = (struct ioc3_driver_data *)arg; + int handled = 1, id; + unsigned int pending; + + read_lock_irqsave(&ioc3_submodules_lock, flags); + + if(idd->dual_irq && idd->vma->eisr) { + /* send Ethernet IRQ to the driver */ + if(ioc3_ethernet && idd->active[ioc3_ethernet->id] && + ioc3_ethernet->intr) { + handled = handled && !ioc3_ethernet->intr(ioc3_ethernet, + idd, 0, regs); + } + } + pending = get_pending_intrs(idd); /* look at the IO IRQs */ + + for(id=0;idactive[id] && ioc3_submodules[id] + && (pending & ioc3_submodules[id]->irq_mask) + && ioc3_submodules[id]->intr) { + write_ireg(idd, ioc3_submodules[id]->irq_mask, + IOC3_W_IEC); + if(!ioc3_submodules[id]->intr(ioc3_submodules[id], + idd, pending & ioc3_submodules[id]->irq_mask, + regs)) + pending &= ~ioc3_submodules[id]->irq_mask; + if (ioc3_submodules[id]->reset_mask) + write_ireg(idd, ioc3_submodules[id]->irq_mask, + IOC3_W_IES); + } + } + read_unlock_irqrestore(&ioc3_submodules_lock, flags); + if(pending) { + printk(KERN_WARNING + "IOC3: Pending IRQs 0x%08x discarded and disabled\n",pending); + write_ireg(idd, pending, IOC3_W_IEC); + handled = 1; + } + return handled?IRQ_HANDLED:IRQ_NONE; +} + +static irqreturn_t ioc3_intr_eth(int irq, void *arg, struct pt_regs *regs) +{ + unsigned long flags; + struct ioc3_driver_data *idd = (struct ioc3_driver_data *)arg; + int handled = 1; + + if(!idd->dual_irq) + return IRQ_NONE; + read_lock_irqsave(&ioc3_submodules_lock, flags); + if(ioc3_ethernet && idd->active[ioc3_ethernet->id] + && ioc3_ethernet->intr) + handled = handled && !ioc3_ethernet->intr(ioc3_ethernet, idd, 0, + regs); + read_unlock_irqrestore(&ioc3_submodules_lock, flags); + return handled?IRQ_HANDLED:IRQ_NONE; +} + +void ioc3_enable(struct ioc3_submodule *is, + struct ioc3_driver_data *idd, unsigned int irqs) +{ + write_ireg(idd, irqs & is->irq_mask, IOC3_W_IES); +} + +void ioc3_ack(struct ioc3_submodule *is, struct ioc3_driver_data *idd, + unsigned int irqs) +{ + writel(irqs & is->irq_mask, &idd->vma->sio_ir); +} + +void ioc3_disable(struct ioc3_submodule *is, + struct ioc3_driver_data *idd, unsigned int irqs) +{ + write_ireg(idd, irqs & is->irq_mask, IOC3_W_IEC); +} + +void ioc3_gpcr_set(struct ioc3_driver_data *idd, unsigned int val) +{ + unsigned long flags; + spin_lock_irqsave(&idd->gpio_lock, flags); + writel(val, &idd->vma->gpcr_s); + spin_unlock_irqrestore(&idd->gpio_lock, flags); +} + +/* Keep it simple, stupid! */ +static int find_slot(void **tab, int max) +{ + int i; + for(i=0;iethernet) { + if(ioc3_ethernet==NULL) + ioc3_ethernet=is; + else + printk(KERN_WARNING + "IOC3 Ethernet module already registered!\n"); + } + } + write_unlock_irqrestore(&ioc3_submodules_lock, flags); + + if(alloc_id == -1) { + printk(KERN_WARNING "Increase IOC3_MAX_SUBMODULES!\n"); + return -ENOMEM; + } + + is->id=alloc_id; + + /* Initialize submodule for each IOC3 */ + if (!is->probe) + return 0; + + down_read(&ioc3_devices_rwsem); + list_for_each_entry(idd, &ioc3_devices, list) { + /* set to 1 for IRQs in probe */ + idd->active[alloc_id] = 1; + idd->active[alloc_id] = !is->probe(is, idd); + } + up_read(&ioc3_devices_rwsem); + + return 0; +} + +/* Unregister an IOC3 submodule */ +void ioc3_unregister_submodule(struct ioc3_submodule *is) +{ + struct ioc3_driver_data *idd; + unsigned long flags; + + write_lock_irqsave(&ioc3_submodules_lock, flags); + if(ioc3_submodules[is->id]==is) + ioc3_submodules[is->id]=NULL; + else + printk(KERN_WARNING + "IOC3 submodule %s has wrong ID.\n",is->name); + if(ioc3_ethernet==is) + ioc3_ethernet = NULL; + write_unlock_irqrestore(&ioc3_submodules_lock, flags); + + /* Remove submodule for each IOC3 */ + down_read(&ioc3_devices_rwsem); + list_for_each_entry(idd, &ioc3_devices, list) + if(idd->active[is->id]) { + if(is->remove) + if(is->remove(is, idd)) + printk(KERN_WARNING + "%s: IOC3 submodule %s remove failed " + "for pci_dev %s.\n", + __FUNCTION__, module_name(is->owner), + pci_name(idd->pdev)); + idd->active[is->id] = 0; + if(is->irq_mask) + write_ireg(idd, is->irq_mask, IOC3_W_IEC); + } + up_read(&ioc3_devices_rwsem); +} + +/********************* + * Device management * + *********************/ + +static char * +ioc3_class_names[]={"unknown", "IP27 BaseIO", "IP30 system", "MENET 1/2/3", + "MENET 4", "CADduo", "Altix Serial"}; + +static int ioc3_class(struct ioc3_driver_data *idd) +{ + int res = IOC3_CLASS_NONE; + /* NIC-based logic */ + if(!strncmp(idd->nic_part, "030-0891-", 9)) + res = IOC3_CLASS_BASE_IP30; + if(!strncmp(idd->nic_part, "030-1155-", 9)) + res = IOC3_CLASS_CADDUO; + if(!strncmp(idd->nic_part, "030-1657-", 9)) + res = IOC3_CLASS_SERIAL; + if(!strncmp(idd->nic_part, "030-1664-", 9)) + res = IOC3_CLASS_SERIAL; + /* total random heuristics */ +#ifdef CONFIG_SGI_IP27 + if(!idd->nic_part[0]) + res = IOC3_CLASS_BASE_IP27; +#endif + /* print educational message */ + printk(KERN_INFO "IOC3 part: [%s], serial: [%s] => class %s\n", + idd->nic_part, idd->nic_serial, ioc3_class_names[res]); + return res; +} +/* Adds a new instance of an IOC3 card */ +static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) +{ + struct ioc3_driver_data *idd; + uint32_t pcmd; + int ret, id; + + /* Enable IOC3 and take ownership of it */ + if ((ret = pci_enable_device(pdev))) { + printk(KERN_WARNING + "%s: Failed to enable IOC3 device for pci_dev %s.\n", + __FUNCTION__, pci_name(pdev)); + goto out; + } + pci_set_master(pdev); + +#ifdef USE_64BIT_DMA + ret = pci_set_dma_mask(pdev, 0xffffffffffffffffULL); + if (!ret) { + ret = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL); + if (ret < 0) { + printk(KERN_WARNING "%s: Unable to obtain 64 bit DMA " + "for consistent allocations\n", + __FUNCTION__); + } + } +#endif + + /* Set up per-IOC3 data */ + idd = kmalloc(sizeof(struct ioc3_driver_data), GFP_KERNEL); + if (!idd) { + printk(KERN_WARNING + "%s: Failed to allocate IOC3 data for pci_dev %s.\n", + __FUNCTION__, pci_name(pdev)); + ret = -ENODEV; + goto out_idd; + } + memset(idd, 0, sizeof(struct ioc3_driver_data)); + spin_lock_init(&idd->ir_lock); + spin_lock_init(&idd->gpio_lock); + idd->pdev = pdev; + + /* Map all IOC3 registers. These are shared between subdevices + * so the main IOC3 module manages them. + */ + idd->pma = pci_resource_start(pdev, 0); + if (!idd->pma) { + printk(KERN_WARNING + "%s: Unable to find IOC3 resource " + "for pci_dev %s.\n", + __FUNCTION__, pci_name(pdev)); + ret = -ENODEV; + goto out_pci; + } + if (!request_region(idd->pma, IOC3_PCI_SIZE, "ioc3")) { + printk(KERN_WARNING + "%s: Unable to request IOC3 region " + "for pci_dev %s.\n", + __FUNCTION__, pci_name(pdev)); + ret = -ENODEV; + goto out_pci; + } + idd->vma = ioremap(idd->pma, IOC3_PCI_SIZE); + if (!idd->vma) { + printk(KERN_WARNING + "%s: Unable to remap IOC3 region " + "for pci_dev %s.\n", + __FUNCTION__, pci_name(pdev)); + ret = -ENODEV; + goto out_misc_region; + } + + /* Track PCI-device specific data */ + pci_set_drvdata(pdev, idd); + down_write(&ioc3_devices_rwsem); + list_add(&idd->list, &ioc3_devices); + idd->id = ioc3_counter++; + up_write(&ioc3_devices_rwsem); + + idd->gpdr_shadow = idd->vma->gpdr; + + /* Read IOC3 NIC contents */ + probe_nic(idd); + + /* Detect IOC3 class */ + idd->class = ioc3_class(idd); + + /* Initialize IOC3 */ + pci_read_config_dword(pdev, PCI_COMMAND, &pcmd); + pci_write_config_dword(pdev, PCI_COMMAND, + pcmd | PCI_COMMAND_MEMORY | + PCI_COMMAND_PARITY | PCI_COMMAND_SERR | + PCI_SCR_DROP_MODE_EN); + + write_ireg(idd, ~0, IOC3_W_IEC); + writel(~0, &idd->vma->sio_ir); + + /* Set up IRQs */ + if(idd->class == IOC3_CLASS_BASE_IP30 + || idd->class == IOC3_CLASS_BASE_IP27) { + writel(0, &idd->vma->eier); + writel(~0, &idd->vma->eisr); + + idd->dual_irq = 1; + if (!request_irq(pdev->irq, ioc3_intr_eth, SA_SHIRQ, + "ioc3-eth", (void *)idd)) { + idd->irq_eth = pdev->irq; + } else { + printk(KERN_WARNING + "%s : request_irq fails for IRQ 0x%x\n ", + __FUNCTION__, pdev->irq); + } + if (!request_irq(pdev->irq+2, ioc3_intr_io, SA_SHIRQ, + "ioc3-io", (void *)idd)) { + idd->irq_io = pdev->irq+2; + } else { + printk(KERN_WARNING + "%s : request_irq fails for IRQ 0x%x\n ", + __FUNCTION__, pdev->irq+2); + } + } else { + if (!request_irq(pdev->irq, ioc3_intr_io, SA_SHIRQ, + "ioc3", (void *)idd)) { + idd->irq_io = pdev->irq; + } else { + printk(KERN_WARNING + "%s : request_irq fails for IRQ 0x%x\n ", + __FUNCTION__, pdev->irq); + } + } + + /* Add this IOC3 to all submodules */ + read_lock(&ioc3_submodules_lock); + for(id=0;idprobe) { + idd->active[id] = 1; + idd->active[id] = !ioc3_submodules[id]->probe + (ioc3_submodules[id], idd); + } + read_unlock(&ioc3_submodules_lock); + + printk(KERN_INFO "IOC3 Master Driver loaded for %s\n", pci_name(pdev)); + + return 0; + +out_misc_region: + release_region(idd->pma, IOC3_PCI_SIZE); +out_pci: + kfree(idd); +out_idd: + pci_disable_device(pdev); +out: + return ret; +} + +/* Removes a particular instance of an IOC3 card. */ +static void ioc3_remove(struct pci_dev *pdev) +{ + int id; + struct ioc3_driver_data *idd; + + idd = pci_get_drvdata(pdev); + + /* Remove this IOC3 from all submodules */ + read_lock(&ioc3_submodules_lock); + for(id=0;idactive[id]) { + if(ioc3_submodules[id] && ioc3_submodules[id]->remove) + if(ioc3_submodules[id]->remove(ioc3_submodules[id], + idd)) + printk(KERN_WARNING + "%s: IOC3 submodule 0x%s remove failed " + "for pci_dev %s.\n", + __FUNCTION__, + module_name(ioc3_submodules[id]->owner), + pci_name(pdev)); + idd->active[id] = 0; + } + read_unlock(&ioc3_submodules_lock); + + /* Clear and disable all IRQs */ + write_ireg(idd, ~0, IOC3_W_IEC); + writel(~0, &idd->vma->sio_ir); + + /* Release resources */ + free_irq(idd->irq_io, (void *)idd); + if(idd->dual_irq) + free_irq(idd->irq_eth, (void *)idd); + iounmap(idd->vma); + release_region(idd->pma, IOC3_PCI_SIZE); + + /* Disable IOC3 and relinquish */ + pci_disable_device(pdev); + + /* Remove and free driver data */ + down_write(&ioc3_devices_rwsem); + list_del(&idd->list); + up_write(&ioc3_devices_rwsem); + kfree(idd); +} + +static struct pci_device_id ioc3_id_table[] = { + {PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, PCI_ANY_ID, PCI_ANY_ID}, + {0} +}; + +static struct pci_driver ioc3_driver = { + .name = "IOC3", + .id_table = ioc3_id_table, + .probe = ioc3_probe, + .remove = ioc3_remove, +}; + +MODULE_DEVICE_TABLE(pci, ioc3_id_table); + +/********************* + * Module management * + *********************/ + +/* Module load */ +static int __devinit ioc3_init(void) +{ + if (ia64_platform_is("sn2")) + return pci_register_driver(&ioc3_driver); + return 0; +} + +/* Module unload */ +static void __devexit ioc3_exit(void) +{ + pci_unregister_driver(&ioc3_driver); +} + +module_init(ioc3_init); +module_exit(ioc3_exit); + +MODULE_AUTHOR("Stanislaw Skowronek "); +MODULE_DESCRIPTION("PCI driver for SGI IOC3"); +MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL(ioc3_register_submodule); +EXPORT_SYMBOL(ioc3_unregister_submodule); +EXPORT_SYMBOL(ioc3_ack); +EXPORT_SYMBOL(ioc3_gpcr_set); +EXPORT_SYMBOL(ioc3_disable); +EXPORT_SYMBOL(ioc3_enable); diff --git a/include/asm-ia64/sn/ioc3.h b/include/asm-ia64/sn/ioc3.h new file mode 100644 index 00000000000..95ed6cc83cf --- /dev/null +++ b/include/asm-ia64/sn/ioc3.h @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2005 Silicon Graphics, Inc. + */ +#ifndef IA64_SN_IOC3_H +#define IA64_SN_IOC3_H + +/* serial port register map */ +struct ioc3_serialregs { + uint32_t sscr; + uint32_t stpir; + uint32_t stcir; + uint32_t srpir; + uint32_t srcir; + uint32_t srtr; + uint32_t shadow; +}; + +/* SUPERIO uart register map */ +struct ioc3_uartregs { + char iu_lcr; + union { + char iir; /* read only */ + char fcr; /* write only */ + } u3; + union { + char ier; /* DLAB == 0 */ + char dlm; /* DLAB == 1 */ + } u2; + union { + char rbr; /* read only, DLAB == 0 */ + char thr; /* write only, DLAB == 0 */ + char dll; /* DLAB == 1 */ + } u1; + char iu_scr; + char iu_msr; + char iu_lsr; + char iu_mcr; +}; + +#define iu_rbr u1.rbr +#define iu_thr u1.thr +#define iu_dll u1.dll +#define iu_ier u2.ier +#define iu_dlm u2.dlm +#define iu_iir u3.iir +#define iu_fcr u3.fcr + +struct ioc3_sioregs { + char fill[0x170]; + struct ioc3_uartregs uartb; + struct ioc3_uartregs uarta; +}; + +/* PCI IO/mem space register map */ +struct ioc3 { + uint32_t pci_id; + uint32_t pci_scr; + uint32_t pci_rev; + uint32_t pci_lat; + uint32_t pci_addr; + uint32_t pci_err_addr_l; + uint32_t pci_err_addr_h; + + uint32_t sio_ir; + /* these registers are read-only for general kernel code. To + * modify them use the functions in ioc3.c + */ + uint32_t sio_ies; + uint32_t sio_iec; + uint32_t sio_cr; + uint32_t int_out; + uint32_t mcr; + uint32_t gpcr_s; + uint32_t gpcr_c; + uint32_t gpdr; + uint32_t gppr[9]; + char fill[0x4c]; + + /* serial port registers */ + uint32_t sbbr_h; + uint32_t sbbr_l; + + struct ioc3_serialregs port_a; + struct ioc3_serialregs port_b; + char fill1[0x1ff10]; + /* superio registers */ + struct ioc3_sioregs sregs; +}; + +/* These don't exist on the ioc3 serial card... */ +#define eier fill1[8] +#define eisr fill1[4] + +#define PCI_LAT 0xc /* Latency Timer */ +#define PCI_SCR_DROP_MODE_EN 0x00008000 /* drop pios on parity err */ +#define UARTA_BASE 0x178 +#define UARTB_BASE 0x170 + + +/* bitmasks for serial RX status byte */ +#define RXSB_OVERRUN 0x01 /* char(s) lost */ +#define RXSB_PAR_ERR 0x02 /* parity error */ +#define RXSB_FRAME_ERR 0x04 /* framing error */ +#define RXSB_BREAK 0x08 /* break character */ +#define RXSB_CTS 0x10 /* state of CTS */ +#define RXSB_DCD 0x20 /* state of DCD */ +#define RXSB_MODEM_VALID 0x40 /* DCD, CTS and OVERRUN are valid */ +#define RXSB_DATA_VALID 0x80 /* FRAME_ERR PAR_ERR & BREAK valid */ + +/* bitmasks for serial TX control byte */ +#define TXCB_INT_WHEN_DONE 0x20 /* interrupt after this byte is sent */ +#define TXCB_INVALID 0x00 /* byte is invalid */ +#define TXCB_VALID 0x40 /* byte is valid */ +#define TXCB_MCR 0x80 /* data<7:0> to modem cntrl register */ +#define TXCB_DELAY 0xc0 /* delay data<7:0> mSec */ + +/* bitmasks for SBBR_L */ +#define SBBR_L_SIZE 0x00000001 /* 0 1KB rings, 1 4KB rings */ + +/* bitmasks for SSCR_ */ +#define SSCR_RX_THRESHOLD 0x000001ff /* hiwater mark */ +#define SSCR_TX_TIMER_BUSY 0x00010000 /* TX timer in progress */ +#define SSCR_HFC_EN 0x00020000 /* h/w flow cntrl enabled */ +#define SSCR_RX_RING_DCD 0x00040000 /* postRX record on delta-DCD */ +#define SSCR_RX_RING_CTS 0x00080000 /* postRX record on delta-CTS */ +#define SSCR_HIGH_SPD 0x00100000 /* 4X speed */ +#define SSCR_DIAG 0x00200000 /* bypass clock divider */ +#define SSCR_RX_DRAIN 0x08000000 /* drain RX buffer to memory */ +#define SSCR_DMA_EN 0x10000000 /* enable ring buffer DMA */ +#define SSCR_DMA_PAUSE 0x20000000 /* pause DMA */ +#define SSCR_PAUSE_STATE 0x40000000 /* set when PAUSE takes effect*/ +#define SSCR_RESET 0x80000000 /* reset DMA channels */ + +/* all producer/comsumer pointers are the same bitfield */ +#define PROD_CONS_PTR_4K 0x00000ff8 /* for 4K buffers */ +#define PROD_CONS_PTR_1K 0x000003f8 /* for 1K buffers */ +#define PROD_CONS_PTR_OFF 3 + +/* bitmasks for SRCIR_ */ +#define SRCIR_ARM 0x80000000 /* arm RX timer */ + +/* bitmasks for SHADOW_ */ +#define SHADOW_DR 0x00000001 /* data ready */ +#define SHADOW_OE 0x00000002 /* overrun error */ +#define SHADOW_PE 0x00000004 /* parity error */ +#define SHADOW_FE 0x00000008 /* framing error */ +#define SHADOW_BI 0x00000010 /* break interrupt */ +#define SHADOW_THRE 0x00000020 /* transmit holding reg empty */ +#define SHADOW_TEMT 0x00000040 /* transmit shift reg empty */ +#define SHADOW_RFCE 0x00000080 /* char in RX fifo has error */ +#define SHADOW_DCTS 0x00010000 /* delta clear to send */ +#define SHADOW_DDCD 0x00080000 /* delta data carrier detect */ +#define SHADOW_CTS 0x00100000 /* clear to send */ +#define SHADOW_DCD 0x00800000 /* data carrier detect */ +#define SHADOW_DTR 0x01000000 /* data terminal ready */ +#define SHADOW_RTS 0x02000000 /* request to send */ +#define SHADOW_OUT1 0x04000000 /* 16550 OUT1 bit */ +#define SHADOW_OUT2 0x08000000 /* 16550 OUT2 bit */ +#define SHADOW_LOOP 0x10000000 /* loopback enabled */ + +/* bitmasks for SRTR_ */ +#define SRTR_CNT 0x00000fff /* reload value for RX timer */ +#define SRTR_CNT_VAL 0x0fff0000 /* current value of RX timer */ +#define SRTR_CNT_VAL_SHIFT 16 +#define SRTR_HZ 16000 /* SRTR clock frequency */ + +/* bitmasks for SIO_IR, SIO_IEC and SIO_IES */ +#define SIO_IR_SA_TX_MT 0x00000001 /* Serial port A TX empty */ +#define SIO_IR_SA_RX_FULL 0x00000002 /* port A RX buf full */ +#define SIO_IR_SA_RX_HIGH 0x00000004 /* port A RX hiwat */ +#define SIO_IR_SA_RX_TIMER 0x00000008 /* port A RX timeout */ +#define SIO_IR_SA_DELTA_DCD 0x00000010 /* port A delta DCD */ +#define SIO_IR_SA_DELTA_CTS 0x00000020 /* port A delta CTS */ +#define SIO_IR_SA_INT 0x00000040 /* port A pass-thru intr */ +#define SIO_IR_SA_TX_EXPLICIT 0x00000080 /* port A explicit TX thru */ +#define SIO_IR_SA_MEMERR 0x00000100 /* port A PCI error */ +#define SIO_IR_SB_TX_MT 0x00000200 +#define SIO_IR_SB_RX_FULL 0x00000400 +#define SIO_IR_SB_RX_HIGH 0x00000800 +#define SIO_IR_SB_RX_TIMER 0x00001000 +#define SIO_IR_SB_DELTA_DCD 0x00002000 +#define SIO_IR_SB_DELTA_CTS 0x00004000 +#define SIO_IR_SB_INT 0x00008000 +#define SIO_IR_SB_TX_EXPLICIT 0x00010000 +#define SIO_IR_SB_MEMERR 0x00020000 +#define SIO_IR_PP_INT 0x00040000 /* P port pass-thru intr */ +#define SIO_IR_PP_INTA 0x00080000 /* PP context A thru */ +#define SIO_IR_PP_INTB 0x00100000 /* PP context B thru */ +#define SIO_IR_PP_MEMERR 0x00200000 /* PP PCI error */ +#define SIO_IR_KBD_INT 0x00400000 /* kbd/mouse intr */ +#define SIO_IR_RT_INT 0x08000000 /* RT output pulse */ +#define SIO_IR_GEN_INT1 0x10000000 /* RT input pulse */ +#define SIO_IR_GEN_INT_SHIFT 28 + +/* per device interrupt masks */ +#define SIO_IR_SA (SIO_IR_SA_TX_MT | \ + SIO_IR_SA_RX_FULL | \ + SIO_IR_SA_RX_HIGH | \ + SIO_IR_SA_RX_TIMER | \ + SIO_IR_SA_DELTA_DCD | \ + SIO_IR_SA_DELTA_CTS | \ + SIO_IR_SA_INT | \ + SIO_IR_SA_TX_EXPLICIT | \ + SIO_IR_SA_MEMERR) + +#define SIO_IR_SB (SIO_IR_SB_TX_MT | \ + SIO_IR_SB_RX_FULL | \ + SIO_IR_SB_RX_HIGH | \ + SIO_IR_SB_RX_TIMER | \ + SIO_IR_SB_DELTA_DCD | \ + SIO_IR_SB_DELTA_CTS | \ + SIO_IR_SB_INT | \ + SIO_IR_SB_TX_EXPLICIT | \ + SIO_IR_SB_MEMERR) + +#define SIO_IR_PP (SIO_IR_PP_INT | SIO_IR_PP_INTA | \ + SIO_IR_PP_INTB | SIO_IR_PP_MEMERR) +#define SIO_IR_RT (SIO_IR_RT_INT | SIO_IR_GEN_INT1) + +/* bitmasks for SIO_CR */ +#define SIO_CR_CMD_PULSE_SHIFT 15 +#define SIO_CR_SER_A_BASE_SHIFT 1 +#define SIO_CR_SER_B_BASE_SHIFT 8 +#define SIO_CR_ARB_DIAG 0x00380000 /* cur !enet PCI requet (ro) */ +#define SIO_CR_ARB_DIAG_TXA 0x00000000 +#define SIO_CR_ARB_DIAG_RXA 0x00080000 +#define SIO_CR_ARB_DIAG_TXB 0x00100000 +#define SIO_CR_ARB_DIAG_RXB 0x00180000 +#define SIO_CR_ARB_DIAG_PP 0x00200000 +#define SIO_CR_ARB_DIAG_IDLE 0x00400000 /* 0 -> active request (ro) */ + +/* defs for some of the generic I/O pins */ +#define GPCR_PHY_RESET 0x20 /* pin is output to PHY reset */ +#define GPCR_UARTB_MODESEL 0x40 /* pin is output to port B mode sel */ +#define GPCR_UARTA_MODESEL 0x80 /* pin is output to port A mode sel */ + +#define GPPR_PHY_RESET_PIN 5 /* GIO pin controlling phy reset */ +#define GPPR_UARTB_MODESEL_PIN 6 /* GIO pin cntrling uartb modeselect */ +#define GPPR_UARTA_MODESEL_PIN 7 /* GIO pin cntrling uarta modeselect */ + +#endif /* IA64_SN_IOC3_H */ diff --git a/include/linux/ioc3.h b/include/linux/ioc3.h new file mode 100644 index 00000000000..e7906a72a4f --- /dev/null +++ b/include/linux/ioc3.h @@ -0,0 +1,93 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 2005 Stanislaw Skowronek + */ + +#ifndef _LINUX_IOC3_H +#define _LINUX_IOC3_H + +#include + +#define IOC3_MAX_SUBMODULES 32 + +#define IOC3_CLASS_NONE 0 +#define IOC3_CLASS_BASE_IP27 1 +#define IOC3_CLASS_BASE_IP30 2 +#define IOC3_CLASS_MENET_123 3 +#define IOC3_CLASS_MENET_4 4 +#define IOC3_CLASS_CADDUO 5 +#define IOC3_CLASS_SERIAL 6 + +/* One of these per IOC3 */ +struct ioc3_driver_data { + struct list_head list; + int id; /* IOC3 sequence number */ + /* PCI mapping */ + unsigned long pma; /* physical address */ + struct __iomem ioc3 *vma; /* pointer to registers */ + struct pci_dev *pdev; /* PCI device */ + /* IRQ stuff */ + int dual_irq; /* set if separate IRQs are used */ + int irq_io, irq_eth; /* IRQ numbers */ + /* GPIO magic */ + spinlock_t gpio_lock; + unsigned int gpdr_shadow; + /* NIC identifiers */ + char nic_part[32]; + char nic_serial[16]; + char nic_mac[6]; + /* submodule set */ + int class; + void *data[IOC3_MAX_SUBMODULES]; /* for submodule use */ + int active[IOC3_MAX_SUBMODULES]; /* set if probe succeeds */ + /* is_ir_lock must be held while + * modifying sio_ie values, so + * we can be sure that sio_ie is + * not changing when we read it + * along with sio_ir. + */ + spinlock_t ir_lock; /* SIO_IE[SC] mod lock */ +}; + +/* One per submodule */ +struct ioc3_submodule { + char *name; /* descriptive submodule name */ + struct module *owner; /* owning kernel module */ + int ethernet; /* set for ethernet drivers */ + int (*probe) (struct ioc3_submodule *, struct ioc3_driver_data *); + int (*remove) (struct ioc3_submodule *, struct ioc3_driver_data *); + int id; /* assigned by IOC3, index for the "data" array */ + /* IRQ stuff */ + unsigned int irq_mask; /* IOC3 IRQ mask, leave clear for Ethernet */ + int reset_mask; /* non-zero if you want the ioc3.c module to reset interrupts */ + int (*intr) (struct ioc3_submodule *, struct ioc3_driver_data *, unsigned int, struct pt_regs *); + /* private submodule data */ + void *data; /* assigned by submodule */ +}; + +/********************************** + * Functions needed by submodules * + **********************************/ + +#define IOC3_W_IES 0 +#define IOC3_W_IEC 1 + +/* registers a submodule for all existing and future IOC3 chips */ +extern int ioc3_register_submodule(struct ioc3_submodule *); +/* unregisters a submodule */ +extern void ioc3_unregister_submodule(struct ioc3_submodule *); +/* enables IRQs indicated by irq_mask for a specified IOC3 chip */ +extern void ioc3_enable(struct ioc3_submodule *, struct ioc3_driver_data *, unsigned int); +/* ackowledges specified IRQs */ +extern void ioc3_ack(struct ioc3_submodule *, struct ioc3_driver_data *, unsigned int); +/* disables IRQs indicated by irq_mask for a specified IOC3 chip */ +extern void ioc3_disable(struct ioc3_submodule *, struct ioc3_driver_data *, unsigned int); +/* atomically sets GPCR bits */ +extern void ioc3_gpcr_set(struct ioc3_driver_data *, unsigned int); +/* general ireg writer */ +extern void ioc3_write_ireg(struct ioc3_driver_data *idd, uint32_t value, int reg); + +#endif -- GitLab From b0a9499c3dd50d333e2aedb7e894873c58da3785 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 14 Jan 2006 13:20:41 -0800 Subject: [PATCH 260/465] [PATCH] sched: add new SCHED_BATCH policy Add a new SCHED_BATCH (3) scheduling policy: such tasks are presumed CPU-intensive, and will acquire a constant +5 priority level penalty. Such policy is nice for workloads that are non-interactive, but which do not want to give up their nice levels. The policy is also useful for workloads that want a deterministic scheduling policy without interactivity causing extra preemptions (between that workload's tasks). Signed-off-by: Ingo Molnar Cc: Michael Kerrisk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/sched.h | 7 ++++--- kernel/exit.c | 4 +++- kernel/sched.c | 48 +++++++++++++++++++++++++++++-------------- 3 files changed, 40 insertions(+), 19 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index a72e1713542..2df1a1a2fee 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -160,6 +160,7 @@ extern unsigned long nr_iowait(void); #define SCHED_NORMAL 0 #define SCHED_FIFO 1 #define SCHED_RR 2 +#define SCHED_BATCH 3 struct sched_param { int sched_priority; @@ -470,9 +471,9 @@ struct signal_struct { /* * Priority of a process goes from 0..MAX_PRIO-1, valid RT - * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL tasks are - * in the range MAX_RT_PRIO..MAX_PRIO-1. Priority values - * are inverted: lower p->prio value means higher priority. + * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH + * tasks are in the range MAX_RT_PRIO..MAX_PRIO-1. Priority + * values are inverted: lower p->prio value means higher priority. * * The MAX_USER_RT_PRIO value allows the actual maximum * RT priority to be separate from the value exported to diff --git a/kernel/exit.c b/kernel/exit.c index f8e609ff189..7fb541cb8d6 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -244,7 +244,9 @@ static inline void reparent_to_init(void) /* Set the exit signal to SIGCHLD so we signal init on exit */ current->exit_signal = SIGCHLD; - if ((current->policy == SCHED_NORMAL) && (task_nice(current) < 0)) + if ((current->policy == SCHED_NORMAL || + current->policy == SCHED_BATCH) + && (task_nice(current) < 0)) set_user_nice(current, 0); /* cpus_allowed? */ /* rt_priority? */ diff --git a/kernel/sched.c b/kernel/sched.c index c9dec2aa197..e1dc903d5a7 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -748,10 +748,14 @@ static int recalc_task_prio(task_t *p, unsigned long long now) unsigned long long __sleep_time = now - p->timestamp; unsigned long sleep_time; - if (__sleep_time > NS_MAX_SLEEP_AVG) - sleep_time = NS_MAX_SLEEP_AVG; - else - sleep_time = (unsigned long)__sleep_time; + if (unlikely(p->policy == SCHED_BATCH)) + sleep_time = 0; + else { + if (__sleep_time > NS_MAX_SLEEP_AVG) + sleep_time = NS_MAX_SLEEP_AVG; + else + sleep_time = (unsigned long)__sleep_time; + } if (likely(sleep_time > 0)) { /* @@ -3560,7 +3564,7 @@ void set_user_nice(task_t *p, long nice) * The RT priorities are set via sched_setscheduler(), but we still * allow the 'normal' nice value to be set - but as expected * it wont have any effect on scheduling until the task is - * not SCHED_NORMAL: + * not SCHED_NORMAL/SCHED_BATCH: */ if (rt_task(p)) { p->static_prio = NICE_TO_PRIO(nice); @@ -3706,10 +3710,16 @@ static void __setscheduler(struct task_struct *p, int policy, int prio) BUG_ON(p->array); p->policy = policy; p->rt_priority = prio; - if (policy != SCHED_NORMAL) + if (policy != SCHED_NORMAL && policy != SCHED_BATCH) { p->prio = MAX_RT_PRIO-1 - p->rt_priority; - else + } else { p->prio = p->static_prio; + /* + * SCHED_BATCH tasks are treated as perpetual CPU hogs: + */ + if (policy == SCHED_BATCH) + p->sleep_avg = 0; + } } /** @@ -3733,29 +3743,35 @@ recheck: if (policy < 0) policy = oldpolicy = p->policy; else if (policy != SCHED_FIFO && policy != SCHED_RR && - policy != SCHED_NORMAL) - return -EINVAL; + policy != SCHED_NORMAL && policy != SCHED_BATCH) + return -EINVAL; /* * Valid priorities for SCHED_FIFO and SCHED_RR are - * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL is 0. + * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL and + * SCHED_BATCH is 0. */ if (param->sched_priority < 0 || (p->mm && param->sched_priority > MAX_USER_RT_PRIO-1) || (!p->mm && param->sched_priority > MAX_RT_PRIO-1)) return -EINVAL; - if ((policy == SCHED_NORMAL) != (param->sched_priority == 0)) + if ((policy == SCHED_NORMAL || policy == SCHED_BATCH) + != (param->sched_priority == 0)) return -EINVAL; /* * Allow unprivileged RT tasks to decrease priority: */ if (!capable(CAP_SYS_NICE)) { - /* can't change policy */ - if (policy != p->policy && - !p->signal->rlim[RLIMIT_RTPRIO].rlim_cur) + /* + * can't change policy, except between SCHED_NORMAL + * and SCHED_BATCH: + */ + if (((policy != SCHED_NORMAL && p->policy != SCHED_BATCH) && + (policy != SCHED_BATCH && p->policy != SCHED_NORMAL)) && + !p->signal->rlim[RLIMIT_RTPRIO].rlim_cur) return -EPERM; /* can't increase priority */ - if (policy != SCHED_NORMAL && + if ((policy != SCHED_NORMAL && policy != SCHED_BATCH) && param->sched_priority > p->rt_priority && param->sched_priority > p->signal->rlim[RLIMIT_RTPRIO].rlim_cur) @@ -4233,6 +4249,7 @@ asmlinkage long sys_sched_get_priority_max(int policy) ret = MAX_USER_RT_PRIO-1; break; case SCHED_NORMAL: + case SCHED_BATCH: ret = 0; break; } @@ -4256,6 +4273,7 @@ asmlinkage long sys_sched_get_priority_min(int policy) ret = 1; break; case SCHED_NORMAL: + case SCHED_BATCH: ret = 0; } return ret; -- GitLab From 858119e159384308a5dde67776691a2ebf70df0f Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sat, 14 Jan 2006 13:20:43 -0800 Subject: [PATCH 261/465] [PATCH] Unlinline a bunch of other functions Remove the "inline" keyword from a bunch of big functions in the kernel with the goal of shrinking it by 30kb to 40kb Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar Acked-by: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/acpi/ec.c | 2 +- drivers/base/firmware_class.c | 2 +- drivers/block/loop.c | 2 +- drivers/bluetooth/hci_bcsp.c | 2 +- drivers/char/drm/r128_state.c | 2 +- drivers/cpufreq/cpufreq.c | 7 ++-- drivers/ide/ide-cd.c | 4 +- drivers/ide/ide-disk.c | 2 +- drivers/ide/ide-taskfile.c | 2 +- drivers/infiniband/core/cm.c | 4 +- drivers/isdn/hisax/avm_pci.c | 2 +- drivers/isdn/hisax/diva.c | 2 +- drivers/isdn/hisax/hscx_irq.c | 4 +- drivers/isdn/hisax/jade_irq.c | 2 +- drivers/md/bitmap.c | 2 +- drivers/md/dm-crypt.c | 2 +- drivers/md/dm-ioctl.c | 4 +- drivers/md/dm-snap.c | 2 +- drivers/md/dm.c | 2 +- drivers/md/raid1.c | 4 +- drivers/md/raid10.c | 4 +- drivers/md/raid5.c | 10 ++--- drivers/md/raid6main.c | 8 ++-- drivers/media/video/tvp5150.c | 2 +- drivers/message/fusion/mptlan.c | 4 +- drivers/mtd/devices/doc2000.c | 2 +- drivers/mtd/devices/doc2001.c | 2 +- drivers/mtd/devices/doc2001plus.c | 2 +- drivers/mtd/nand/diskonchip.c | 2 +- drivers/net/e100.c | 18 ++++---- drivers/net/sb1000.c | 4 +- drivers/net/wireless/hostap/hostap_80211_rx.c | 10 ++--- drivers/net/wireless/hostap/hostap_hw.c | 8 ++-- drivers/net/wireless/ipw2100.c | 26 ++++++------ drivers/net/wireless/ipw2200.c | 42 +++++++++---------- drivers/net/wireless/wavelan.c | 38 ++++++++--------- drivers/scsi/aic7xxx_old.c | 4 +- drivers/scsi/iscsi_tcp.c | 2 +- drivers/scsi/libata-core.c | 2 +- drivers/scsi/megaraid/megaraid_mbox.c | 10 ++--- drivers/scsi/megaraid/megaraid_sas.c | 18 ++++---- drivers/scsi/sr.c | 2 +- drivers/usb/atm/usbatm.c | 4 +- drivers/video/matrox/matroxfb_maven.c | 2 +- fs/9p/conv.c | 32 +++++++------- fs/binfmt_elf.c | 4 +- fs/binfmt_misc.c | 2 +- fs/bio.c | 4 +- fs/buffer.c | 6 +-- fs/compat.c | 4 +- fs/dcache.c | 2 +- fs/exec.c | 6 +-- fs/fcntl.c | 2 +- fs/jffs2/build.c | 2 +- fs/jffs2/nodelist.c | 4 +- fs/lockd/xdr.c | 6 +-- fs/mbcache.c | 6 +-- fs/namei.c | 8 ++-- fs/nfsd/nfsxdr.c | 4 +- fs/pipe.c | 4 +- kernel/cpuset.c | 2 +- kernel/exit.c | 10 ++--- kernel/posix-timers.c | 8 ++-- kernel/sched.c | 16 +++---- kernel/signal.c | 4 +- kernel/workqueue.c | 2 +- net/ieee80211/ieee80211_module.c | 4 +- net/ieee80211/ieee80211_rx.c | 14 +++---- net/ieee80211/ieee80211_tx.c | 4 +- net/ieee80211/ieee80211_wx.c | 2 +- net/netfilter/nfnetlink.c | 2 +- security/selinux/hooks.c | 2 +- sound/oss/esssolo1.c | 2 +- sound/pci/es1968.c | 4 +- 74 files changed, 226 insertions(+), 227 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 7e1a445955b..3758b558d2b 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -153,7 +153,7 @@ static int acpi_ec_polling_mode = EC_POLLING; Transaction Management -------------------------------------------------------------------------- */ -static inline u32 acpi_ec_read_status(union acpi_ec *ec) +static u32 acpi_ec_read_status(union acpi_ec *ec) { u32 status = 0; diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 3d384e3d34d..e97e911ebf7 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -48,7 +48,7 @@ struct firmware_priv { struct timer_list timeout; }; -static inline void +static void fw_load_abort(struct firmware_priv *fw_priv) { set_bit(FW_STATUS_ABORT, &fw_priv->status); diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 864729046e2..5f6d1a5cce1 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -294,7 +294,7 @@ fail: * This helper just factors out common code between do_lo_send_direct_write() * and do_lo_send_write(). */ -static inline int __do_lo_send_write(struct file *file, +static int __do_lo_send_write(struct file *file, u8 __user *buf, const int len, loff_t pos) { ssize_t bw; diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c index 8fddfdfd0fb..7bd4ef90411 100644 --- a/drivers/bluetooth/hci_bcsp.c +++ b/drivers/bluetooth/hci_bcsp.c @@ -494,7 +494,7 @@ static inline void bcsp_unslip_one_byte(struct bcsp_struct *bcsp, unsigned char } } -static inline void bcsp_complete_rx_pkt(struct hci_uart *hu) +static void bcsp_complete_rx_pkt(struct hci_uart *hu) { struct bcsp_struct *bcsp = hu->priv; int pass_up; diff --git a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c index caeecc2c36d..a080cdd6081 100644 --- a/drivers/char/drm/r128_state.c +++ b/drivers/char/drm/r128_state.c @@ -220,7 +220,7 @@ static __inline__ void r128_emit_tex1(drm_r128_private_t * dev_priv) ADVANCE_RING(); } -static __inline__ void r128_emit_state(drm_r128_private_t * dev_priv) +static void r128_emit_state(drm_r128_private_t * dev_priv) { drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int dirty = sarea_priv->dirty; diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index a9163d02983..277a843a87a 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -41,7 +41,6 @@ static DEFINE_SPINLOCK(cpufreq_driver_lock); /* internal prototypes */ static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event); static void handle_update(void *data); -static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci); /** * Two notifier lists: the "policy" list is involved in the @@ -127,7 +126,7 @@ static unsigned int debug_ratelimit = 1; static unsigned int disable_ratelimit = 1; static DEFINE_SPINLOCK(disable_ratelimit_lock); -static inline void cpufreq_debug_enable_ratelimit(void) +static void cpufreq_debug_enable_ratelimit(void) { unsigned long flags; @@ -137,7 +136,7 @@ static inline void cpufreq_debug_enable_ratelimit(void) spin_unlock_irqrestore(&disable_ratelimit_lock, flags); } -static inline void cpufreq_debug_disable_ratelimit(void) +static void cpufreq_debug_disable_ratelimit(void) { unsigned long flags; @@ -206,7 +205,7 @@ static inline void cpufreq_debug_disable_ratelimit(void) { return; } static unsigned long l_p_j_ref; static unsigned int l_p_j_ref_freq; -static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) +static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) { if (ci->flags & CPUFREQ_CONST_LOOPS) return; diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index ef09a7ef239..3325660f724 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -980,7 +980,7 @@ static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector, * and attempt to recover if there are problems. Returns 0 if everything's * ok; nonzero if the request has been terminated. */ -static inline +static int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason) { if (ireason == 2) @@ -1539,7 +1539,7 @@ int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq) /* * Write handling */ -static inline int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason) +static int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason) { /* Two notes about IDE interrupt reason here - 0 means that * the drive wants to receive data from us, 2 means that diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 245b508208d..ca25f9e3d0f 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -477,7 +477,7 @@ static inline int idedisk_supports_lba48(const struct hd_driveid *id) && id->lba_capacity_2; } -static inline void idedisk_check_hpa(ide_drive_t *drive) +static void idedisk_check_hpa(ide_drive_t *drive) { unsigned long long capacity, set_max; int lba48 = idedisk_supports_lba48(drive->id); diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 62ebefd6394..9834dce4e20 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -308,7 +308,7 @@ static void ide_pio_multi(ide_drive_t *drive, unsigned int write) ide_pio_sector(drive, write); } -static inline void ide_pio_datablock(ide_drive_t *drive, struct request *rq, +static void ide_pio_datablock(ide_drive_t *drive, struct request *rq, unsigned int write) { if (rq->bio) /* fs request */ diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index c06b18102b6..2514de3480d 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -856,7 +856,7 @@ static void cm_format_req(struct cm_req_msg *req_msg, param->private_data_len); } -static inline int cm_validate_req_param(struct ib_cm_req_param *param) +static int cm_validate_req_param(struct ib_cm_req_param *param) { /* peer-to-peer not supported */ if (param->peer_to_peer) @@ -1005,7 +1005,7 @@ static inline int cm_is_active_peer(__be64 local_ca_guid, __be64 remote_ca_guid, (be32_to_cpu(local_qpn) > be32_to_cpu(remote_qpn)))); } -static inline void cm_format_paths_from_req(struct cm_req_msg *req_msg, +static void cm_format_paths_from_req(struct cm_req_msg *req_msg, struct ib_sa_path_rec *primary_path, struct ib_sa_path_rec *alt_path) { diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c index 5d8ee7368f7..4abe5ff10e7 100644 --- a/drivers/isdn/hisax/avm_pci.c +++ b/drivers/isdn/hisax/avm_pci.c @@ -358,7 +358,7 @@ hdlc_fill_fifo(struct BCState *bcs) } } -static inline void +static void HDLC_irq(struct BCState *bcs, u_int stat) { int len; struct sk_buff *skb; diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c index b62d6b30b72..b0ff1cc97d7 100644 --- a/drivers/isdn/hisax/diva.c +++ b/drivers/isdn/hisax/diva.c @@ -476,7 +476,7 @@ Memhscx_fill_fifo(struct BCState *bcs) } } -static inline void +static void Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) { u_char r; diff --git a/drivers/isdn/hisax/hscx_irq.c b/drivers/isdn/hisax/hscx_irq.c index 5fe9d42d03a..7b1ad5e4ecd 100644 --- a/drivers/isdn/hisax/hscx_irq.c +++ b/drivers/isdn/hisax/hscx_irq.c @@ -119,7 +119,7 @@ hscx_fill_fifo(struct BCState *bcs) } } -static inline void +static void hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) { u_char r; @@ -221,7 +221,7 @@ hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) } } -static inline void +static void hscx_int_main(struct IsdnCardState *cs, u_char val) { diff --git a/drivers/isdn/hisax/jade_irq.c b/drivers/isdn/hisax/jade_irq.c index 08563400e4f..1f201af15a0 100644 --- a/drivers/isdn/hisax/jade_irq.c +++ b/drivers/isdn/hisax/jade_irq.c @@ -110,7 +110,7 @@ jade_fill_fifo(struct BCState *bcs) } -static inline void +static void jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade) { u_char r; diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 76a189ceb52..eae4473eadd 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -200,7 +200,7 @@ out: /* if page is completely empty, put it back on the free list, or dealloc it */ /* if page was hijacked, unmark the flag so it might get alloced next time */ /* Note: lock should be held when calling this */ -static inline void bitmap_checkfree(struct bitmap *bitmap, unsigned long page) +static void bitmap_checkfree(struct bitmap *bitmap, unsigned long page) { char *ptr; diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index a601a427885..e7a650f9ca0 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -228,7 +228,7 @@ static struct crypt_iv_operations crypt_iv_essiv_ops = { }; -static inline int +static int crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out, struct scatterlist *in, unsigned int length, int write, sector_t sector) diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 561bda5011e..1235135b384 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -598,7 +598,7 @@ static int dev_create(struct dm_ioctl *param, size_t param_size) /* * Always use UUID for lookups if it's present, otherwise use name or dev. */ -static inline struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param) +static struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param) { if (*param->uuid) return __get_uuid_cell(param->uuid); @@ -608,7 +608,7 @@ static inline struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param) return dm_get_mdptr(huge_decode_dev(param->dev)); } -static inline struct mapped_device *find_device(struct dm_ioctl *param) +static struct mapped_device *find_device(struct dm_ioctl *param) { struct hash_cell *hc; struct mapped_device *md = NULL; diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 4b9dd8fb1e5..87727d84dbb 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -691,7 +691,7 @@ static void copy_callback(int read_err, unsigned int write_err, void *context) /* * Dispatches the copy operation to kcopyd. */ -static inline void start_copy(struct pending_exception *pe) +static void start_copy(struct pending_exception *pe) { struct dm_snapshot *s = pe->snap; struct io_region src, dest; diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 097d1e54009..8c16359f8b0 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -293,7 +293,7 @@ struct dm_table *dm_get_table(struct mapped_device *md) * Decrements the number of outstanding ios that a bio has been * cloned into, completing the original io if necc. */ -static inline void dec_pending(struct dm_io *io, int error) +static void dec_pending(struct dm_io *io, int error) { if (error) io->error = error; diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index a06ff91f27e..d39f584cd8b 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -176,7 +176,7 @@ static void put_all_bios(conf_t *conf, r1bio_t *r1_bio) } } -static inline void free_r1bio(r1bio_t *r1_bio) +static void free_r1bio(r1bio_t *r1_bio) { conf_t *conf = mddev_to_conf(r1_bio->mddev); @@ -190,7 +190,7 @@ static inline void free_r1bio(r1bio_t *r1_bio) mempool_free(r1_bio, conf->r1bio_pool); } -static inline void put_buf(r1bio_t *r1_bio) +static void put_buf(r1bio_t *r1_bio) { conf_t *conf = mddev_to_conf(r1_bio->mddev); int i; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 9e658e519a2..9130d051b47 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -176,7 +176,7 @@ static void put_all_bios(conf_t *conf, r10bio_t *r10_bio) } } -static inline void free_r10bio(r10bio_t *r10_bio) +static void free_r10bio(r10bio_t *r10_bio) { conf_t *conf = mddev_to_conf(r10_bio->mddev); @@ -190,7 +190,7 @@ static inline void free_r10bio(r10bio_t *r10_bio) mempool_free(r10_bio, conf->r10bio_pool); } -static inline void put_buf(r10bio_t *r10_bio) +static void put_buf(r10bio_t *r10_bio) { conf_t *conf = mddev_to_conf(r10_bio->mddev); diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 54f4a9847e3..25976bfb6f9 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -69,7 +69,7 @@ static void print_raid5_conf (raid5_conf_t *conf); -static inline void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh) +static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh) { if (atomic_dec_and_test(&sh->count)) { if (!list_empty(&sh->lru)) @@ -118,7 +118,7 @@ static inline void remove_hash(struct stripe_head *sh) hlist_del_init(&sh->hash); } -static inline void insert_hash(raid5_conf_t *conf, struct stripe_head *sh) +static void insert_hash(raid5_conf_t *conf, struct stripe_head *sh) { struct hlist_head *hp = stripe_hash(conf, sh->sector); @@ -178,7 +178,7 @@ static int grow_buffers(struct stripe_head *sh, int num) static void raid5_build_block (struct stripe_head *sh, int i); -static inline void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) +static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) { raid5_conf_t *conf = sh->raid_conf; int disks = conf->raid_disks, i; @@ -1415,7 +1415,7 @@ static void handle_stripe(struct stripe_head *sh) } } -static inline void raid5_activate_delayed(raid5_conf_t *conf) +static void raid5_activate_delayed(raid5_conf_t *conf) { if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) { while (!list_empty(&conf->delayed_list)) { @@ -1431,7 +1431,7 @@ static inline void raid5_activate_delayed(raid5_conf_t *conf) } } -static inline void activate_bit_delay(raid5_conf_t *conf) +static void activate_bit_delay(raid5_conf_t *conf) { /* device_lock is held */ struct list_head head; diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c index 8c823d686a6..f618a53b98b 100644 --- a/drivers/md/raid6main.c +++ b/drivers/md/raid6main.c @@ -88,7 +88,7 @@ static inline int raid6_next_disk(int disk, int raid_disks) static void print_raid6_conf (raid6_conf_t *conf); -static inline void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh) +static void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh) { if (atomic_dec_and_test(&sh->count)) { if (!list_empty(&sh->lru)) @@ -197,7 +197,7 @@ static int grow_buffers(struct stripe_head *sh, int num) static void raid6_build_block (struct stripe_head *sh, int i); -static inline void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) +static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) { raid6_conf_t *conf = sh->raid_conf; int disks = conf->raid_disks, i; @@ -1577,7 +1577,7 @@ static void handle_stripe(struct stripe_head *sh, struct page *tmp_page) } } -static inline void raid6_activate_delayed(raid6_conf_t *conf) +static void raid6_activate_delayed(raid6_conf_t *conf) { if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) { while (!list_empty(&conf->delayed_list)) { @@ -1593,7 +1593,7 @@ static inline void raid6_activate_delayed(raid6_conf_t *conf) } } -static inline void activate_bit_delay(raid6_conf_t *conf) +static void activate_bit_delay(raid6_conf_t *conf) { /* device_lock is held */ struct list_head head; diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index e86b522938f..9094fa9f2ec 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -93,7 +93,7 @@ struct tvp5150 { int sat; }; -static inline int tvp5150_read(struct i2c_client *c, unsigned char addr) +static int tvp5150_read(struct i2c_client *c, unsigned char addr) { unsigned char buffer[1]; int rc; diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c index 0b1b72825ae..73f59528212 100644 --- a/drivers/message/fusion/mptlan.c +++ b/drivers/message/fusion/mptlan.c @@ -844,7 +844,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, struct net_device *dev) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static inline void +static void mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority) /* * @priority: 0 = put it on the timer queue, 1 = put it on the immediate queue @@ -866,7 +866,7 @@ mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static inline int +static int mpt_lan_receive_skb(struct net_device *dev, struct sk_buff *skb) { struct mpt_lan_priv *priv = dev->priv; diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c index be5e88b3888..e4345cf744a 100644 --- a/drivers/mtd/devices/doc2000.c +++ b/drivers/mtd/devices/doc2000.c @@ -138,7 +138,7 @@ static inline int DoC_WaitReady(struct DiskOnChip *doc) bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */ -static inline int DoC_Command(struct DiskOnChip *doc, unsigned char command, +static int DoC_Command(struct DiskOnChip *doc, unsigned char command, unsigned char xtraflags) { void __iomem *docptr = doc->virtadr; diff --git a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c index fcb28a6fd89..681a9c73a2a 100644 --- a/drivers/mtd/devices/doc2001.c +++ b/drivers/mtd/devices/doc2001.c @@ -103,7 +103,7 @@ static inline int DoC_WaitReady(void __iomem * docptr) with the internal pipeline. Each of 4 delay cycles (read from the NOP register) is required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */ -static inline void DoC_Command(void __iomem * docptr, unsigned char command, +static void DoC_Command(void __iomem * docptr, unsigned char command, unsigned char xtraflags) { /* Assert the CLE (Command Latch Enable) line to the flash chip */ diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c index 0595cc7324b..5f57f29efee 100644 --- a/drivers/mtd/devices/doc2001plus.c +++ b/drivers/mtd/devices/doc2001plus.c @@ -118,7 +118,7 @@ static inline void DoC_CheckASIC(void __iomem * docptr) /* DoC_Command: Send a flash command to the flash chip through the Flash * command register. Need 2 Write Pipeline Terminates to complete send. */ -static inline void DoC_Command(void __iomem * docptr, unsigned char command, +static void DoC_Command(void __iomem * docptr, unsigned char command, unsigned char xtraflags) { WriteDOC(command, docptr, Mplus_FlashCmd); diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index 21d4e8f4b7a..ec5e45e4e4e 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c @@ -1506,7 +1506,7 @@ static inline int __init doc2001plus_init(struct mtd_info *mtd) return 1; } -static inline int __init doc_probe(unsigned long physadr) +static int __init doc_probe(unsigned long physadr) { unsigned char ChipID; struct mtd_info *mtd; diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 23de22631c6..4726722a063 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -592,7 +592,7 @@ static inline void e100_write_flush(struct nic *nic) (void)readb(&nic->csr->scb.status); } -static inline void e100_enable_irq(struct nic *nic) +static void e100_enable_irq(struct nic *nic) { unsigned long flags; @@ -602,7 +602,7 @@ static inline void e100_enable_irq(struct nic *nic) e100_write_flush(nic); } -static inline void e100_disable_irq(struct nic *nic) +static void e100_disable_irq(struct nic *nic) { unsigned long flags; @@ -791,7 +791,7 @@ static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) #define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */ #define E100_WAIT_SCB_FAST 20 /* delay like the old code */ -static inline int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) +static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) { unsigned long flags; unsigned int i; @@ -822,7 +822,7 @@ err_unlock: return err; } -static inline int e100_exec_cb(struct nic *nic, struct sk_buff *skb, +static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) { struct cb *cb; @@ -1567,7 +1567,7 @@ static void e100_watchdog(unsigned long data) mod_timer(&nic->watchdog, jiffies + E100_WATCHDOG_PERIOD); } -static inline void e100_xmit_prepare(struct nic *nic, struct cb *cb, +static void e100_xmit_prepare(struct nic *nic, struct cb *cb, struct sk_buff *skb) { cb->command = nic->tx_command; @@ -1617,7 +1617,7 @@ static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev) return 0; } -static inline int e100_tx_clean(struct nic *nic) +static int e100_tx_clean(struct nic *nic) { struct cb *cb; int tx_cleaned = 0; @@ -1728,7 +1728,7 @@ static inline void e100_start_receiver(struct nic *nic, struct rx *rx) } #define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) -static inline int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) +static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) { if(!(rx->skb = dev_alloc_skb(RFD_BUF_LEN + NET_IP_ALIGN))) return -ENOMEM; @@ -1762,7 +1762,7 @@ static inline int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) return 0; } -static inline int e100_rx_indicate(struct nic *nic, struct rx *rx, +static int e100_rx_indicate(struct nic *nic, struct rx *rx, unsigned int *work_done, unsigned int work_to_do) { struct sk_buff *skb = rx->skb; @@ -1822,7 +1822,7 @@ static inline int e100_rx_indicate(struct nic *nic, struct rx *rx, return 0; } -static inline void e100_rx_clean(struct nic *nic, unsigned int *work_done, +static void e100_rx_clean(struct nic *nic, unsigned int *work_done, unsigned int work_to_do) { struct rx *rx; diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c index d6388e1533f..76139478c3d 100644 --- a/drivers/net/sb1000.c +++ b/drivers/net/sb1000.c @@ -94,7 +94,7 @@ static inline int card_wait_for_busy_clear(const int ioaddr[], const char* name); static inline int card_wait_for_ready(const int ioaddr[], const char* name, unsigned char in[]); -static inline int card_send_command(const int ioaddr[], const char* name, +static int card_send_command(const int ioaddr[], const char* name, const unsigned char out[], unsigned char in[]); /* SB1000 hardware routines to be used during frame rx interrupt */ @@ -309,7 +309,7 @@ card_wait_for_ready(const int ioaddr[], const char* name, unsigned char in[]) } /* Card Send Command (cannot be used during an interrupt) */ -static inline int +static int card_send_command(const int ioaddr[], const char* name, const unsigned char out[], unsigned char in[]) { diff --git a/drivers/net/wireless/hostap/hostap_80211_rx.c b/drivers/net/wireless/hostap/hostap_80211_rx.c index ffac5089945..4b13b76425c 100644 --- a/drivers/net/wireless/hostap/hostap_80211_rx.c +++ b/drivers/net/wireless/hostap/hostap_80211_rx.c @@ -435,7 +435,7 @@ static void hostap_rx_sta_beacon(local_info_t *local, struct sk_buff *skb, } -static inline int +static int hostap_rx_frame_mgmt(local_info_t *local, struct sk_buff *skb, struct hostap_80211_rx_status *rx_stats, u16 type, u16 stype) @@ -499,7 +499,7 @@ hostap_rx_frame_mgmt(local_info_t *local, struct sk_buff *skb, /* Called only as a tasklet (software IRQ) */ -static inline struct net_device *prism2_rx_get_wds(local_info_t *local, +static struct net_device *prism2_rx_get_wds(local_info_t *local, u8 *addr) { struct hostap_interface *iface = NULL; @@ -519,7 +519,7 @@ static inline struct net_device *prism2_rx_get_wds(local_info_t *local, } -static inline int +static int hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr_4addr *hdr, u16 fc, struct net_device **wds) { @@ -615,7 +615,7 @@ static int hostap_is_eapol_frame(local_info_t *local, struct sk_buff *skb) /* Called only as a tasklet (software IRQ) */ -static inline int +static int hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb, struct ieee80211_crypt_data *crypt) { @@ -654,7 +654,7 @@ hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb, /* Called only as a tasklet (software IRQ) */ -static inline int +static int hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb, int keyidx, struct ieee80211_crypt_data *crypt) { diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index abfae7fedeb..b1f142d9e23 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c @@ -253,7 +253,7 @@ static void prism2_clear_cmd_queue(local_info_t *local) * @dev: pointer to net_device * @entry: Prism2 command queue entry to be issued */ -static inline int hfa384x_cmd_issue(struct net_device *dev, +static int hfa384x_cmd_issue(struct net_device *dev, struct hostap_cmd_queue *entry) { struct hostap_interface *iface; @@ -743,7 +743,7 @@ static void prism2_cmd_ev(struct net_device *dev) } -static inline int hfa384x_wait_offset(struct net_device *dev, u16 o_off) +static int hfa384x_wait_offset(struct net_device *dev, u16 o_off) { int tries = HFA384X_BAP_BUSY_TIMEOUT; int res = HFA384X_INW(o_off) & HFA384X_OFFSET_BUSY; @@ -1904,7 +1904,7 @@ fail: * and will try to get the correct fid eventually. */ #define EXTRA_FID_READ_TESTS -static inline u16 prism2_read_fid_reg(struct net_device *dev, u16 reg) +static u16 prism2_read_fid_reg(struct net_device *dev, u16 reg) { #ifdef EXTRA_FID_READ_TESTS u16 val, val2, val3; @@ -2581,7 +2581,7 @@ static void prism2_ev_tick(struct net_device *dev) /* Called only from hardware IRQ */ -static inline void prism2_check_magic(local_info_t *local) +static void prism2_check_magic(local_info_t *local) { /* at least PCI Prism2.5 with bus mastering seems to sometimes * return 0x0000 in SWSUPPORT0 for unknown reason, but re-reading the diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index cf05661fb1b..7518384f34d 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -411,7 +411,7 @@ static inline void write_nic_dword_auto_inc(struct net_device *dev, u32 val) write_register(dev, IPW_REG_AUTOINCREMENT_DATA, val); } -static inline void write_nic_memory(struct net_device *dev, u32 addr, u32 len, +static void write_nic_memory(struct net_device *dev, u32 addr, u32 len, const u8 * buf) { u32 aligned_addr; @@ -449,7 +449,7 @@ static inline void write_nic_memory(struct net_device *dev, u32 addr, u32 len, *buf); } -static inline void read_nic_memory(struct net_device *dev, u32 addr, u32 len, +static void read_nic_memory(struct net_device *dev, u32 addr, u32 len, u8 * buf) { u32 aligned_addr; @@ -657,7 +657,7 @@ static void printk_buf(int level, const u8 * data, u32 len) #define MAX_RESET_BACKOFF 10 -static inline void schedule_reset(struct ipw2100_priv *priv) +static void schedule_reset(struct ipw2100_priv *priv) { unsigned long now = get_seconds(); @@ -1130,7 +1130,7 @@ static inline void ipw2100_hw_set_gpio(struct ipw2100_priv *priv) write_register(priv->net_dev, IPW_REG_GPIO, reg); } -static inline int rf_kill_active(struct ipw2100_priv *priv) +static int rf_kill_active(struct ipw2100_priv *priv) { #define MAX_RF_KILL_CHECKS 5 #define RF_KILL_CHECK_DELAY 40 @@ -2177,7 +2177,7 @@ static const char *frame_types[] = { }; #endif -static inline int ipw2100_alloc_skb(struct ipw2100_priv *priv, +static int ipw2100_alloc_skb(struct ipw2100_priv *priv, struct ipw2100_rx_packet *packet) { packet->skb = dev_alloc_skb(sizeof(struct ipw2100_rx)); @@ -2201,7 +2201,7 @@ static inline int ipw2100_alloc_skb(struct ipw2100_priv *priv, #define SEARCH_SNAPSHOT 1 #define SNAPSHOT_ADDR(ofs) (priv->snapshot[((ofs) >> 12) & 0xff] + ((ofs) & 0xfff)) -static inline int ipw2100_snapshot_alloc(struct ipw2100_priv *priv) +static int ipw2100_snapshot_alloc(struct ipw2100_priv *priv) { int i; if (priv->snapshot[0]) @@ -2221,7 +2221,7 @@ static inline int ipw2100_snapshot_alloc(struct ipw2100_priv *priv) return 1; } -static inline void ipw2100_snapshot_free(struct ipw2100_priv *priv) +static void ipw2100_snapshot_free(struct ipw2100_priv *priv) { int i; if (!priv->snapshot[0]) @@ -2231,7 +2231,7 @@ static inline void ipw2100_snapshot_free(struct ipw2100_priv *priv) priv->snapshot[0] = NULL; } -static inline u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf, +static u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf, size_t len, int mode) { u32 i, j; @@ -2288,7 +2288,7 @@ static inline u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf, static u8 packet_data[IPW_RX_NIC_BUFFER_LENGTH]; #endif -static inline void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i) +static void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i) { #ifdef CONFIG_IPW2100_DEBUG_C3 struct ipw2100_status *status = &priv->status_queue.drv[i]; @@ -2346,7 +2346,7 @@ static inline void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i) schedule_reset(priv); } -static inline void isr_rx(struct ipw2100_priv *priv, int i, +static void isr_rx(struct ipw2100_priv *priv, int i, struct ieee80211_rx_stats *stats) { struct ipw2100_status *status = &priv->status_queue.drv[i]; @@ -2425,7 +2425,7 @@ static inline void isr_rx(struct ipw2100_priv *priv, int i, priv->rx_queue.drv[i].host_addr = packet->dma_addr; } -static inline int ipw2100_corruption_check(struct ipw2100_priv *priv, int i) +static int ipw2100_corruption_check(struct ipw2100_priv *priv, int i) { struct ipw2100_status *status = &priv->status_queue.drv[i]; struct ipw2100_rx *u = priv->rx_buffers[i].rxp; @@ -2481,7 +2481,7 @@ static inline int ipw2100_corruption_check(struct ipw2100_priv *priv, int i) * The WRITE index is cached in the variable 'priv->rx_queue.next'. * */ -static inline void __ipw2100_rx_process(struct ipw2100_priv *priv) +static void __ipw2100_rx_process(struct ipw2100_priv *priv) { struct ipw2100_bd_queue *rxq = &priv->rx_queue; struct ipw2100_status_queue *sq = &priv->status_queue; @@ -2634,7 +2634,7 @@ static inline void __ipw2100_rx_process(struct ipw2100_priv *priv) * for use by future command and data packets. * */ -static inline int __ipw2100_tx_process(struct ipw2100_priv *priv) +static int __ipw2100_tx_process(struct ipw2100_priv *priv) { struct ipw2100_bd_queue *txq = &priv->tx_queue; struct ipw2100_bd *tbd; diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index cdfe5020775..819be2b6b7d 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -813,7 +813,7 @@ static void ipw_bg_led_link_off(void *data) up(&priv->sem); } -static inline void __ipw_led_activity_on(struct ipw_priv *priv) +static void __ipw_led_activity_on(struct ipw_priv *priv) { u32 led; @@ -1508,7 +1508,7 @@ static ssize_t store_direct_dword(struct device *d, static DEVICE_ATTR(direct_dword, S_IWUSR | S_IRUGO, show_direct_dword, store_direct_dword); -static inline int rf_kill_active(struct ipw_priv *priv) +static int rf_kill_active(struct ipw_priv *priv) { if (0 == (ipw_read32(priv, 0x30) & 0x10000)) priv->status |= STATUS_RF_KILL_HW; @@ -2359,7 +2359,7 @@ static inline void eeprom_write_reg(struct ipw_priv *p, u32 data) } /* perform a chip select operation */ -static inline void eeprom_cs(struct ipw_priv *priv) +static void eeprom_cs(struct ipw_priv *priv) { eeprom_write_reg(priv, 0); eeprom_write_reg(priv, EEPROM_BIT_CS); @@ -2368,7 +2368,7 @@ static inline void eeprom_cs(struct ipw_priv *priv) } /* perform a chip select operation */ -static inline void eeprom_disable_cs(struct ipw_priv *priv) +static void eeprom_disable_cs(struct ipw_priv *priv) { eeprom_write_reg(priv, EEPROM_BIT_CS); eeprom_write_reg(priv, 0); @@ -2475,7 +2475,7 @@ static void ipw_eeprom_init_sram(struct ipw_priv *priv) IPW_DEBUG_TRACE("<<\n"); } -static inline void ipw_zero_memory(struct ipw_priv *priv, u32 start, u32 count) +static void ipw_zero_memory(struct ipw_priv *priv, u32 start, u32 count) { count >>= 2; if (!count) @@ -2772,7 +2772,7 @@ static inline int ipw_alive(struct ipw_priv *priv) return ipw_read32(priv, 0x90) == 0xd55555d5; } -static inline int ipw_poll_bit(struct ipw_priv *priv, u32 addr, u32 mask, +static int ipw_poll_bit(struct ipw_priv *priv, u32 addr, u32 mask, int timeout) { int i = 0; @@ -3150,7 +3150,7 @@ static int ipw_get_fw(struct ipw_priv *priv, #define IPW_RX_BUF_SIZE (3000) -static inline void ipw_rx_queue_reset(struct ipw_priv *priv, +static void ipw_rx_queue_reset(struct ipw_priv *priv, struct ipw_rx_queue *rxq) { unsigned long flags; @@ -3608,7 +3608,7 @@ static void ipw_tx_queue_free(struct ipw_priv *priv) ipw_queue_tx_free(priv, &priv->txq[3]); } -static inline void ipw_create_bssid(struct ipw_priv *priv, u8 * bssid) +static void ipw_create_bssid(struct ipw_priv *priv, u8 * bssid) { /* First 3 bytes are manufacturer */ bssid[0] = priv->mac_addr[0]; @@ -3622,7 +3622,7 @@ static inline void ipw_create_bssid(struct ipw_priv *priv, u8 * bssid) bssid[0] |= 0x02; /* set local assignment bit (IEEE802) */ } -static inline u8 ipw_add_station(struct ipw_priv *priv, u8 * bssid) +static u8 ipw_add_station(struct ipw_priv *priv, u8 * bssid) { struct ipw_station_entry entry; int i; @@ -3655,7 +3655,7 @@ static inline u8 ipw_add_station(struct ipw_priv *priv, u8 * bssid) return i; } -static inline u8 ipw_find_station(struct ipw_priv *priv, u8 * bssid) +static u8 ipw_find_station(struct ipw_priv *priv, u8 * bssid) { int i; @@ -3794,7 +3794,7 @@ static void inline average_init(struct average *avg) memset(avg, 0, sizeof(*avg)); } -static void inline average_add(struct average *avg, s16 val) +static void average_add(struct average *avg, s16 val) { avg->sum -= avg->entries[avg->pos]; avg->sum += val; @@ -3805,7 +3805,7 @@ static void inline average_add(struct average *avg, s16 val) } } -static s16 inline average_value(struct average *avg) +static s16 average_value(struct average *avg) { if (!unlikely(avg->init)) { if (avg->pos) @@ -3847,7 +3847,7 @@ static void ipw_reset_stats(struct ipw_priv *priv) } -static inline u32 ipw_get_max_rate(struct ipw_priv *priv) +static u32 ipw_get_max_rate(struct ipw_priv *priv) { u32 i = 0x80000000; u32 mask = priv->rates_mask; @@ -4087,7 +4087,7 @@ static void ipw_bg_gather_stats(void *data) * roaming_threshold -> disassociate_threshold, scan and roam for better signal. * Above disassociate threshold, give up and stop scanning. * Roaming is disabled if disassociate_threshold <= roaming_threshold */ -static inline void ipw_handle_missed_beacon(struct ipw_priv *priv, +static void ipw_handle_missed_beacon(struct ipw_priv *priv, int missed_count) { priv->notif_missed_beacons = missed_count; @@ -4157,7 +4157,7 @@ static inline void ipw_handle_missed_beacon(struct ipw_priv *priv, * Handle host notification packet. * Called from interrupt routine */ -static inline void ipw_rx_notification(struct ipw_priv *priv, +static void ipw_rx_notification(struct ipw_priv *priv, struct ipw_rx_notification *notif) { notif->size = le16_to_cpu(notif->size); @@ -5095,7 +5095,7 @@ static int ipw_compatible_rates(struct ipw_priv *priv, return 1; } -static inline void ipw_copy_rates(struct ipw_supported_rates *dest, +static void ipw_copy_rates(struct ipw_supported_rates *dest, const struct ipw_supported_rates *src) { u8 i; @@ -5856,7 +5856,7 @@ static void ipw_debug_config(struct ipw_priv *priv) #define ipw_debug_config(x) do {} while (0) #endif -static inline void ipw_set_fixed_rate(struct ipw_priv *priv, int mode) +static void ipw_set_fixed_rate(struct ipw_priv *priv, int mode) { /* TODO: Verify that this works... */ struct ipw_fixed_rate fr = { @@ -7634,7 +7634,7 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, } #endif -static inline int is_network_packet(struct ipw_priv *priv, +static int is_network_packet(struct ipw_priv *priv, struct ieee80211_hdr_4addr *header) { /* Filter incoming packets to determine if they are targetted toward @@ -7672,7 +7672,7 @@ static inline int is_network_packet(struct ipw_priv *priv, #define IPW_PACKET_RETRY_TIME HZ -static inline int is_duplicate_packet(struct ipw_priv *priv, +static int is_duplicate_packet(struct ipw_priv *priv, struct ieee80211_hdr_4addr *header) { u16 sc = le16_to_cpu(header->seq_ctl); @@ -9581,7 +9581,7 @@ static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev) /* net device stuff */ -static inline void init_sys_config(struct ipw_sys_config *sys_config) +static void init_sys_config(struct ipw_sys_config *sys_config) { memset(sys_config, 0, sizeof(struct ipw_sys_config)); sys_config->bt_coexistence = 1; /* We may need to look into prvStaBtConfig */ @@ -9627,7 +9627,7 @@ modify to send one tfd per fragment instead of using chunking. otherwise we need to heavily modify the ieee80211_skb_to_txb. */ -static inline int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, +static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, int pri) { struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *) diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c index b0d8b5b0315..ff192e96268 100644 --- a/drivers/net/wireless/wavelan.c +++ b/drivers/net/wireless/wavelan.c @@ -102,7 +102,7 @@ static inline void hacr_write(unsigned long ioaddr, u16 hacr) * Write to card's Host Adapter Command Register. Include a delay for * those times when it is needed. */ -static inline void hacr_write_slow(unsigned long ioaddr, u16 hacr) +static void hacr_write_slow(unsigned long ioaddr, u16 hacr) { hacr_write(ioaddr, hacr); /* delay might only be needed sometimes */ @@ -242,7 +242,7 @@ static void psa_write(unsigned long ioaddr, u16 hacr, int o, /* Offset in PSA */ * The Windows drivers don't use the CRC, but the AP and the PtP tool * depend on it. */ -static inline u16 psa_crc(u8 * psa, /* The PSA */ +static u16 psa_crc(u8 * psa, /* The PSA */ int size) { /* Number of short for CRC */ int byte_cnt; /* Loop on the PSA */ @@ -310,7 +310,7 @@ static void update_psa_checksum(struct net_device * dev, unsigned long ioaddr, u /* * Write 1 byte to the MMC. */ -static inline void mmc_out(unsigned long ioaddr, u16 o, u8 d) +static void mmc_out(unsigned long ioaddr, u16 o, u8 d) { int count = 0; @@ -326,7 +326,7 @@ static inline void mmc_out(unsigned long ioaddr, u16 o, u8 d) * Routine to write bytes to the Modem Management Controller. * We start at the end because it is the way it should be! */ -static inline void mmc_write(unsigned long ioaddr, u8 o, u8 * b, int n) +static void mmc_write(unsigned long ioaddr, u8 o, u8 * b, int n) { o += n; b += n; @@ -340,7 +340,7 @@ static inline void mmc_write(unsigned long ioaddr, u8 o, u8 * b, int n) * Read a byte from the MMC. * Optimised version for 1 byte, avoid using memory. */ -static inline u8 mmc_in(unsigned long ioaddr, u16 o) +static u8 mmc_in(unsigned long ioaddr, u16 o) { int count = 0; @@ -587,7 +587,7 @@ static void wv_ack(struct net_device * dev) * Set channel attention bit and busy wait until command has * completed, then acknowledge completion of the command. */ -static inline int wv_synchronous_cmd(struct net_device * dev, const char *str) +static int wv_synchronous_cmd(struct net_device * dev, const char *str) { net_local *lp = (net_local *) dev->priv; unsigned long ioaddr = dev->base_addr; @@ -633,7 +633,7 @@ static inline int wv_synchronous_cmd(struct net_device * dev, const char *str) * Configuration commands completion interrupt. * Check if done, and if OK. */ -static inline int +static int wv_config_complete(struct net_device * dev, unsigned long ioaddr, net_local * lp) { unsigned short mcs_addr; @@ -843,7 +843,7 @@ if (lp->tx_n_in_use > 0) * wavelan_interrupt is not an option), so you may experience * delays sometimes. */ -static inline void wv_82586_reconfig(struct net_device * dev) +static void wv_82586_reconfig(struct net_device * dev) { net_local *lp = (net_local *) dev->priv; unsigned long flags; @@ -1281,7 +1281,7 @@ static inline void wv_packet_info(u8 * p, /* Packet to dump */ * This is the information which is displayed by the driver at startup. * There are lots of flags for configuring it to your liking. */ -static inline void wv_init_info(struct net_device * dev) +static void wv_init_info(struct net_device * dev) { short ioaddr = dev->base_addr; net_local *lp = (net_local *) dev->priv; @@ -1502,7 +1502,7 @@ static int wavelan_set_mac_address(struct net_device * dev, void *addr) * It's a bit complicated and you don't really want to look into it. * (called in wavelan_ioctl) */ -static inline int wv_set_frequency(unsigned long ioaddr, /* I/O port of the card */ +static int wv_set_frequency(unsigned long ioaddr, /* I/O port of the card */ iw_freq * frequency) { const int BAND_NUM = 10; /* Number of bands */ @@ -1677,7 +1677,7 @@ static inline int wv_set_frequency(unsigned long ioaddr, /* I/O port of the card /* * Give the list of available frequencies. */ -static inline int wv_frequency_list(unsigned long ioaddr, /* I/O port of the card */ +static int wv_frequency_list(unsigned long ioaddr, /* I/O port of the card */ iw_freq * list, /* List of frequencies to fill */ int max) { /* Maximum number of frequencies */ @@ -2489,7 +2489,7 @@ static iw_stats *wavelan_get_wireless_stats(struct net_device * dev) * Note: if any errors occur, the packet is "dropped on the floor". * (called by wv_packet_rcv()) */ -static inline void +static void wv_packet_read(struct net_device * dev, u16 buf_off, int sksize) { net_local *lp = (net_local *) dev->priv; @@ -2585,7 +2585,7 @@ wv_packet_read(struct net_device * dev, u16 buf_off, int sksize) * (called in wavelan_interrupt()). * Note : the spinlock is already grabbed for us. */ -static inline void wv_receive(struct net_device * dev) +static void wv_receive(struct net_device * dev) { unsigned long ioaddr = dev->base_addr; net_local *lp = (net_local *) dev->priv; @@ -2768,7 +2768,7 @@ static inline void wv_receive(struct net_device * dev) * * (called in wavelan_packet_xmit()) */ -static inline int wv_packet_write(struct net_device * dev, void *buf, short length) +static int wv_packet_write(struct net_device * dev, void *buf, short length) { net_local *lp = (net_local *) dev->priv; unsigned long ioaddr = dev->base_addr; @@ -2964,7 +2964,7 @@ static int wavelan_packet_xmit(struct sk_buff *skb, struct net_device * dev) * Routine to initialize the Modem Management Controller. * (called by wv_hw_reset()) */ -static inline int wv_mmc_init(struct net_device * dev) +static int wv_mmc_init(struct net_device * dev) { unsigned long ioaddr = dev->base_addr; net_local *lp = (net_local *) dev->priv; @@ -3136,7 +3136,7 @@ static inline int wv_mmc_init(struct net_device * dev) * Start the receive unit. * (called by wv_hw_reset()) */ -static inline int wv_ru_start(struct net_device * dev) +static int wv_ru_start(struct net_device * dev) { net_local *lp = (net_local *) dev->priv; unsigned long ioaddr = dev->base_addr; @@ -3228,7 +3228,7 @@ static inline int wv_ru_start(struct net_device * dev) * * (called by wv_hw_reset()) */ -static inline int wv_cu_start(struct net_device * dev) +static int wv_cu_start(struct net_device * dev) { net_local *lp = (net_local *) dev->priv; unsigned long ioaddr = dev->base_addr; @@ -3329,7 +3329,7 @@ static inline int wv_cu_start(struct net_device * dev) * * (called by wv_hw_reset()) */ -static inline int wv_82586_start(struct net_device * dev) +static int wv_82586_start(struct net_device * dev) { net_local *lp = (net_local *) dev->priv; unsigned long ioaddr = dev->base_addr; @@ -3641,7 +3641,7 @@ static void wv_82586_config(struct net_device * dev) * WaveLAN controller (i82586). * (called by wavelan_close()) */ -static inline void wv_82586_stop(struct net_device * dev) +static void wv_82586_stop(struct net_device * dev) { net_local *lp = (net_local *) dev->priv; unsigned long ioaddr = dev->base_addr; diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c index 33d56c34494..770f1647e4d 100644 --- a/drivers/scsi/aic7xxx_old.c +++ b/drivers/scsi/aic7xxx_old.c @@ -1290,7 +1290,7 @@ static void aic7xxx_check_scbs(struct aic7xxx_host *p, char *buffer); * ***************************************************************************/ -static inline unsigned char +static unsigned char aic_inb(struct aic7xxx_host *p, long port) { #ifdef MMAPIO @@ -1309,7 +1309,7 @@ aic_inb(struct aic7xxx_host *p, long port) #endif } -static inline void +static void aic_outb(struct aic7xxx_host *p, unsigned char val, long port) { #ifdef MMAPIO diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 1b495afe6d1..780bfcc6709 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -1418,7 +1418,7 @@ iscsi_data_digest_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) ctask->digest_count = 4; } -static inline int +static int iscsi_digest_final_send(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, struct iscsi_buf *buf, uint32_t *digest, int final) { diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index f55b9b3f7b3..99bae8369ab 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1747,7 +1747,7 @@ static const struct { { ATA_SHIFT_PIO, XFER_PIO_0 }, }; -static inline u8 base_from_shift(unsigned int shift) +static u8 base_from_shift(unsigned int shift) { int i; diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index d18a4bc2498..bf9f7f7ba35 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -1266,7 +1266,7 @@ megaraid_mbox_teardown_dma_pools(adapter_t *adapter) * return the scb from the head of the free list. NULL if there are none * available **/ -static inline scb_t * +static scb_t * megaraid_alloc_scb(adapter_t *adapter, struct scsi_cmnd *scp) { struct list_head *head = &adapter->kscb_pool; @@ -1329,7 +1329,7 @@ megaraid_dealloc_scb(adapter_t *adapter, scb_t *scb) * * prepare the scatter-gather list */ -static inline int +static int megaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb) { struct scatterlist *sgl; @@ -1402,7 +1402,7 @@ megaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb) * * post the command to the controller if mailbox is availble. */ -static inline int +static int mbox_post_cmd(adapter_t *adapter, scb_t *scb) { mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); @@ -2070,7 +2070,7 @@ megaraid_mbox_prepare_epthru(adapter_t *adapter, scb_t *scb, * * Returns: 1 if the interrupt is valid, 0 otherwise */ -static inline int +static int megaraid_ack_sequence(adapter_t *adapter) { mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); @@ -2208,7 +2208,7 @@ megaraid_isr(int irq, void *devp, struct pt_regs *regs) * * DMA sync if required. */ -static inline void +static void megaraid_mbox_sync_scb(adapter_t *adapter, scb_t *scb) { mbox_ccb_t *ccb; diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index c0bb8061401..511ed52a580 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -81,7 +81,7 @@ static DEFINE_MUTEX(megasas_async_queue_mutex); * * Returns a free command from the pool */ -static inline struct megasas_cmd *megasas_get_cmd(struct megasas_instance +static struct megasas_cmd *megasas_get_cmd(struct megasas_instance *instance) { unsigned long flags; @@ -263,7 +263,7 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance, * If successful, this function returns the number of SG elements. Otherwise, * it returnes -1. */ -static inline int +static int megasas_make_sgl32(struct megasas_instance *instance, struct scsi_cmnd *scp, union megasas_sgl *mfi_sgl) { @@ -311,7 +311,7 @@ megasas_make_sgl32(struct megasas_instance *instance, struct scsi_cmnd *scp, * If successful, this function returns the number of SG elements. Otherwise, * it returnes -1. */ -static inline int +static int megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp, union megasas_sgl *mfi_sgl) { @@ -360,7 +360,7 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp, * This function prepares CDB commands. These are typcially pass-through * commands to the devices. */ -static inline int +static int megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, struct megasas_cmd *cmd) { @@ -441,7 +441,7 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, * * Frames (and accompanying SGLs) for regular SCSI IOs use this function. */ -static inline int +static int megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, struct megasas_cmd *cmd) { @@ -563,7 +563,7 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, * @scp: SCSI command * @frame_count: [OUT] Number of frames used to prepare this command */ -static inline struct megasas_cmd *megasas_build_cmd(struct megasas_instance +static struct megasas_cmd *megasas_build_cmd(struct megasas_instance *instance, struct scsi_cmnd *scp, int *frame_count) @@ -914,7 +914,7 @@ megasas_complete_abort(struct megasas_instance *instance, * @instance: Adapter soft state * @cmd: Completed command */ -static inline void +static void megasas_unmap_sgbuf(struct megasas_instance *instance, struct megasas_cmd *cmd) { dma_addr_t buf_h; @@ -958,7 +958,7 @@ megasas_unmap_sgbuf(struct megasas_instance *instance, struct megasas_cmd *cmd) * an alternate status (as in the case of aborted * commands) */ -static inline void +static void megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, u8 alt_status) { @@ -1105,7 +1105,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, * SCSI mid-layer instead of the status * returned by the FW */ -static inline int +static int megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status) { u32 status; diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index dd8050392d0..997f8e30509 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -151,7 +151,7 @@ static inline struct scsi_cd *scsi_cd_get(struct gendisk *disk) return cd; } -static inline void scsi_cd_put(struct scsi_cd *cd) +static void scsi_cd_put(struct scsi_cd *cd) { struct scsi_device *sdev = cd->device; diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index 9baa6296fc9..7af1883d4bf 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c @@ -207,7 +207,7 @@ static inline void usbatm_pop(struct atm_vcc *vcc, struct sk_buff *skb) ** urbs ** ************/ -static inline struct urb *usbatm_pop_urb(struct usbatm_channel *channel) +static struct urb *usbatm_pop_urb(struct usbatm_channel *channel) { struct urb *urb; @@ -224,7 +224,7 @@ static inline struct urb *usbatm_pop_urb(struct usbatm_channel *channel) return urb; } -static inline int usbatm_submit_urb(struct urb *urb) +static int usbatm_submit_urb(struct urb *urb) { struct usbatm_channel *channel = urb->context; int ret; diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c index a1f2c5e8fc8..6019710dc29 100644 --- a/drivers/video/matrox/matroxfb_maven.c +++ b/drivers/video/matrox/matroxfb_maven.c @@ -968,7 +968,7 @@ static inline int maven_compute_timming(struct maven_data* md, return 0; } -static inline int maven_program_timming(struct maven_data* md, +static int maven_program_timming(struct maven_data* md, const struct mavenregs* m) { struct i2c_client* c = md->client; diff --git a/fs/9p/conv.c b/fs/9p/conv.c index 55ccfa10ee9..32a9f99154e 100644 --- a/fs/9p/conv.c +++ b/fs/9p/conv.c @@ -56,7 +56,7 @@ static inline int buf_check_overflow(struct cbuf *buf) return buf->p > buf->ep; } -static inline int buf_check_size(struct cbuf *buf, int len) +static int buf_check_size(struct cbuf *buf, int len) { if (buf->p + len > buf->ep) { if (buf->p < buf->ep) { @@ -72,7 +72,7 @@ static inline int buf_check_size(struct cbuf *buf, int len) return 1; } -static inline void *buf_alloc(struct cbuf *buf, int len) +static void *buf_alloc(struct cbuf *buf, int len) { void *ret = NULL; @@ -84,7 +84,7 @@ static inline void *buf_alloc(struct cbuf *buf, int len) return ret; } -static inline void buf_put_int8(struct cbuf *buf, u8 val) +static void buf_put_int8(struct cbuf *buf, u8 val) { if (buf_check_size(buf, 1)) { buf->p[0] = val; @@ -92,7 +92,7 @@ static inline void buf_put_int8(struct cbuf *buf, u8 val) } } -static inline void buf_put_int16(struct cbuf *buf, u16 val) +static void buf_put_int16(struct cbuf *buf, u16 val) { if (buf_check_size(buf, 2)) { *(__le16 *) buf->p = cpu_to_le16(val); @@ -100,7 +100,7 @@ static inline void buf_put_int16(struct cbuf *buf, u16 val) } } -static inline void buf_put_int32(struct cbuf *buf, u32 val) +static void buf_put_int32(struct cbuf *buf, u32 val) { if (buf_check_size(buf, 4)) { *(__le32 *)buf->p = cpu_to_le32(val); @@ -108,7 +108,7 @@ static inline void buf_put_int32(struct cbuf *buf, u32 val) } } -static inline void buf_put_int64(struct cbuf *buf, u64 val) +static void buf_put_int64(struct cbuf *buf, u64 val) { if (buf_check_size(buf, 8)) { *(__le64 *)buf->p = cpu_to_le64(val); @@ -116,7 +116,7 @@ static inline void buf_put_int64(struct cbuf *buf, u64 val) } } -static inline void buf_put_stringn(struct cbuf *buf, const char *s, u16 slen) +static void buf_put_stringn(struct cbuf *buf, const char *s, u16 slen) { if (buf_check_size(buf, slen + 2)) { buf_put_int16(buf, slen); @@ -130,7 +130,7 @@ static inline void buf_put_string(struct cbuf *buf, const char *s) buf_put_stringn(buf, s, strlen(s)); } -static inline u8 buf_get_int8(struct cbuf *buf) +static u8 buf_get_int8(struct cbuf *buf) { u8 ret = 0; @@ -142,7 +142,7 @@ static inline u8 buf_get_int8(struct cbuf *buf) return ret; } -static inline u16 buf_get_int16(struct cbuf *buf) +static u16 buf_get_int16(struct cbuf *buf) { u16 ret = 0; @@ -154,7 +154,7 @@ static inline u16 buf_get_int16(struct cbuf *buf) return ret; } -static inline u32 buf_get_int32(struct cbuf *buf) +static u32 buf_get_int32(struct cbuf *buf) { u32 ret = 0; @@ -166,7 +166,7 @@ static inline u32 buf_get_int32(struct cbuf *buf) return ret; } -static inline u64 buf_get_int64(struct cbuf *buf) +static u64 buf_get_int64(struct cbuf *buf) { u64 ret = 0; @@ -178,7 +178,7 @@ static inline u64 buf_get_int64(struct cbuf *buf) return ret; } -static inline void buf_get_str(struct cbuf *buf, struct v9fs_str *vstr) +static void buf_get_str(struct cbuf *buf, struct v9fs_str *vstr) { vstr->len = buf_get_int16(buf); if (!buf_check_overflow(buf) && buf_check_size(buf, vstr->len)) { @@ -190,7 +190,7 @@ static inline void buf_get_str(struct cbuf *buf, struct v9fs_str *vstr) } } -static inline void buf_get_qid(struct cbuf *bufp, struct v9fs_qid *qid) +static void buf_get_qid(struct cbuf *bufp, struct v9fs_qid *qid) { qid->type = buf_get_int8(bufp); qid->version = buf_get_int32(bufp); @@ -254,7 +254,7 @@ static int v9fs_size_wstat(struct v9fs_wstat *wstat, int extended) * */ -static inline void +static void buf_get_stat(struct cbuf *bufp, struct v9fs_stat *stat, int extended) { stat->size = buf_get_int16(bufp); @@ -427,7 +427,7 @@ static inline void v9fs_put_int64(struct cbuf *bufp, u64 val, u64 * p) buf_put_int64(bufp, val); } -static inline void +static void v9fs_put_str(struct cbuf *bufp, char *data, struct v9fs_str *str) { if (data) { @@ -441,7 +441,7 @@ v9fs_put_str(struct cbuf *bufp, char *data, struct v9fs_str *str) buf_put_stringn(bufp, data, str->len); } -static inline int +static int v9fs_put_user_data(struct cbuf *bufp, const char __user * data, int count, unsigned char **pdata) { diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index f979ebbce49..1b117a44129 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1218,7 +1218,7 @@ static int writenote(struct memelfnote *men, struct file *file) if (!dump_seek(file, (off))) \ goto end_coredump; -static inline void fill_elf_header(struct elfhdr *elf, int segs) +static void fill_elf_header(struct elfhdr *elf, int segs) { memcpy(elf->e_ident, ELFMAG, SELFMAG); elf->e_ident[EI_CLASS] = ELF_CLASS; @@ -1243,7 +1243,7 @@ static inline void fill_elf_header(struct elfhdr *elf, int segs) return; } -static inline void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset) +static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset) { phdr->p_type = PT_NOTE; phdr->p_offset = offset; diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index 9ccc7d8275b..6a7b730c206 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -264,7 +264,7 @@ static int unquote(char *from) return p - from; } -static inline char * check_special_flags (char * sfs, Node * e) +static char * check_special_flags (char * sfs, Node * e) { char * p = sfs; int cont = 1; diff --git a/fs/bio.c b/fs/bio.c index 7b306958995..bbc442b8c86 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -123,7 +123,7 @@ static void bio_fs_destructor(struct bio *bio) bio_free(bio, fs_bio_set); } -inline void bio_init(struct bio *bio) +void bio_init(struct bio *bio) { bio->bi_next = NULL; bio->bi_bdev = NULL; @@ -253,7 +253,7 @@ inline int bio_hw_segments(request_queue_t *q, struct bio *bio) * the actual data it points to. Reference count of returned * bio will be one. */ -inline void __bio_clone(struct bio *bio, struct bio *bio_src) +void __bio_clone(struct bio *bio, struct bio *bio_src) { request_queue_t *q = bdev_get_queue(bio_src->bi_bdev); diff --git a/fs/buffer.c b/fs/buffer.c index b9bb7ad6897..7cdf48a9a50 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -1165,7 +1165,7 @@ failed: * some of those buffers may be aliases of filesystem data. * grow_dev_page() will go BUG() if this happens. */ -static inline int +static int grow_buffers(struct block_device *bdev, sector_t block, int size) { struct page *page; @@ -1391,7 +1391,7 @@ static void bh_lru_install(struct buffer_head *bh) /* * Look up the bh in this cpu's LRU. If it's there, move it to the head. */ -static inline struct buffer_head * +static struct buffer_head * lookup_bh_lru(struct block_device *bdev, sector_t block, int size) { struct buffer_head *ret = NULL; @@ -1541,7 +1541,7 @@ EXPORT_SYMBOL(set_bh_page); /* * Called when truncating a buffer on a page completely. */ -static inline void discard_buffer(struct buffer_head * bh) +static void discard_buffer(struct buffer_head * bh) { lock_buffer(bh); clear_buffer_dirty(bh); diff --git a/fs/compat.c b/fs/compat.c index 271b75d1597..2468ac1df2f 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -1537,7 +1537,7 @@ out_ret: * Ooo, nasty. We need here to frob 32-bit unsigned longs to * 64-bit unsigned longs. */ -static inline +static int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset, unsigned long *fdset) { @@ -1570,7 +1570,7 @@ int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset, return 0; } -static inline +static void compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset, unsigned long *fdset) { diff --git a/fs/dcache.c b/fs/dcache.c index 134d6775183..86bdb93789c 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -94,7 +94,7 @@ static void d_free(struct dentry *dentry) * d_iput() operation if defined. * Called with dcache_lock and per dentry lock held, drops both. */ -static inline void dentry_iput(struct dentry * dentry) +static void dentry_iput(struct dentry * dentry) { struct inode *inode = dentry->d_inode; if (inode) { diff --git a/fs/exec.c b/fs/exec.c index b5bcf1aae0a..62b40af68cc 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -575,7 +575,7 @@ static int exec_mmap(struct mm_struct *mm) * disturbing other processes. (Other processes might share the signal * table via the CLONE_SIGHAND option to clone().) */ -static inline int de_thread(struct task_struct *tsk) +static int de_thread(struct task_struct *tsk) { struct signal_struct *sig = tsk->signal; struct sighand_struct *newsighand, *oldsighand = tsk->sighand; @@ -780,7 +780,7 @@ no_thread_group: * so that a new one can be started */ -static inline void flush_old_files(struct files_struct * files) +static void flush_old_files(struct files_struct * files) { long j = -1; struct fdtable *fdt; @@ -964,7 +964,7 @@ int prepare_binprm(struct linux_binprm *bprm) EXPORT_SYMBOL(prepare_binprm); -static inline int unsafe_exec(struct task_struct *p) +static int unsafe_exec(struct task_struct *p) { int unsafe = 0; if (p->ptrace & PT_PTRACED) { diff --git a/fs/fcntl.c b/fs/fcntl.c index d0767fe5836..5f96786d1c7 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -36,7 +36,7 @@ void fastcall set_close_on_exec(unsigned int fd, int flag) spin_unlock(&files->file_lock); } -static inline int get_close_on_exec(unsigned int fd) +static int get_close_on_exec(unsigned int fd) { struct files_struct *files = current->files; struct fdtable *fdt; diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index fff108bb118..70f7a896c04 100644 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c @@ -47,7 +47,7 @@ next_inode(int *i, struct jffs2_inode_cache *ic, struct jffs2_sb_info *c) ic = next_inode(&i, ic, (c))) -static inline void jffs2_build_inode_pass1(struct jffs2_sb_info *c, +static void jffs2_build_inode_pass1(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) { struct jffs2_full_dirent *fd; diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index c79eebb8ab3..b635e167a3f 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -134,7 +134,7 @@ static void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_ /* * Allocate and initializes a new fragment. */ -static inline struct jffs2_node_frag * new_fragment(struct jffs2_full_dnode *fn, uint32_t ofs, uint32_t size) +static struct jffs2_node_frag * new_fragment(struct jffs2_full_dnode *fn, uint32_t ofs, uint32_t size) { struct jffs2_node_frag *newfrag; @@ -513,7 +513,7 @@ free_out: * * Checks the node if we are in the checking stage. */ -static inline int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn) +static int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn) { int ret; diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c index f01e9c0d267..200fbda2c6d 100644 --- a/fs/lockd/xdr.c +++ b/fs/lockd/xdr.c @@ -44,7 +44,7 @@ loff_t_to_s32(loff_t offset) /* * XDR functions for basic NLM types */ -static inline u32 *nlm_decode_cookie(u32 *p, struct nlm_cookie *c) +static u32 *nlm_decode_cookie(u32 *p, struct nlm_cookie *c) { unsigned int len; @@ -79,7 +79,7 @@ nlm_encode_cookie(u32 *p, struct nlm_cookie *c) return p; } -static inline u32 * +static u32 * nlm_decode_fh(u32 *p, struct nfs_fh *f) { unsigned int len; @@ -119,7 +119,7 @@ nlm_encode_oh(u32 *p, struct xdr_netobj *oh) return xdr_encode_netobj(p, oh); } -static inline u32 * +static u32 * nlm_decode_lock(u32 *p, struct nlm_lock *lock) { struct file_lock *fl = &lock->fl; diff --git a/fs/mbcache.c b/fs/mbcache.c index 0f1e4530670..f5bbe4c97c5 100644 --- a/fs/mbcache.c +++ b/fs/mbcache.c @@ -126,7 +126,7 @@ __mb_cache_entry_is_hashed(struct mb_cache_entry *ce) } -static inline void +static void __mb_cache_entry_unhash(struct mb_cache_entry *ce) { int n; @@ -139,7 +139,7 @@ __mb_cache_entry_unhash(struct mb_cache_entry *ce) } -static inline void +static void __mb_cache_entry_forget(struct mb_cache_entry *ce, gfp_t gfp_mask) { struct mb_cache *cache = ce->e_cache; @@ -158,7 +158,7 @@ __mb_cache_entry_forget(struct mb_cache_entry *ce, gfp_t gfp_mask) } -static inline void +static void __mb_cache_entry_release_unlock(struct mb_cache_entry *ce) { /* Wake up all processes queuing for this cache entry. */ diff --git a/fs/namei.c b/fs/namei.c index 1e5746eb138..7bde381fa49 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -113,7 +113,7 @@ * POSIX.1 2.4: an empty pathname is invalid (ENOENT). * PATH_MAX includes the nul terminator --RR. */ -static inline int do_getname(const char __user *filename, char *page) +static int do_getname(const char __user *filename, char *page) { int retval; unsigned long len = PATH_MAX; @@ -396,7 +396,7 @@ static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, * short-cut DAC fails, then call permission() to do more * complete permission check. */ -static inline int exec_permission_lite(struct inode *inode, +static int exec_permission_lite(struct inode *inode, struct nameidata *nd) { umode_t mode = inode->i_mode; @@ -1294,7 +1294,7 @@ static inline int check_sticky(struct inode *dir, struct inode *inode) * 10. We don't allow removal of NFS sillyrenamed files; it's handled by * nfs_async_unlink(). */ -static inline int may_delete(struct inode *dir,struct dentry *victim,int isdir) +static int may_delete(struct inode *dir,struct dentry *victim,int isdir) { int error; @@ -2315,7 +2315,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, return error; } -static inline int do_rename(const char * oldname, const char * newname) +static int do_rename(const char * oldname, const char * newname) { int error = 0; struct dentry * old_dir, * new_dir; diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c index aa7bb41b293..e3a0797dd56 100644 --- a/fs/nfsd/nfsxdr.c +++ b/fs/nfsd/nfsxdr.c @@ -37,7 +37,7 @@ static u32 nfs_ftypes[] = { /* * XDR functions for basic NFS types */ -static inline u32 * +static u32 * decode_fh(u32 *p, struct svc_fh *fhp) { fh_init(fhp, NFS_FHSIZE); @@ -151,7 +151,7 @@ decode_sattr(u32 *p, struct iattr *iap) return p; } -static inline u32 * +static u32 * encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp, struct kstat *stat) { diff --git a/fs/pipe.c b/fs/pipe.c index eef0f29e86e..d722579df79 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -50,7 +50,7 @@ void pipe_wait(struct inode * inode) mutex_lock(PIPE_MUTEX(*inode)); } -static inline int +static int pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len) { unsigned long copy; @@ -70,7 +70,7 @@ pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len) return 0; } -static inline int +static int pipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len) { unsigned long copy; diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 2a75e44e1a4..d4b6bd7d74e 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -1554,7 +1554,7 @@ struct ctr_struct { * when reading out p->cpuset, as we don't really care if it changes * on the next cycle, and we are not going to try to dereference it. */ -static inline int pid_array_load(pid_t *pidarray, int npids, struct cpuset *cs) +static int pid_array_load(pid_t *pidarray, int npids, struct cpuset *cs) { int n = 0; struct task_struct *g, *p; diff --git a/kernel/exit.c b/kernel/exit.c index 7fb541cb8d6..93cee367133 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -193,7 +193,7 @@ int is_orphaned_pgrp(int pgrp) return retval; } -static inline int has_stopped_jobs(int pgrp) +static int has_stopped_jobs(int pgrp) { int retval = 0; struct task_struct *p; @@ -230,7 +230,7 @@ static inline int has_stopped_jobs(int pgrp) * * NOTE that reparent_to_init() gives the caller full capabilities. */ -static inline void reparent_to_init(void) +static void reparent_to_init(void) { write_lock_irq(&tasklist_lock); @@ -369,7 +369,7 @@ void daemonize(const char *name, ...) EXPORT_SYMBOL(daemonize); -static inline void close_files(struct files_struct * files) +static void close_files(struct files_struct * files) { int i, j; struct fdtable *fdt; @@ -543,7 +543,7 @@ static inline void choose_new_parent(task_t *p, task_t *reaper, task_t *child_re p->real_parent = reaper; } -static inline void reparent_thread(task_t *p, task_t *father, int traced) +static void reparent_thread(task_t *p, task_t *father, int traced) { /* We don't want people slaying init. */ if (p->exit_signal != -1) @@ -607,7 +607,7 @@ static inline void reparent_thread(task_t *p, task_t *father, int traced) * group, and if no such member exists, give it to * the global child reaper process (ie "init") */ -static inline void forget_original_parent(struct task_struct * father, +static void forget_original_parent(struct task_struct * father, struct list_head *to_release) { struct task_struct *p, *reaper = father; diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index 9e66e614862..197208b3aa2 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -192,7 +192,7 @@ static inline int common_clock_set(const clockid_t which_clock, return do_sys_settimeofday(tp, NULL); } -static inline int common_timer_create(struct k_itimer *new_timer) +static int common_timer_create(struct k_itimer *new_timer) { hrtimer_init(&new_timer->it.real.timer, new_timer->it_clock); new_timer->it.real.timer.data = new_timer; @@ -361,7 +361,7 @@ static int posix_timer_fn(void *data) return ret; } -static inline struct task_struct * good_sigevent(sigevent_t * event) +static struct task_struct * good_sigevent(sigevent_t * event) { struct task_struct *rtn = current->group_leader; @@ -687,7 +687,7 @@ sys_timer_getoverrun(timer_t timer_id) /* Set a POSIX.1b interval timer. */ /* timr->it_lock is taken. */ -static inline int +static int common_timer_set(struct k_itimer *timr, int flags, struct itimerspec *new_setting, struct itimerspec *old_setting) { @@ -829,7 +829,7 @@ retry_delete: /* * return timer owned by the process, used by exit_itimers */ -static inline void itimer_delete(struct k_itimer *timer) +static void itimer_delete(struct k_itimer *timer) { unsigned long flags; diff --git a/kernel/sched.c b/kernel/sched.c index e1dc903d5a7..788ecce1e0e 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -521,7 +521,7 @@ static inline void sched_info_dequeued(task_t *t) * long it was waiting to run. We also note when it began so that we * can keep stats on how long its timeslice is. */ -static inline void sched_info_arrive(task_t *t) +static void sched_info_arrive(task_t *t) { unsigned long now = jiffies, diff = 0; struct runqueue *rq = task_rq(t); @@ -1007,7 +1007,7 @@ void kick_process(task_t *p) * We want to under-estimate the load of migration sources, to * balance conservatively. */ -static inline unsigned long __source_load(int cpu, int type, enum idle_type idle) +static unsigned long __source_load(int cpu, int type, enum idle_type idle) { runqueue_t *rq = cpu_rq(cpu); unsigned long running = rq->nr_running; @@ -1870,7 +1870,7 @@ void sched_exec(void) * pull_task - move a task from a remote runqueue to the local runqueue. * Both runqueues must be locked. */ -static inline +static void pull_task(runqueue_t *src_rq, prio_array_t *src_array, task_t *p, runqueue_t *this_rq, prio_array_t *this_array, int this_cpu) { @@ -1892,7 +1892,7 @@ void pull_task(runqueue_t *src_rq, prio_array_t *src_array, task_t *p, /* * can_migrate_task - may task p from runqueue rq be migrated to this_cpu? */ -static inline +static int can_migrate_task(task_t *p, runqueue_t *rq, int this_cpu, struct sched_domain *sd, enum idle_type idle, int *all_pinned) @@ -2378,7 +2378,7 @@ out_balanced: * idle_balance is called by schedule() if this_cpu is about to become * idle. Attempts to pull tasks from other CPUs. */ -static inline void idle_balance(int this_cpu, runqueue_t *this_rq) +static void idle_balance(int this_cpu, runqueue_t *this_rq) { struct sched_domain *sd; @@ -2762,7 +2762,7 @@ static inline void wakeup_busy_runqueue(runqueue_t *rq) resched_task(rq->idle); } -static inline void wake_sleeping_dependent(int this_cpu, runqueue_t *this_rq) +static void wake_sleeping_dependent(int this_cpu, runqueue_t *this_rq) { struct sched_domain *tmp, *sd = NULL; cpumask_t sibling_map; @@ -2816,7 +2816,7 @@ static inline unsigned long smt_slice(task_t *p, struct sched_domain *sd) return p->time_slice * (100 - sd->per_cpu_gain) / 100; } -static inline int dependent_sleeper(int this_cpu, runqueue_t *this_rq) +static int dependent_sleeper(int this_cpu, runqueue_t *this_rq) { struct sched_domain *tmp, *sd = NULL; cpumask_t sibling_map; @@ -6008,7 +6008,7 @@ next_sg: * Detach sched domains from a group of cpus specified in cpu_map * These cpus will now be attached to the NULL domain */ -static inline void detach_destroy_domains(const cpumask_t *cpu_map) +static void detach_destroy_domains(const cpumask_t *cpu_map) { int i; diff --git a/kernel/signal.c b/kernel/signal.c index 1da2e74beb9..5dafbd36d62 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -476,7 +476,7 @@ unblock_all_signals(void) spin_unlock_irqrestore(¤t->sighand->siglock, flags); } -static inline int collect_signal(int sig, struct sigpending *list, siginfo_t *info) +static int collect_signal(int sig, struct sigpending *list, siginfo_t *info) { struct sigqueue *q, *first = NULL; int still_pending = 0; @@ -1881,7 +1881,7 @@ do_signal_stop(int signr) * We return zero if we still hold the siglock and should look * for another signal without checking group_stop_count again. */ -static inline int handle_group_stop(void) +static int handle_group_stop(void) { int stop_count; diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 82c4fa70595..b052e2c4c71 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -147,7 +147,7 @@ int fastcall queue_delayed_work(struct workqueue_struct *wq, return ret; } -static inline void run_workqueue(struct cpu_workqueue_struct *cwq) +static void run_workqueue(struct cpu_workqueue_struct *cwq) { unsigned long flags; diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c index 321287bc887..90d18b72da3 100644 --- a/net/ieee80211/ieee80211_module.c +++ b/net/ieee80211/ieee80211_module.c @@ -62,7 +62,7 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION); MODULE_AUTHOR(DRV_COPYRIGHT); MODULE_LICENSE("GPL"); -static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee) +static int ieee80211_networks_allocate(struct ieee80211_device *ieee) { if (ieee->networks) return 0; @@ -90,7 +90,7 @@ static inline void ieee80211_networks_free(struct ieee80211_device *ieee) ieee->networks = NULL; } -static inline void ieee80211_networks_initialize(struct ieee80211_device *ieee) +static void ieee80211_networks_initialize(struct ieee80211_device *ieee) { int i; diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index 5e338038804..7a121802faa 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c @@ -35,7 +35,7 @@ #include -static inline void ieee80211_monitor_rx(struct ieee80211_device *ieee, +static void ieee80211_monitor_rx(struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_rx_stats *rx_stats) { @@ -165,7 +165,7 @@ static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee, * Responsible for handling management control frames * * Called by ieee80211_rx */ -static inline int +static int ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_rx_stats *rx_stats, u16 type, u16 stype) @@ -266,7 +266,7 @@ static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee, } /* Called only as a tasklet (software IRQ), by ieee80211_rx */ -static inline int +static int ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_crypt_data *crypt) { @@ -297,7 +297,7 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb, } /* Called only as a tasklet (software IRQ), by ieee80211_rx */ -static inline int +static int ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee, struct sk_buff *skb, int keyidx, struct ieee80211_crypt_data *crypt) @@ -1156,7 +1156,7 @@ static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct iee /***************************************************/ -static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct ieee80211_probe_response +static int ieee80211_network_init(struct ieee80211_device *ieee, struct ieee80211_probe_response *beacon, struct ieee80211_network *network, struct ieee80211_rx_stats *stats) @@ -1235,7 +1235,7 @@ static inline int is_same_network(struct ieee80211_network *src, !memcmp(src->ssid, dst->ssid, src->ssid_len)); } -static inline void update_network(struct ieee80211_network *dst, +static void update_network(struct ieee80211_network *dst, struct ieee80211_network *src) { int qos_active; @@ -1294,7 +1294,7 @@ static inline int is_beacon(int fc) return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == IEEE80211_STYPE_BEACON); } -static inline void ieee80211_process_probe_response(struct ieee80211_device +static void ieee80211_process_probe_response(struct ieee80211_device *ieee, struct ieee80211_probe_response *beacon, struct ieee80211_rx_stats diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c index e5b33c8d5db..8fdd943ebe8 100644 --- a/net/ieee80211/ieee80211_tx.c +++ b/net/ieee80211/ieee80211_tx.c @@ -127,7 +127,7 @@ payload of each frame is reduced to 492 bytes. static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 }; static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 }; -static inline int ieee80211_copy_snap(u8 * data, u16 h_proto) +static int ieee80211_copy_snap(u8 * data, u16 h_proto) { struct ieee80211_snap_hdr *snap; u8 *oui; @@ -150,7 +150,7 @@ static inline int ieee80211_copy_snap(u8 * data, u16 h_proto) return SNAP_SIZE + sizeof(u16); } -static inline int ieee80211_encrypt_fragment(struct ieee80211_device *ieee, +static int ieee80211_encrypt_fragment(struct ieee80211_device *ieee, struct sk_buff *frag, int hdr_len) { struct ieee80211_crypt_data *crypt = ieee->crypt[ieee->tx_keyidx]; diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c index 406d5b96490..23e1630f50b 100644 --- a/net/ieee80211/ieee80211_wx.c +++ b/net/ieee80211/ieee80211_wx.c @@ -42,7 +42,7 @@ static const char *ieee80211_modes[] = { }; #define MAX_CUSTOM_LEN 64 -static inline char *ipw2100_translate_scan(struct ieee80211_device *ieee, +static char *ipw2100_translate_scan(struct ieee80211_device *ieee, char *start, char *stop, struct ieee80211_network *network) { diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 95fdf04f1d8..f6063e8f005 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c @@ -212,7 +212,7 @@ int nfnetlink_unicast(struct sk_buff *skb, u_int32_t pid, int flags) } /* Process one complete nfnetlink message. */ -static inline int nfnetlink_rcv_msg(struct sk_buff *skb, +static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) { struct nfnl_callback *nc; diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 6647204e463..b9f8d9731c3 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1019,7 +1019,7 @@ static inline int dentry_has_perm(struct task_struct *tsk, has the same SID as the process. If av is zero, then access to the file is not checked, e.g. for cases where only the descriptor is affected like seek. */ -static inline int file_has_perm(struct task_struct *tsk, +static int file_has_perm(struct task_struct *tsk, struct file *file, u32 av) { diff --git a/sound/oss/esssolo1.c b/sound/oss/esssolo1.c index a4ecab2f052..849b59f67ef 100644 --- a/sound/oss/esssolo1.c +++ b/sound/oss/esssolo1.c @@ -515,7 +515,7 @@ static inline int prog_dmabuf_adc(struct solo1_state *s) return 0; } -static inline int prog_dmabuf_dac(struct solo1_state *s) +static int prog_dmabuf_dac(struct solo1_state *s) { unsigned long va; int c; diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 9ffb600321c..3747a436f0c 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -727,7 +727,7 @@ static void __apu_set_register(struct es1968 *chip, u16 channel, u8 reg, u16 dat apu_data_set(chip, data); } -static inline void apu_set_register(struct es1968 *chip, u16 channel, u8 reg, u16 data) +static void apu_set_register(struct es1968 *chip, u16 channel, u8 reg, u16 data) { unsigned long flags; spin_lock_irqsave(&chip->reg_lock, flags); @@ -743,7 +743,7 @@ static u16 __apu_get_register(struct es1968 *chip, u16 channel, u8 reg) return __maestro_read(chip, IDR0_DATA_PORT); } -static inline u16 apu_get_register(struct es1968 *chip, u16 channel, u8 reg) +static u16 apu_get_register(struct es1968 *chip, u16 channel, u8 reg) { unsigned long flags; u16 v; -- GitLab From ee7be5de357b8ff69afc8c39648b336cd917218a Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Sat, 14 Jan 2006 13:20:44 -0800 Subject: [PATCH 262/465] [PATCH] uml: fix symbol for mktime LD .tmp_vmlinux1 /usr/lib/gcc-lib/i486-linux/3.3.4/../../../libc.a(mktime.o): In function `timelocal': : multiple definition of `mktime' kernel/built-in.o:kernel/time.c:604: first defined here /usr/bin/ld: Warning: size of symbol `mktime' changed from 134 in kernel/built-in.o to 44 in /usr/lib/gcc-lib/i486-linux/3.3.4/../../../libc.a(mktime.o) collect2: ld returned 1 exit status Signed-off-by: Miklos Szeredi Cc: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/um/Makefile b/arch/um/Makefile index 322972fd064..45435ff589c 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -67,7 +67,8 @@ USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \ # in CFLAGS. Otherwise, it would cause ld to complain about the two different # errnos. -CFLAGS += -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask +CFLAGS += -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask \ + -Dmktime=kernel_mktime CFLAGS += $(call cc-option,-fno-unit-at-a-time,) include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH) -- GitLab From eed6565f70ce3fc958e5a3483c48fc4a8e111bdc Mon Sep 17 00:00:00 2001 From: "Calin A. Culianu" Date: Sat, 14 Jan 2006 13:20:46 -0800 Subject: [PATCH 263/465] [PATCH] Watchdog: Winsystems EPX-C3 SBC This is a 2.6 patch that adds support for the watchdog timer built into the EPX-C3 single board computer manufactured by Winsystems, Inc. Driver details: This is for x86 only. This watchdog is pretty basic and simple. It is only configurable via jumpers on the SBC, and it only has either a 1.5s or 200s interval. The watchdog can either be auto-configured to start as soon as the machine powers up (bad idea for the 1.5s interval!) or it can be enabled and disabled by writing to io port 0x1ee. Petting the watchdog involves writing any value to io port 0x1ef. The only unfortunate thing about this watchdog (and it is not at all uncommmon in watchdogs that linux supports) is that it is not a PCI or ISA-PNP device and as such it isn't at all probeable. Either the watchdog exists as 2 bytes at 0x1ee, or it doesn't. Thus, using this driver on a machine that doesn't have that watchdog can potentially hang/crash the system, etc. So only use this driver if you in fact are on a Winsystems EPX-C3 SBC. Anyway this driver fits into the already-existing watchdog framework quite nicely and I already tested it on my EPX-C3 and it works like a charm. Signed-off-by: Calin A. Culianu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/watchdog/Kconfig | 22 +++ drivers/char/watchdog/Makefile | 1 + drivers/char/watchdog/sbc_epx_c3.c | 216 +++++++++++++++++++++++++++++ 3 files changed, 239 insertions(+) create mode 100644 drivers/char/watchdog/sbc_epx_c3.c diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index a6544790af6..f68aaa60fa8 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig @@ -395,6 +395,28 @@ config MACHZ_WDT To compile this driver as a module, choose M here: the module will be called machzwd. +config SBC_EPX_C3_WATCHDOG + tristate "Winsystems SBC EPX-C3 watchdog" + depends on WATCHDOG && X86 + ---help--- + This is the driver for the built-in watchdog timer on the EPX-C3 + Single-board computer made by Winsystems, Inc. + + *Note*: This hardware watchdog is not probeable and thus there + is no way to know if writing to its IO address will corrupt + your system or have any real effect. The only way to be sure + that this driver does what you want is to make sure you + are runnning it on an EPX-C3 from Winsystems with the watchdog + timer at IO address 0x1ee and 0x1ef. It will write to both those + IO ports. Basically, the assumption is made that if you compile + this driver into your kernel and/or load it as a module, that you + know what you are doing and that you are in fact running on an + EPX-C3 board! + + To compile this driver as a module, choose M here: the + module will be called sbc_epx_c3. + + # PowerPC Architecture config 8xx_WDT diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile index cfd0a398771..4fa2ca8e943 100644 --- a/drivers/char/watchdog/Makefile +++ b/drivers/char/watchdog/Makefile @@ -52,6 +52,7 @@ obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o obj-$(CONFIG_MACHZ_WDT) += machzwd.o +obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o # PowerPC Architecture obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o diff --git a/drivers/char/watchdog/sbc_epx_c3.c b/drivers/char/watchdog/sbc_epx_c3.c new file mode 100644 index 00000000000..951764614eb --- /dev/null +++ b/drivers/char/watchdog/sbc_epx_c3.c @@ -0,0 +1,216 @@ +/* + * SBC EPX C3 0.1 A Hardware Watchdog Device for the Winsystems EPX-C3 + * single board computer + * + * (c) Copyright 2006 Calin A. Culianu , All Rights + * Reserved. + * + * 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. + * + * based on softdog.c by Alan Cox + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PFX "epx_c3: " +static int epx_c3_alive; + +#define WATCHDOG_TIMEOUT 1 /* 1 sec default timeout */ + +static int nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); + +#define EPXC3_WATCHDOG_CTL_REG 0x1ee /* write 1 to enable, 0 to disable */ +#define EPXC3_WATCHDOG_PET_REG 0x1ef /* write anything to pet once enabled */ + +static void epx_c3_start(void) +{ + outb(1, EPXC3_WATCHDOG_CTL_REG); +} + +static void epx_c3_stop(void) +{ + + outb(0, EPXC3_WATCHDOG_CTL_REG); + + printk(KERN_INFO PFX "Stopped watchdog timer.\n"); +} + +static void epx_c3_pet(void) +{ + outb(1, EPXC3_WATCHDOG_PET_REG); +} + +/* + * Allow only one person to hold it open + */ +static int epx_c3_open(struct inode *inode, struct file *file) +{ + if (epx_c3_alive) + return -EBUSY; + + if (nowayout) + __module_get(THIS_MODULE); + + /* Activate timer */ + epx_c3_start(); + epx_c3_pet(); + + epx_c3_alive = 1; + printk(KERN_INFO "Started watchdog timer.\n"); + + return nonseekable_open(inode, file); +} + +static int epx_c3_release(struct inode *inode, struct file *file) +{ + /* Shut off the timer. + * Lock it in if it's a module and we defined ...NOWAYOUT */ + if (!nowayout) + epx_c3_stop(); /* Turn the WDT off */ + + epx_c3_alive = 0; + + return 0; +} + +static ssize_t epx_c3_write(struct file *file, const char *data, + size_t len, loff_t *ppos) +{ + /* Refresh the timer. */ + if (len) + epx_c3_pet(); + return len; +} + +static int epx_c3_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + int options, retval = -EINVAL; + static struct watchdog_info ident = { + .options = WDIOF_KEEPALIVEPING | + WDIOF_MAGICCLOSE, + .firmware_version = 0, + .identity = "Winsystems EPX-C3 H/W Watchdog", + }; + + switch (cmd) { + case WDIOC_GETSUPPORT: + if (copy_to_user((struct watchdog_info *)arg, + &ident, sizeof(ident))) + return -EFAULT; + return 0; + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0,(int *)arg); + case WDIOC_KEEPALIVE: + epx_c3_pet(); + return 0; + case WDIOC_GETTIMEOUT: + return put_user(WATCHDOG_TIMEOUT,(int *)arg); + case WDIOC_SETOPTIONS: { + if (get_user(options, (int *)arg)) + return -EFAULT; + + if (options & WDIOS_DISABLECARD) { + epx_c3_stop(); + retval = 0; + } + + if (options & WDIOS_ENABLECARD) { + epx_c3_start(); + retval = 0; + } + + return retval; + } + default: + return -ENOIOCTLCMD; + } +} + +static int epx_c3_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if (code == SYS_DOWN || code == SYS_HALT) + epx_c3_stop(); /* Turn the WDT off */ + + return NOTIFY_DONE; +} + +static struct file_operations epx_c3_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = epx_c3_write, + .ioctl = epx_c3_ioctl, + .open = epx_c3_open, + .release = epx_c3_release, +}; + +static struct miscdevice epx_c3_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &epx_c3_fops, +}; + +static struct notifier_block epx_c3_notifier = { + .notifier_call = epx_c3_notify_sys, +}; + +static const char banner[] __initdata = + KERN_INFO PFX "Hardware Watchdog Timer for Winsystems EPX-C3 SBC: 0.1\n"; + +static int __init watchdog_init(void) +{ + int ret; + + ret = register_reboot_notifier(&epx_c3_notifier); + if (ret) { + printk(KERN_ERR PFX "cannot register reboot notifier " + "(err=%d)\n", ret); + return ret; + } + + ret = misc_register(&epx_c3_miscdev); + if (ret) { + printk(KERN_ERR PFX "cannot register miscdev on minor=%d " + "(err=%d)\n", WATCHDOG_MINOR, ret); + unregister_reboot_notifier(&epx_c3_notifier); + return ret; + } + + printk(banner); + + return 0; +} + +static void __exit watchdog_exit(void) +{ + misc_deregister(&epx_c3_miscdev); + unregister_reboot_notifier(&epx_c3_notifier); +} + +module_init(watchdog_init); +module_exit(watchdog_exit); + +MODULE_AUTHOR("Calin A. Culianu "); +MODULE_DESCRIPTION("Hardware Watchdog Device for Winsystems EPX-C3 SBC. Note that there is no way to probe for this device -- so only use it if you are *sure* you are runnning on this specific SBC system from Winsystems! It writes to IO ports 0x1ee and 0x1ef!"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- GitLab From 852cf918dcf2ae46468b425e679fbcbf0ea8fdbb Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Sat, 14 Jan 2006 13:20:46 -0800 Subject: [PATCH 264/465] [PATCH] Fix for CONFIG_NUMA without CONFIG_SWAP Some people apparently run CONFIG_NUMA without CONFIG_SWAP. The migration code currently depends on swap. This patch provides a set of inline fallback functions so that the kernel properly compiles. However, calls to migration functions will fail. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/swap.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/linux/swap.h b/include/linux/swap.h index 389d1c382e2..e92054d6530 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -180,6 +180,11 @@ extern int isolate_lru_page(struct page *p); extern int putback_lru_pages(struct list_head *l); extern int migrate_pages(struct list_head *l, struct list_head *t, struct list_head *moved, struct list_head *failed); +#else +static inline int isolate_lru_page(struct page *p) { return -ENOSYS; } +static inline int putback_lru_pages(struct list_head *l) { return 0; } +static inline int migrate_pages(struct list_head *l, struct list_head *t, + struct list_head *moved, struct list_head *failed) { return -ENOSYS; } #endif #ifdef CONFIG_MMU -- GitLab From 7339ff8302fd70aabf5f1ae26e0c4905fa74a495 Mon Sep 17 00:00:00 2001 From: Robin Holt Date: Sat, 14 Jan 2006 13:20:48 -0800 Subject: [PATCH 265/465] [PATCH] Add tmpfs options for memory placement policies Anything that writes into a tmpfs filesystem is liable to disproportionately decrease the available memory on a particular node. Since there's no telling what sort of application (e.g. dd/cp/cat) might be dropping large files there, this lets the admin choose the appropriate default behavior for their site's situation. Introduce a tmpfs mount option which allows specifying a memory policy and a second option to specify the nodelist for that policy. With the default policy, tmpfs will behave as it does today. This patch adds support for preferred, bind, and interleave policies. The default policy will cause pages to be added to tmpfs files on the node which is doing the writing. Some jobs expect a single process to create and manage the tmpfs files. This results in a node which has a significantly reduced number of free pages. With this patch, the administrator can specify the policy and nodes for that policy where they would prefer allocations. This patch was originally written by Brent Casavant and Hugh Dickins. I added support for the bind and preferred policies and the mpol_nodelist mount option. Signed-off-by: Brent Casavant Signed-off-by: Hugh Dickins Signed-off-by: Robin Holt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/filesystems/tmpfs.txt | 12 +++++++++ fs/hugetlbfs/inode.c | 2 +- include/linux/mempolicy.h | 11 +++----- include/linux/shmem_fs.h | 2 ++ mm/mempolicy.c | 24 ++++++++++++++++++ mm/shmem.c | 39 +++++++++++++++++++++++------ 6 files changed, 75 insertions(+), 15 deletions(-) diff --git a/Documentation/filesystems/tmpfs.txt b/Documentation/filesystems/tmpfs.txt index 0d783c504ea..dbe4d87d261 100644 --- a/Documentation/filesystems/tmpfs.txt +++ b/Documentation/filesystems/tmpfs.txt @@ -78,6 +78,18 @@ use up all the memory on the machine; but enhances the scalability of that instance in a system with many cpus making intensive use of it. +tmpfs has a mount option to set the NUMA memory allocation policy for +all files in that instance: +mpol=interleave prefers to allocate memory from each node in turn +mpol=default prefers to allocate memory from the local node +mpol=bind prefers to allocate from mpol_nodelist +mpol=preferred prefers to allocate from first node in mpol_nodelist + +The following mount option is used in conjunction with mpol=interleave, +mpol=bind or mpol=preferred: +mpol_nodelist: nodelist suitable for parsing with nodelist_parse. + + To specify the initial root directory you can use the following mount options: diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index ab4c3a9d51b..f568102da1e 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -402,7 +402,7 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid, inode->i_mapping->backing_dev_info =&hugetlbfs_backing_dev_info; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; info = HUGETLBFS_I(inode); - mpol_shared_policy_init(&info->policy); + mpol_shared_policy_init(&info->policy, MPOL_DEFAULT, NULL); switch (mode & S_IFMT) { default: init_special_inode(inode, mode, dev); diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h index c7ac77e873b..d6a53ed6ab6 100644 --- a/include/linux/mempolicy.h +++ b/include/linux/mempolicy.h @@ -132,12 +132,8 @@ struct shared_policy { spinlock_t lock; }; -static inline void mpol_shared_policy_init(struct shared_policy *info) -{ - info->root = RB_ROOT; - spin_lock_init(&info->lock); -} - +void mpol_shared_policy_init(struct shared_policy *info, int policy, + nodemask_t *nodes); int mpol_set_shared_policy(struct shared_policy *info, struct vm_area_struct *vma, struct mempolicy *new); @@ -211,7 +207,8 @@ static inline int mpol_set_shared_policy(struct shared_policy *info, return -EINVAL; } -static inline void mpol_shared_policy_init(struct shared_policy *info) +static inline void mpol_shared_policy_init(struct shared_policy *info, + int policy, nodemask_t *nodes) { } diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h index c3e598276e7..c057f0b3231 100644 --- a/include/linux/shmem_fs.h +++ b/include/linux/shmem_fs.h @@ -26,6 +26,8 @@ struct shmem_sb_info { unsigned long free_blocks; /* How many are left for allocation */ unsigned long max_inodes; /* How many inodes are allowed */ unsigned long free_inodes; /* How many are left for allocation */ + int policy; /* Default NUMA memory alloc policy */ + nodemask_t policy_nodes; /* nodemask for preferred and bind */ spinlock_t stat_lock; }; diff --git a/mm/mempolicy.c b/mm/mempolicy.c index b62cab575a8..3171f884d24 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -1359,6 +1359,30 @@ restart: return 0; } +void mpol_shared_policy_init(struct shared_policy *info, int policy, + nodemask_t *policy_nodes) +{ + info->root = RB_ROOT; + spin_lock_init(&info->lock); + + if (policy != MPOL_DEFAULT) { + struct mempolicy *newpol; + + /* Falls back to MPOL_DEFAULT on any error */ + newpol = mpol_new(policy, policy_nodes); + if (!IS_ERR(newpol)) { + /* Create pseudo-vma that contains just the policy */ + struct vm_area_struct pvma; + + memset(&pvma, 0, sizeof(struct vm_area_struct)); + /* Policy covers entire file */ + pvma.vm_end = TASK_SIZE; + mpol_set_shared_policy(info, &pvma, newpol); + mpol_free(newpol); + } + } +} + int mpol_set_shared_policy(struct shared_policy *info, struct vm_area_struct *vma, struct mempolicy *npol) { diff --git a/mm/shmem.c b/mm/shmem.c index 343b3c0937e..ce501bce1c2 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1316,7 +1316,8 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev) case S_IFREG: inode->i_op = &shmem_inode_operations; inode->i_fop = &shmem_file_operations; - mpol_shared_policy_init(&info->policy); + mpol_shared_policy_init(&info->policy, sbinfo->policy, + &sbinfo->policy_nodes); break; case S_IFDIR: inode->i_nlink++; @@ -1330,7 +1331,8 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev) * Must not load anything in the rbtree, * mpol_free_shared_policy will not be called. */ - mpol_shared_policy_init(&info->policy); + mpol_shared_policy_init(&info->policy, MPOL_DEFAULT, + NULL); break; } } else if (sbinfo->max_inodes) { @@ -1843,7 +1845,9 @@ static struct inode_operations shmem_symlink_inode_operations = { .put_link = shmem_put_link, }; -static int shmem_parse_options(char *options, int *mode, uid_t *uid, gid_t *gid, unsigned long *blocks, unsigned long *inodes) +static int shmem_parse_options(char *options, int *mode, uid_t *uid, + gid_t *gid, unsigned long *blocks, unsigned long *inodes, + int *policy, nodemask_t *policy_nodes) { char *this_char, *value, *rest; @@ -1897,6 +1901,19 @@ static int shmem_parse_options(char *options, int *mode, uid_t *uid, gid_t *gid, *gid = simple_strtoul(value,&rest,0); if (*rest) goto bad_val; + } else if (!strcmp(this_char,"mpol")) { + if (!strcmp(value,"default")) + *policy = MPOL_DEFAULT; + else if (!strcmp(value,"preferred")) + *policy = MPOL_PREFERRED; + else if (!strcmp(value,"bind")) + *policy = MPOL_BIND; + else if (!strcmp(value,"interleave")) + *policy = MPOL_INTERLEAVE; + else + goto bad_val; + } else if (!strcmp(this_char,"mpol_nodelist")) { + nodelist_parse(value, *policy_nodes); } else { printk(KERN_ERR "tmpfs: Bad mount option %s\n", this_char); @@ -1917,12 +1934,14 @@ static int shmem_remount_fs(struct super_block *sb, int *flags, char *data) struct shmem_sb_info *sbinfo = SHMEM_SB(sb); unsigned long max_blocks = sbinfo->max_blocks; unsigned long max_inodes = sbinfo->max_inodes; + int policy = sbinfo->policy; + nodemask_t policy_nodes = sbinfo->policy_nodes; unsigned long blocks; unsigned long inodes; int error = -EINVAL; - if (shmem_parse_options(data, NULL, NULL, NULL, - &max_blocks, &max_inodes)) + if (shmem_parse_options(data, NULL, NULL, NULL, &max_blocks, + &max_inodes, &policy, &policy_nodes)) return error; spin_lock(&sbinfo->stat_lock); @@ -1948,6 +1967,8 @@ static int shmem_remount_fs(struct super_block *sb, int *flags, char *data) sbinfo->free_blocks = max_blocks - blocks; sbinfo->max_inodes = max_inodes; sbinfo->free_inodes = max_inodes - inodes; + sbinfo->policy = policy; + sbinfo->policy_nodes = policy_nodes; out: spin_unlock(&sbinfo->stat_lock); return error; @@ -1972,6 +1993,8 @@ static int shmem_fill_super(struct super_block *sb, struct shmem_sb_info *sbinfo; unsigned long blocks = 0; unsigned long inodes = 0; + int policy = MPOL_DEFAULT; + nodemask_t policy_nodes = node_online_map; #ifdef CONFIG_TMPFS /* @@ -1984,8 +2007,8 @@ static int shmem_fill_super(struct super_block *sb, inodes = totalram_pages - totalhigh_pages; if (inodes > blocks) inodes = blocks; - if (shmem_parse_options(data, &mode, &uid, &gid, - &blocks, &inodes)) + if (shmem_parse_options(data, &mode, &uid, &gid, &blocks, + &inodes, &policy, &policy_nodes)) return -EINVAL; } #else @@ -2003,6 +2026,8 @@ static int shmem_fill_super(struct super_block *sb, sbinfo->free_blocks = blocks; sbinfo->max_inodes = inodes; sbinfo->free_inodes = inodes; + sbinfo->policy = policy; + sbinfo->policy_nodes = policy_nodes; sb->s_fs_info = sbinfo; sb->s_maxbytes = SHMEM_MAX_BYTES; -- GitLab From fabbfb9e8c53416eaa4f62b957430211376c9c82 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Sat, 14 Jan 2006 13:20:50 -0800 Subject: [PATCH 266/465] [PATCH] powerpc: Add support for the MPC83xx watchdog Add support for the PowerPC MPC83xx watchdog. The MPC83xx has a simple watchdog that once enabled it can not be stopped, has some simple timeout range selection, and the ability to either reset the processor or take a machine check. Signed-off-by: Dave Updegraff Signed-off-by: Kumar Gala Cc: Wim Van Sebroeck Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/watchdog/Kconfig | 4 + drivers/char/watchdog/Makefile | 1 + drivers/char/watchdog/mpc83xx_wdt.c | 229 ++++++++++++++++++++++++++++ 3 files changed, 234 insertions(+) create mode 100644 drivers/char/watchdog/mpc83xx_wdt.c diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index f68aaa60fa8..c0dfcf273f0 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig @@ -423,6 +423,10 @@ config 8xx_WDT tristate "MPC8xx Watchdog Timer" depends on WATCHDOG && 8xx +config 83xx_WDT + tristate "MPC83xx Watchdog Timer" + depends on WATCHDOG && PPC_83xx + config MV64X60_WDT tristate "MV64X60 (Marvell Discovery) Watchdog Timer" depends on WATCHDOG && MV64X60 diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile index 4fa2ca8e943..36c0b282b8b 100644 --- a/drivers/char/watchdog/Makefile +++ b/drivers/char/watchdog/Makefile @@ -56,6 +56,7 @@ obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o # PowerPC Architecture obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o +obj-$(CONFIG_83xx_WDT) += mpc83xx_wdt.o obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o diff --git a/drivers/char/watchdog/mpc83xx_wdt.c b/drivers/char/watchdog/mpc83xx_wdt.c new file mode 100644 index 00000000000..5d6f5061603 --- /dev/null +++ b/drivers/char/watchdog/mpc83xx_wdt.c @@ -0,0 +1,229 @@ +/* + * mpc83xx_wdt.c - MPC83xx watchdog userspace interface + * + * Authors: Dave Updegraff + * Kumar Gala + * Attribution: from 83xx_wst: Florian Schirmer + * ..and from sc520_wdt + * + * Note: it appears that you can only actually ENABLE or DISABLE the thing + * once after POR. Once enabled, you cannot disable, and vice versa. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct mpc83xx_wdt { + __be32 res0; + __be32 swcrr; /* System watchdog control register */ +#define SWCRR_SWTC 0xFFFF0000 /* Software Watchdog Time Count. */ +#define SWCRR_SWEN 0x00000004 /* Watchdog Enable bit. */ +#define SWCRR_SWRI 0x00000002 /* Software Watchdog Reset/Interrupt Select bit.*/ +#define SWCRR_SWPR 0x00000001 /* Software Watchdog Counter Prescale bit. */ + __be32 swcnr; /* System watchdog count register */ + u8 res1[2]; + __be16 swsrr; /* System watchdog service register */ + u8 res2[0xF0]; +}; + +static struct mpc83xx_wdt __iomem *wd_base; + +static u16 timeout = 0xffff; +module_param(timeout, ushort, 0); +MODULE_PARM_DESC(timeout, "Watchdog timeout in ticks. (0swsrr, 0x556c); + out_be16(&wd_base->swsrr, 0xaa39); + spin_unlock(&wdt_spinlock); +} + +static ssize_t mpc83xx_wdt_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + if (count) + mpc83xx_wdt_keepalive(); + return count; +} + +static int mpc83xx_wdt_open(struct inode *inode, struct file *file) +{ + u32 tmp = SWCRR_SWEN; + if (test_and_set_bit(0, &wdt_is_open)) + return -EBUSY; + + /* Once we start the watchdog we can't stop it */ + __module_get(THIS_MODULE); + + /* Good, fire up the show */ + if (prescale) + tmp |= SWCRR_SWPR; + if (reset) + tmp |= SWCRR_SWRI; + + tmp |= timeout << 16; + + out_be32(&wd_base->swcrr, tmp); + + return nonseekable_open(inode, file); +} + +static int mpc83xx_wdt_release(struct inode *inode, struct file *file) +{ + printk(KERN_CRIT "Unexpected close, not stopping watchdog!\n"); + mpc83xx_wdt_keepalive(); + clear_bit(0, &wdt_is_open); + return 0; +} + +static int mpc83xx_wdt_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + void __user *argp = (void __user *)arg; + int __user *p = argp; + static struct watchdog_info ident = { + .options = WDIOF_KEEPALIVEPING, + .firmware_version = 1, + .identity = "MPC83xx", + }; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; + case WDIOC_KEEPALIVE: + mpc83xx_wdt_keepalive(); + return 0; + case WDIOC_GETTIMEOUT: + return put_user(timeout_sec, p); + default: + return -ENOIOCTLCMD; + } +} + +static struct file_operations mpc83xx_wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = mpc83xx_wdt_write, + .ioctl = mpc83xx_wdt_ioctl, + .open = mpc83xx_wdt_open, + .release = mpc83xx_wdt_release, +}; + +static struct miscdevice mpc83xx_wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &mpc83xx_wdt_fops, +}; + +static int __devinit mpc83xx_wdt_probe(struct platform_device *dev) +{ + struct resource *r; + int ret; + unsigned int *freq = dev->dev.platform_data; + + /* get a pointer to the register memory */ + r = platform_get_resource(dev, IORESOURCE_MEM, 0); + + if (!r) { + ret = -ENODEV; + goto err_out; + } + + wd_base = ioremap(r->start, sizeof (struct mpc83xx_wdt)); + + if (wd_base == NULL) { + ret = -ENOMEM; + goto err_out; + } + + ret = misc_register(&mpc83xx_wdt_miscdev); + if (ret) { + printk(KERN_ERR "cannot register miscdev on minor=%d " + "(err=%d)\n", + WATCHDOG_MINOR, ret); + goto err_unmap; + } + + /* Calculate the timeout in seconds */ + if (prescale) + timeout_sec = (timeout * 0x10000) / (*freq); + else + timeout_sec = timeout / (*freq); + + printk(KERN_INFO "WDT driver for MPC83xx initialized. " + "mode:%s timeout=%d (%d seconds)\n", + reset ? "reset":"interrupt", timeout, timeout_sec); + + spin_lock_init(&wdt_spinlock); + + return 0; + +err_unmap: + iounmap(wd_base); +err_out: + return ret; +} + +static int __devexit mpc83xx_wdt_remove(struct platform_device *dev) +{ + misc_deregister(&mpc83xx_wdt_miscdev); + iounmap(wd_base); + + return 0; +} + +static struct platform_driver mpc83xx_wdt_driver = { + .probe = mpc83xx_wdt_probe, + .remove = __devexit_p(mpc83xx_wdt_remove), + .driver = { + .name = "mpc83xx_wdt", + }, +}; + +static int __init mpc83xx_wdt_init(void) +{ + return platform_driver_register(&mpc83xx_wdt_driver); +} + +static void __exit mpc83xx_wdt_exit(void) +{ + platform_driver_unregister(&mpc83xx_wdt_driver); +} + +module_init(mpc83xx_wdt_init); +module_exit(mpc83xx_wdt_exit); + +MODULE_AUTHOR("Dave Updegraff, Kumar Gala"); +MODULE_DESCRIPTION("Driver for watchdog timer in MPC83xx uProcessor"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- GitLab From ce63ad78b55daf708d5d4ced9b832a4354ad2a4c Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 14 Jan 2006 13:20:51 -0800 Subject: [PATCH 267/465] [PATCH] i386: put HOTPLUG_CPU under Processor type, not Bus options Move the HOTPLUG_CPU option under "Processor type" instead of under "Bus options". This makes it the same for i386 as most other processor types (arm, ia64, parisc, ppc, s390, & x86_64; but not for powerpc). Besides, it takes me too long to find it under Bus options. I can't be the only person who has trouble finding it. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/Kconfig | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index d5d0df7f04f..cbde675bc95 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -702,6 +702,15 @@ config PHYSICAL_START Don't change this unless you know what you are doing. +config HOTPLUG_CPU + bool "Support for hot-pluggable CPUs (EXPERIMENTAL)" + depends on SMP && HOTPLUG && EXPERIMENTAL + ---help--- + Say Y here to experiment with turning CPUs off and on. CPUs + can be controlled through /sys/devices/system/cpu. + + Say N. + endmenu @@ -988,15 +997,6 @@ config SCx200 This support is also available as a module. If compiled as a module, it will be called scx200. -config HOTPLUG_CPU - bool "Support for hot-pluggable CPUs (EXPERIMENTAL)" - depends on SMP && HOTPLUG && EXPERIMENTAL - ---help--- - Say Y here to experiment with turning CPUs off and on. CPUs - can be controlled through /sys/devices/system/cpu. - - Say N. - source "drivers/pcmcia/Kconfig" source "drivers/pci/hotplug/Kconfig" -- GitLab From 7aa89746e89fca8fc722485aaf4454f2b636cf4d Mon Sep 17 00:00:00 2001 From: Chuck Ebbert <76306.1226@compuserve.com> Date: Sat, 14 Jan 2006 13:20:52 -0800 Subject: [PATCH 268/465] [PATCH] i386: fix stack dump loglevel Recent changes caused part of stack traces from SysRq-T to print at KERN_EMERG loglevel. Also, parts of stack dump during oops were failing to print at that level when they should. Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/traps.c | 57 +++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index b9f0030a2eb..0aaebf3e1cf 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -112,33 +112,38 @@ static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) p < (void *)tinfo + THREAD_SIZE - 3; } +static void print_addr_and_symbol(unsigned long addr, char *log_lvl) +{ + printk(log_lvl); + printk(" [<%08lx>] ", addr); + print_symbol("%s", addr); + printk("\n"); +} + static inline unsigned long print_context_stack(struct thread_info *tinfo, - unsigned long *stack, unsigned long ebp) + unsigned long *stack, unsigned long ebp, + char *log_lvl) { unsigned long addr; #ifdef CONFIG_FRAME_POINTER while (valid_stack_ptr(tinfo, (void *)ebp)) { addr = *(unsigned long *)(ebp + 4); - printk(KERN_EMERG " [<%08lx>] ", addr); - print_symbol("%s", addr); - printk("\n"); + print_addr_and_symbol(addr, log_lvl); ebp = *(unsigned long *)ebp; } #else while (valid_stack_ptr(tinfo, stack)) { addr = *stack++; - if (__kernel_text_address(addr)) { - printk(KERN_EMERG " [<%08lx>]", addr); - print_symbol(" %s", addr); - printk("\n"); - } + if (__kernel_text_address(addr)) + print_addr_and_symbol(addr, log_lvl); } #endif return ebp; } -void show_trace(struct task_struct *task, unsigned long * stack) +static void show_trace_log_lvl(struct task_struct *task, + unsigned long *stack, char *log_lvl) { unsigned long ebp; @@ -157,7 +162,7 @@ void show_trace(struct task_struct *task, unsigned long * stack) struct thread_info *context; context = (struct thread_info *) ((unsigned long)stack & (~(THREAD_SIZE - 1))); - ebp = print_context_stack(context, stack, ebp); + ebp = print_context_stack(context, stack, ebp, log_lvl); stack = (unsigned long*)context->previous_esp; if (!stack) break; @@ -165,7 +170,13 @@ void show_trace(struct task_struct *task, unsigned long * stack) } } -void show_stack(struct task_struct *task, unsigned long *esp) +void show_trace(struct task_struct *task, unsigned long * stack) +{ + show_trace_log_lvl(task, stack, ""); +} + +static void show_stack_log_lvl(struct task_struct *task, unsigned long *esp, + char *log_lvl) { unsigned long *stack; int i; @@ -178,16 +189,26 @@ void show_stack(struct task_struct *task, unsigned long *esp) } stack = esp; - printk(KERN_EMERG); + printk(log_lvl); for(i = 0; i < kstack_depth_to_print; i++) { if (kstack_end(stack)) break; - if (i && ((i % 8) == 0)) - printk("\n" KERN_EMERG " "); + if (i && ((i % 8) == 0)) { + printk("\n"); + printk(log_lvl); + printk(" "); + } printk("%08lx ", *stack++); } - printk("\n" KERN_EMERG "Call Trace:\n"); - show_trace(task, esp); + printk("\n"); + printk(log_lvl); + printk("Call Trace:\n"); + show_trace_log_lvl(task, esp, log_lvl); +} + +void show_stack(struct task_struct *task, unsigned long *esp) +{ + show_stack_log_lvl(task, esp, ""); } /* @@ -238,7 +259,7 @@ void show_registers(struct pt_regs *regs) u8 __user *eip; printk("\n" KERN_EMERG "Stack: "); - show_stack(NULL, (unsigned long*)esp); + show_stack_log_lvl(NULL, (unsigned long *)esp, KERN_EMERG); printk(KERN_EMERG "Code: "); -- GitLab From c1357833bf5d92b1bda41215ae88a6597664251b Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Sat, 14 Jan 2006 13:20:53 -0800 Subject: [PATCH 269/465] [PATCH] s390: des crypto code cleanup Beautify the s390 in-kernel-crypto des code. Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/crypto/des_s390.c | 155 ++++++++++++++++-------------------- 1 file changed, 67 insertions(+), 88 deletions(-) diff --git a/arch/s390/crypto/des_s390.c b/arch/s390/crypto/des_s390.c index a38bb2a3eef..f090c3c2745 100644 --- a/arch/s390/crypto/des_s390.c +++ b/arch/s390/crypto/des_s390.c @@ -15,10 +15,8 @@ */ #include #include -#include -#include -#include #include + #include "crypt_s390.h" #include "crypto_des.h" @@ -46,37 +44,30 @@ struct crypt_s390_des3_192_ctx { u8 key[DES3_192_KEY_SIZE]; }; -static int -des_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) +static int des_setkey(void *ctx, const u8 *key, unsigned int keylen, + u32 *flags) { - struct crypt_s390_des_ctx *dctx; + struct crypt_s390_des_ctx *dctx = ctx; int ret; - dctx = ctx; - //test if key is valid (not a weak key) + /* test if key is valid (not a weak key) */ ret = crypto_des_check_key(key, keylen, flags); - if (ret == 0){ + if (ret == 0) memcpy(dctx->key, key, keylen); - } return ret; } - -static void -des_encrypt(void *ctx, u8 *dst, const u8 *src) +static void des_encrypt(void *ctx, u8 *dst, const u8 *src) { - struct crypt_s390_des_ctx *dctx; + struct crypt_s390_des_ctx *dctx = ctx; - dctx = ctx; crypt_s390_km(KM_DEA_ENCRYPT, dctx->key, dst, src, DES_BLOCK_SIZE); } -static void -des_decrypt(void *ctx, u8 *dst, const u8 *src) +static void des_decrypt(void *ctx, u8 *dst, const u8 *src) { - struct crypt_s390_des_ctx *dctx; + struct crypt_s390_des_ctx *dctx = ctx; - dctx = ctx; crypt_s390_km(KM_DEA_DECRYPT, dctx->key, dst, src, DES_BLOCK_SIZE); } @@ -87,12 +78,15 @@ static struct crypto_alg des_alg = { .cra_ctxsize = sizeof(struct crypt_s390_des_ctx), .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(des_alg.cra_list), - .cra_u = { .cipher = { - .cia_min_keysize = DES_KEY_SIZE, - .cia_max_keysize = DES_KEY_SIZE, - .cia_setkey = des_setkey, - .cia_encrypt = des_encrypt, - .cia_decrypt = des_decrypt } } + .cra_u = { + .cipher = { + .cia_min_keysize = DES_KEY_SIZE, + .cia_max_keysize = DES_KEY_SIZE, + .cia_setkey = des_setkey, + .cia_encrypt = des_encrypt, + .cia_decrypt = des_decrypt + } + } }; /* @@ -107,20 +101,18 @@ static struct crypto_alg des_alg = { * Implementers MUST reject keys that exhibit this property. * */ -static int -des3_128_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) +static int des3_128_setkey(void *ctx, const u8 *key, unsigned int keylen, + u32 *flags) { int i, ret; - struct crypt_s390_des3_128_ctx *dctx; + struct crypt_s390_des3_128_ctx *dctx = ctx; const u8* temp_key = key; - dctx = ctx; if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE))) { - *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED; return -EINVAL; } - for (i = 0; i < 2; i++, temp_key += DES_KEY_SIZE) { + for (i = 0; i < 2; i++, temp_key += DES_KEY_SIZE) { ret = crypto_des_check_key(temp_key, DES_KEY_SIZE, flags); if (ret < 0) return ret; @@ -129,24 +121,20 @@ des3_128_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) return 0; } -static void -des3_128_encrypt(void *ctx, u8 *dst, const u8 *src) +static void des3_128_encrypt(void *ctx, u8 *dst, const u8 *src) { - struct crypt_s390_des3_128_ctx *dctx; + struct crypt_s390_des3_128_ctx *dctx = ctx; - dctx = ctx; crypt_s390_km(KM_TDEA_128_ENCRYPT, dctx->key, dst, (void*)src, - DES3_128_BLOCK_SIZE); + DES3_128_BLOCK_SIZE); } -static void -des3_128_decrypt(void *ctx, u8 *dst, const u8 *src) +static void des3_128_decrypt(void *ctx, u8 *dst, const u8 *src) { - struct crypt_s390_des3_128_ctx *dctx; + struct crypt_s390_des3_128_ctx *dctx = ctx; - dctx = ctx; crypt_s390_km(KM_TDEA_128_DECRYPT, dctx->key, dst, (void*)src, - DES3_128_BLOCK_SIZE); + DES3_128_BLOCK_SIZE); } static struct crypto_alg des3_128_alg = { @@ -156,12 +144,15 @@ static struct crypto_alg des3_128_alg = { .cra_ctxsize = sizeof(struct crypt_s390_des3_128_ctx), .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(des3_128_alg.cra_list), - .cra_u = { .cipher = { - .cia_min_keysize = DES3_128_KEY_SIZE, - .cia_max_keysize = DES3_128_KEY_SIZE, - .cia_setkey = des3_128_setkey, - .cia_encrypt = des3_128_encrypt, - .cia_decrypt = des3_128_decrypt } } + .cra_u = { + .cipher = { + .cia_min_keysize = DES3_128_KEY_SIZE, + .cia_max_keysize = DES3_128_KEY_SIZE, + .cia_setkey = des3_128_setkey, + .cia_encrypt = des3_128_encrypt, + .cia_decrypt = des3_128_decrypt + } + } }; /* @@ -177,50 +168,43 @@ static struct crypto_alg des3_128_alg = { * property. * */ -static int -des3_192_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) +static int des3_192_setkey(void *ctx, const u8 *key, unsigned int keylen, + u32 *flags) { int i, ret; - struct crypt_s390_des3_192_ctx *dctx; - const u8* temp_key; + struct crypt_s390_des3_192_ctx *dctx = ctx; + const u8* temp_key = key; - dctx = ctx; - temp_key = key; if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) && memcmp(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2], - DES_KEY_SIZE))) { + DES_KEY_SIZE))) { *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED; return -EINVAL; } for (i = 0; i < 3; i++, temp_key += DES_KEY_SIZE) { ret = crypto_des_check_key(temp_key, DES_KEY_SIZE, flags); - if (ret < 0){ + if (ret < 0) return ret; - } } memcpy(dctx->key, key, keylen); return 0; } -static void -des3_192_encrypt(void *ctx, u8 *dst, const u8 *src) +static void des3_192_encrypt(void *ctx, u8 *dst, const u8 *src) { - struct crypt_s390_des3_192_ctx *dctx; + struct crypt_s390_des3_192_ctx *dctx = ctx; - dctx = ctx; crypt_s390_km(KM_TDEA_192_ENCRYPT, dctx->key, dst, (void*)src, - DES3_192_BLOCK_SIZE); + DES3_192_BLOCK_SIZE); } -static void -des3_192_decrypt(void *ctx, u8 *dst, const u8 *src) +static void des3_192_decrypt(void *ctx, u8 *dst, const u8 *src) { - struct crypt_s390_des3_192_ctx *dctx; + struct crypt_s390_des3_192_ctx *dctx = ctx; - dctx = ctx; crypt_s390_km(KM_TDEA_192_DECRYPT, dctx->key, dst, (void*)src, - DES3_192_BLOCK_SIZE); + DES3_192_BLOCK_SIZE); } static struct crypto_alg des3_192_alg = { @@ -230,44 +214,39 @@ static struct crypto_alg des3_192_alg = { .cra_ctxsize = sizeof(struct crypt_s390_des3_192_ctx), .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(des3_192_alg.cra_list), - .cra_u = { .cipher = { - .cia_min_keysize = DES3_192_KEY_SIZE, - .cia_max_keysize = DES3_192_KEY_SIZE, - .cia_setkey = des3_192_setkey, - .cia_encrypt = des3_192_encrypt, - .cia_decrypt = des3_192_decrypt } } + .cra_u = { + .cipher = { + .cia_min_keysize = DES3_192_KEY_SIZE, + .cia_max_keysize = DES3_192_KEY_SIZE, + .cia_setkey = des3_192_setkey, + .cia_encrypt = des3_192_encrypt, + .cia_decrypt = des3_192_decrypt + } + } }; - - -static int -init(void) +static int init(void) { - int ret; + int ret = 0; if (!crypt_s390_func_available(KM_DEA_ENCRYPT) || !crypt_s390_func_available(KM_TDEA_128_ENCRYPT) || - !crypt_s390_func_available(KM_TDEA_192_ENCRYPT)){ + !crypt_s390_func_available(KM_TDEA_192_ENCRYPT)) return -ENOSYS; - } - ret = 0; - ret |= (crypto_register_alg(&des_alg) == 0)? 0:1; - ret |= (crypto_register_alg(&des3_128_alg) == 0)? 0:2; - ret |= (crypto_register_alg(&des3_192_alg) == 0)? 0:4; - if (ret){ + ret |= (crypto_register_alg(&des_alg) == 0) ? 0:1; + ret |= (crypto_register_alg(&des3_128_alg) == 0) ? 0:2; + ret |= (crypto_register_alg(&des3_192_alg) == 0) ? 0:4; + if (ret) { crypto_unregister_alg(&des3_192_alg); crypto_unregister_alg(&des3_128_alg); crypto_unregister_alg(&des_alg); return -EEXIST; } - - printk(KERN_INFO "crypt_s390: des_s390 loaded.\n"); return 0; } -static void __exit -fini(void) +static void __exit fini(void) { crypto_unregister_alg(&des3_192_alg); crypto_unregister_alg(&des3_128_alg); -- GitLab From b8dc6038ff894d0eb0b5d61c9fafdf323ec10251 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Sat, 14 Jan 2006 13:20:53 -0800 Subject: [PATCH 270/465] [PATCH] s390: des crypto code speedup Provide ECB and CBC encrypt / decrypt functions to crypto API to speed up our hardware accelerated DES implementation. This new functions allow the crypto API to call ECB / CBC directly with large blocks in difference to the old functions that were calles with algorithm block size (8 bytes for DES). This is up to factor 10 faster than our old hardware implementation :) Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/crypto/des_s390.c | 217 ++++++++++++++++++++++++++++++++++-- 1 file changed, 210 insertions(+), 7 deletions(-) diff --git a/arch/s390/crypto/des_s390.c b/arch/s390/crypto/des_s390.c index f090c3c2745..e3c37aa0a19 100644 --- a/arch/s390/crypto/des_s390.c +++ b/arch/s390/crypto/des_s390.c @@ -57,18 +57,79 @@ static int des_setkey(void *ctx, const u8 *key, unsigned int keylen, return ret; } -static void des_encrypt(void *ctx, u8 *dst, const u8 *src) +static void des_encrypt(void *ctx, u8 *out, const u8 *in) { struct crypt_s390_des_ctx *dctx = ctx; - crypt_s390_km(KM_DEA_ENCRYPT, dctx->key, dst, src, DES_BLOCK_SIZE); + crypt_s390_km(KM_DEA_ENCRYPT, dctx->key, out, in, DES_BLOCK_SIZE); } -static void des_decrypt(void *ctx, u8 *dst, const u8 *src) +static void des_decrypt(void *ctx, u8 *out, const u8 *in) { struct crypt_s390_des_ctx *dctx = ctx; - crypt_s390_km(KM_DEA_DECRYPT, dctx->key, dst, src, DES_BLOCK_SIZE); + crypt_s390_km(KM_DEA_DECRYPT, dctx->key, out, in, DES_BLOCK_SIZE); +} + +static unsigned int des_encrypt_ecb(const struct cipher_desc *desc, u8 *out, + const u8 *in, unsigned int nbytes) +{ + struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; + + /* only use complete blocks */ + nbytes &= ~(DES_BLOCK_SIZE - 1); + ret = crypt_s390_km(KM_DEA_ENCRYPT, sctx->key, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); + + return nbytes; +} + +static unsigned int des_decrypt_ecb(const struct cipher_desc *desc, u8 *out, + const u8 *in, unsigned int nbytes) +{ + struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; + + /* only use complete blocks */ + nbytes &= ~(DES_BLOCK_SIZE - 1); + ret = crypt_s390_km(KM_DEA_DECRYPT, sctx->key, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); + + return nbytes; +} + +static unsigned int des_encrypt_cbc(const struct cipher_desc *desc, u8 *out, + const u8 *in, unsigned int nbytes) +{ + struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; + + /* only use complete blocks */ + nbytes &= ~(DES_BLOCK_SIZE - 1); + + memcpy(sctx->iv, desc->info, DES_BLOCK_SIZE); + ret = crypt_s390_kmc(KMC_DEA_ENCRYPT, &sctx->iv, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); + + memcpy(desc->info, sctx->iv, DES_BLOCK_SIZE); + return nbytes; +} + +static unsigned int des_decrypt_cbc(const struct cipher_desc *desc, u8 *out, + const u8 *in, unsigned int nbytes) +{ + struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; + + /* only use complete blocks */ + nbytes &= ~(DES_BLOCK_SIZE - 1); + + memcpy(&sctx->iv, desc->info, DES_BLOCK_SIZE); + ret = crypt_s390_kmc(KMC_DEA_DECRYPT, &sctx->iv, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); + + return nbytes; } static struct crypto_alg des_alg = { @@ -84,7 +145,11 @@ static struct crypto_alg des_alg = { .cia_max_keysize = DES_KEY_SIZE, .cia_setkey = des_setkey, .cia_encrypt = des_encrypt, - .cia_decrypt = des_decrypt + .cia_decrypt = des_decrypt, + .cia_encrypt_ecb = des_encrypt_ecb, + .cia_decrypt_ecb = des_decrypt_ecb, + .cia_encrypt_cbc = des_encrypt_cbc, + .cia_decrypt_cbc = des_decrypt_cbc, } } }; @@ -137,6 +202,71 @@ static void des3_128_decrypt(void *ctx, u8 *dst, const u8 *src) DES3_128_BLOCK_SIZE); } +static unsigned int des3_128_encrypt_ecb(const struct cipher_desc *desc, + u8 *out, const u8 *in, + unsigned int nbytes) +{ + struct crypt_s390_des3_128_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; + + /* only use complete blocks */ + nbytes &= ~(DES3_128_BLOCK_SIZE - 1); + ret = crypt_s390_km(KM_TDEA_128_ENCRYPT, sctx->key, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); + + return nbytes; +} + +static unsigned int des3_128_decrypt_ecb(const struct cipher_desc *desc, + u8 *out, const u8 *in, + unsigned int nbytes) +{ + struct crypt_s390_des3_128_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; + + /* only use complete blocks */ + nbytes &= ~(DES3_128_BLOCK_SIZE - 1); + ret = crypt_s390_km(KM_TDEA_128_DECRYPT, sctx->key, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); + + return nbytes; +} + +static unsigned int des3_128_encrypt_cbc(const struct cipher_desc *desc, + u8 *out, const u8 *in, + unsigned int nbytes) +{ + struct crypt_s390_des3_128_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; + + /* only use complete blocks */ + nbytes &= ~(DES3_128_BLOCK_SIZE - 1); + + memcpy(sctx->iv, desc->info, DES3_128_BLOCK_SIZE); + ret = crypt_s390_kmc(KMC_TDEA_128_ENCRYPT, &sctx->iv, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); + + memcpy(desc->info, sctx->iv, DES3_128_BLOCK_SIZE); + return nbytes; +} + +static unsigned int des3_128_decrypt_cbc(const struct cipher_desc *desc, + u8 *out, const u8 *in, + unsigned int nbytes) +{ + struct crypt_s390_des3_128_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; + + /* only use complete blocks */ + nbytes &= ~(DES3_128_BLOCK_SIZE - 1); + + memcpy(&sctx->iv, desc->info, DES3_128_BLOCK_SIZE); + ret = crypt_s390_kmc(KMC_TDEA_128_DECRYPT, &sctx->iv, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); + + return nbytes; +} + static struct crypto_alg des3_128_alg = { .cra_name = "des3_ede128", .cra_flags = CRYPTO_ALG_TYPE_CIPHER, @@ -150,7 +280,11 @@ static struct crypto_alg des3_128_alg = { .cia_max_keysize = DES3_128_KEY_SIZE, .cia_setkey = des3_128_setkey, .cia_encrypt = des3_128_encrypt, - .cia_decrypt = des3_128_decrypt + .cia_decrypt = des3_128_decrypt, + .cia_encrypt_ecb = des3_128_encrypt_ecb, + .cia_decrypt_ecb = des3_128_decrypt_ecb, + .cia_encrypt_cbc = des3_128_encrypt_cbc, + .cia_decrypt_cbc = des3_128_decrypt_cbc, } } }; @@ -207,6 +341,71 @@ static void des3_192_decrypt(void *ctx, u8 *dst, const u8 *src) DES3_192_BLOCK_SIZE); } +static unsigned int des3_192_encrypt_ecb(const struct cipher_desc *desc, + u8 *out, const u8 *in, + unsigned int nbytes) +{ + struct crypt_s390_des3_192_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; + + /* only use complete blocks */ + nbytes &= ~(DES3_192_BLOCK_SIZE - 1); + ret = crypt_s390_km(KM_TDEA_192_ENCRYPT, sctx->key, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); + + return nbytes; +} + +static unsigned int des3_192_decrypt_ecb(const struct cipher_desc *desc, + u8 *out, const u8 *in, + unsigned int nbytes) +{ + struct crypt_s390_des3_192_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; + + /* only use complete blocks */ + nbytes &= ~(DES3_192_BLOCK_SIZE - 1); + ret = crypt_s390_km(KM_TDEA_192_DECRYPT, sctx->key, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); + + return nbytes; +} + +static unsigned int des3_192_encrypt_cbc(const struct cipher_desc *desc, + u8 *out, const u8 *in, + unsigned int nbytes) +{ + struct crypt_s390_des3_192_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; + + /* only use complete blocks */ + nbytes &= ~(DES3_192_BLOCK_SIZE - 1); + + memcpy(sctx->iv, desc->info, DES3_192_BLOCK_SIZE); + ret = crypt_s390_kmc(KMC_TDEA_192_ENCRYPT, &sctx->iv, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); + + memcpy(desc->info, sctx->iv, DES3_192_BLOCK_SIZE); + return nbytes; +} + +static unsigned int des3_192_decrypt_cbc(const struct cipher_desc *desc, + u8 *out, const u8 *in, + unsigned int nbytes) +{ + struct crypt_s390_des3_192_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; + + /* only use complete blocks */ + nbytes &= ~(DES3_192_BLOCK_SIZE - 1); + + memcpy(&sctx->iv, desc->info, DES3_192_BLOCK_SIZE); + ret = crypt_s390_kmc(KMC_TDEA_192_DECRYPT, &sctx->iv, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); + + return nbytes; +} + static struct crypto_alg des3_192_alg = { .cra_name = "des3_ede", .cra_flags = CRYPTO_ALG_TYPE_CIPHER, @@ -220,7 +419,11 @@ static struct crypto_alg des3_192_alg = { .cia_max_keysize = DES3_192_KEY_SIZE, .cia_setkey = des3_192_setkey, .cia_encrypt = des3_192_encrypt, - .cia_decrypt = des3_192_decrypt + .cia_decrypt = des3_192_decrypt, + .cia_encrypt_ecb = des3_192_encrypt_ecb, + .cia_decrypt_ecb = des3_192_decrypt_ecb, + .cia_encrypt_cbc = des3_192_encrypt_cbc, + .cia_decrypt_cbc = des3_192_decrypt_cbc, } } }; -- GitLab From fda5e142598341d30006e3715e53b2c983a9fca7 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Sat, 14 Jan 2006 13:20:55 -0800 Subject: [PATCH 271/465] [PATCH] s390: aes crypto code fixes Call KM[C] only with a multiple of block size. Check return value of KM[C] instructions and complain about erros Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/crypto/aes_s390.c | 60 +++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 16 deletions(-) diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c index 7a1033d8e00..c5ca2dc5d42 100644 --- a/arch/s390/crypto/aes_s390.c +++ b/arch/s390/crypto/aes_s390.c @@ -114,80 +114,108 @@ static unsigned int aes_encrypt_ecb(const struct cipher_desc *desc, u8 *out, const u8 *in, unsigned int nbytes) { struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; + + /* only use complete blocks */ + nbytes &= ~(AES_BLOCK_SIZE - 1); switch (sctx->key_len) { case 16: - crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in, nbytes); + ret = crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); break; case 24: - crypt_s390_km(KM_AES_192_ENCRYPT, &sctx->key, out, in, nbytes); + ret = crypt_s390_km(KM_AES_192_ENCRYPT, &sctx->key, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); break; case 32: - crypt_s390_km(KM_AES_256_ENCRYPT, &sctx->key, out, in, nbytes); + ret = crypt_s390_km(KM_AES_256_ENCRYPT, &sctx->key, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); break; } - return nbytes & ~(AES_BLOCK_SIZE - 1); + return nbytes; } static unsigned int aes_decrypt_ecb(const struct cipher_desc *desc, u8 *out, const u8 *in, unsigned int nbytes) { struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; + + /* only use complete blocks */ + nbytes &= ~(AES_BLOCK_SIZE - 1); switch (sctx->key_len) { case 16: - crypt_s390_km(KM_AES_128_DECRYPT, &sctx->key, out, in, nbytes); + ret = crypt_s390_km(KM_AES_128_DECRYPT, &sctx->key, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); break; case 24: - crypt_s390_km(KM_AES_192_DECRYPT, &sctx->key, out, in, nbytes); + ret = crypt_s390_km(KM_AES_192_DECRYPT, &sctx->key, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); break; case 32: - crypt_s390_km(KM_AES_256_DECRYPT, &sctx->key, out, in, nbytes); + ret = crypt_s390_km(KM_AES_256_DECRYPT, &sctx->key, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); break; } - return nbytes & ~(AES_BLOCK_SIZE - 1); + return nbytes; } static unsigned int aes_encrypt_cbc(const struct cipher_desc *desc, u8 *out, const u8 *in, unsigned int nbytes) { struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; + + /* only use complete blocks */ + nbytes &= ~(AES_BLOCK_SIZE - 1); memcpy(&sctx->iv, desc->info, AES_BLOCK_SIZE); switch (sctx->key_len) { case 16: - crypt_s390_kmc(KMC_AES_128_ENCRYPT, &sctx->iv, out, in, nbytes); + ret = crypt_s390_kmc(KMC_AES_128_ENCRYPT, &sctx->iv, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); break; case 24: - crypt_s390_kmc(KMC_AES_192_ENCRYPT, &sctx->iv, out, in, nbytes); + ret = crypt_s390_kmc(KMC_AES_192_ENCRYPT, &sctx->iv, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); break; case 32: - crypt_s390_kmc(KMC_AES_256_ENCRYPT, &sctx->iv, out, in, nbytes); + ret = crypt_s390_kmc(KMC_AES_256_ENCRYPT, &sctx->iv, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); break; } memcpy(desc->info, &sctx->iv, AES_BLOCK_SIZE); - return nbytes & ~(AES_BLOCK_SIZE - 1); + return nbytes; } static unsigned int aes_decrypt_cbc(const struct cipher_desc *desc, u8 *out, const u8 *in, unsigned int nbytes) { struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; + + /* only use complete blocks */ + nbytes &= ~(AES_BLOCK_SIZE - 1); memcpy(&sctx->iv, desc->info, AES_BLOCK_SIZE); switch (sctx->key_len) { case 16: - crypt_s390_kmc(KMC_AES_128_DECRYPT, &sctx->iv, out, in, nbytes); + ret = crypt_s390_kmc(KMC_AES_128_DECRYPT, &sctx->iv, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); break; case 24: - crypt_s390_kmc(KMC_AES_192_DECRYPT, &sctx->iv, out, in, nbytes); + ret = crypt_s390_kmc(KMC_AES_192_DECRYPT, &sctx->iv, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); break; case 32: - crypt_s390_kmc(KMC_AES_256_DECRYPT, &sctx->iv, out, in, nbytes); + ret = crypt_s390_kmc(KMC_AES_256_DECRYPT, &sctx->iv, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); break; } - return nbytes & ~(AES_BLOCK_SIZE - 1); + return nbytes; } -- GitLab From 7ffbc9da137ef475afd5e01f72e1ce1ce49668b1 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Sat, 14 Jan 2006 13:20:56 -0800 Subject: [PATCH 272/465] [PATCH] s390: sha256 crypto code fix Fix processing of messages larger than 2 * SHA256_BLOCK_SIZE. Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/crypto/sha256_s390.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/arch/s390/crypto/sha256_s390.c b/arch/s390/crypto/sha256_s390.c index b75bdbd476c..1ec5e92b345 100644 --- a/arch/s390/crypto/sha256_s390.c +++ b/arch/s390/crypto/sha256_s390.c @@ -51,6 +51,7 @@ static void sha256_update(void *ctx, const u8 *data, unsigned int len) { struct s390_sha256_ctx *sctx = ctx; unsigned int index; + int ret; /* how much is already in the buffer? */ index = sctx->count / 8 & 0x3f; @@ -58,15 +59,29 @@ static void sha256_update(void *ctx, const u8 *data, unsigned int len) /* update message bit length */ sctx->count += len * 8; - /* process one block */ - if ((index + len) >= SHA256_BLOCK_SIZE) { + if ((index + len) < SHA256_BLOCK_SIZE) + goto store; + + /* process one stored block */ + if (index) { memcpy(sctx->buf + index, data, SHA256_BLOCK_SIZE - index); - crypt_s390_kimd(KIMD_SHA_256, sctx->state, sctx->buf, - SHA256_BLOCK_SIZE); + ret = crypt_s390_kimd(KIMD_SHA_256, sctx->state, sctx->buf, + SHA256_BLOCK_SIZE); + BUG_ON(ret != SHA256_BLOCK_SIZE); data += SHA256_BLOCK_SIZE - index; len -= SHA256_BLOCK_SIZE - index; } + /* process as many blocks as possible */ + if (len >= SHA256_BLOCK_SIZE) { + ret = crypt_s390_kimd(KIMD_SHA_256, sctx->state, data, + len & ~(SHA256_BLOCK_SIZE - 1)); + BUG_ON(ret != (len & ~(SHA256_BLOCK_SIZE - 1))); + data += ret; + len -= ret; + } + +store: /* anything left? */ if (len) memcpy(sctx->buf + index , data, len); @@ -119,9 +134,9 @@ static struct crypto_alg alg = { .cra_list = LIST_HEAD_INIT(alg.cra_list), .cra_u = { .digest = { .dia_digestsize = SHA256_DIGEST_SIZE, - .dia_init = sha256_init, - .dia_update = sha256_update, - .dia_final = sha256_final } } + .dia_init = sha256_init, + .dia_update = sha256_update, + .dia_final = sha256_final } } }; static int init(void) -- GitLab From eb33c190c2b633f0dfc98481ecf12f62a02c705e Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Sat, 14 Jan 2006 13:20:57 -0800 Subject: [PATCH 273/465] [PATCH] s390: show_task oops The show_task function walks the kernel stack backchain of processes assuming that the processes are not running. Since this assumption is not correct walking the backchain can lead to an addressing exception and therefore to a kernel hang. So prevent the kernel hang (you still get incorrect results) verity that all read accesses are within the bounds of the kernel stack before performing them. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/kernel/process.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 2ff90a1a105..008c74526fd 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -58,10 +58,18 @@ asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); */ unsigned long thread_saved_pc(struct task_struct *tsk) { - struct stack_frame *sf; + struct stack_frame *sf, *low, *high; - sf = (struct stack_frame *) tsk->thread.ksp; - sf = (struct stack_frame *) sf->back_chain; + if (!tsk || !task_stack_page(tsk)) + return 0; + low = task_stack_page(tsk); + high = (struct stack_frame *) task_pt_regs(tsk); + sf = (struct stack_frame *) (tsk->thread.ksp & PSW_ADDR_INSN); + if (sf <= low || sf > high) + return 0; + sf = (struct stack_frame *) (sf->back_chain & PSW_ADDR_INSN); + if (sf <= low || sf > high) + return 0; return sf->gprs[8]; } -- GitLab From 6410dd5e07b63606605794eeb7ec29e61fbda3db Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Sat, 14 Jan 2006 13:20:58 -0800 Subject: [PATCH 274/465] [PATCH] s390: sigcontext.h vs __user Add an include of linux/compiler.h in sigcontext.h to avoid compiler errors in user space apps because of a missing definition for __user. Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-s390/sigcontext.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/asm-s390/sigcontext.h b/include/asm-s390/sigcontext.h index 803545351dd..aeb6e0b1332 100644 --- a/include/asm-s390/sigcontext.h +++ b/include/asm-s390/sigcontext.h @@ -8,6 +8,8 @@ #ifndef _ASM_S390_SIGCONTEXT_H #define _ASM_S390_SIGCONTEXT_H +#include + #define __NUM_GPRS 16 #define __NUM_FPRS 16 #define __NUM_ACRS 16 -- GitLab From 68c119177890afff4759abda8da2b4ff5e06efa1 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sat, 14 Jan 2006 13:20:58 -0800 Subject: [PATCH 275/465] [PATCH] s390: fix cpcmd calls on UP Add missing fourth argument to cpcmd calls under !CONFIG_SMP. Signed-off-by: Alexey Dobriyan Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/kernel/setup.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index b03847d100d..c08325187a4 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -268,7 +268,7 @@ static void do_machine_restart_nonsmp(char * __unused) reipl_diag(); if (MACHINE_IS_VM) - cpcmd ("IPL", NULL, 0); + cpcmd ("IPL", NULL, 0, NULL); else reipl (0x10000 | S390_lowcore.ipl_device); } @@ -276,14 +276,14 @@ static void do_machine_restart_nonsmp(char * __unused) static void do_machine_halt_nonsmp(void) { if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0) - cpcmd(vmhalt_cmd, NULL, 0); + cpcmd(vmhalt_cmd, NULL, 0, NULL); signal_processor(smp_processor_id(), sigp_stop_and_store_status); } static void do_machine_power_off_nonsmp(void) { if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0) - cpcmd(vmpoff_cmd, NULL, 0); + cpcmd(vmpoff_cmd, NULL, 0, NULL); signal_processor(smp_processor_id(), sigp_stop_and_store_status); } -- GitLab From 0152fb37603e3a776768794030b809ae77027aa4 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Sat, 14 Jan 2006 13:21:00 -0800 Subject: [PATCH 276/465] [PATCH] s390: spinlock fixes Remove useless spin_retry_counter and fix compilation for UP kernels. Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/lib/Makefile | 3 ++- arch/s390/lib/spinlock.c | 7 ------- kernel/sysctl.c | 2 +- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile index d9b97b3c597..f20b51ff1d8 100644 --- a/arch/s390/lib/Makefile +++ b/arch/s390/lib/Makefile @@ -4,5 +4,6 @@ EXTRA_AFLAGS := -traditional -lib-y += delay.o string.o spinlock.o +lib-y += delay.o string.o lib-y += $(if $(CONFIG_64BIT),uaccess64.o,uaccess.o) +lib-$(CONFIG_SMP) += spinlock.o \ No newline at end of file diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c index 68d79c50208..60f80a4eed4 100644 --- a/arch/s390/lib/spinlock.c +++ b/arch/s390/lib/spinlock.c @@ -13,7 +13,6 @@ #include #include -atomic_t spin_retry_counter; int spin_retry = 1000; /** @@ -45,7 +44,6 @@ _raw_spin_lock_wait(raw_spinlock_t *lp, unsigned int pc) _diag44(); count = spin_retry; } - atomic_inc(&spin_retry_counter); if (_raw_compare_and_swap(&lp->lock, 0, pc) == 0) return; } @@ -58,7 +56,6 @@ _raw_spin_trylock_retry(raw_spinlock_t *lp, unsigned int pc) int count = spin_retry; while (count-- > 0) { - atomic_inc(&spin_retry_counter); if (_raw_compare_and_swap(&lp->lock, 0, pc) == 0) return 1; } @@ -77,7 +74,6 @@ _raw_read_lock_wait(raw_rwlock_t *rw) _diag44(); count = spin_retry; } - atomic_inc(&spin_retry_counter); old = rw->lock & 0x7fffffffU; if (_raw_compare_and_swap(&rw->lock, old, old + 1) == old) return; @@ -92,7 +88,6 @@ _raw_read_trylock_retry(raw_rwlock_t *rw) int count = spin_retry; while (count-- > 0) { - atomic_inc(&spin_retry_counter); old = rw->lock & 0x7fffffffU; if (_raw_compare_and_swap(&rw->lock, old, old + 1) == old) return 1; @@ -111,7 +106,6 @@ _raw_write_lock_wait(raw_rwlock_t *rw) _diag44(); count = spin_retry; } - atomic_inc(&spin_retry_counter); if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0) return; } @@ -124,7 +118,6 @@ _raw_write_trylock_retry(raw_rwlock_t *rw) int count = spin_retry; while (count-- > 0) { - atomic_inc(&spin_retry_counter); if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0) return 1; } diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 62d4d956687..f5d69b6e29f 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -648,7 +648,7 @@ static ctl_table kern_table[] = { .mode = 0644, .proc_handler = &proc_dointvec, }, -#if defined(CONFIG_S390) +#if defined(CONFIG_S390) && defined(CONFIG_SMP) { .ctl_name = KERN_SPIN_RETRY, .procname = "spin_retry", -- GitLab From 53df751ccd0a404cca169dbd61bae571cc21559a Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Sat, 14 Jan 2006 13:21:01 -0800 Subject: [PATCH 277/465] [PATCH] s390: add dummy pm_power_off Define a dummy pm_power_off pointer to make sys_reboot happy. Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/kernel/setup.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index c08325187a4..de878426747 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -315,6 +315,11 @@ void machine_power_off(void) _machine_power_off(); } +/* + * Dummy power off function. + */ +void (*pm_power_off)(void) = machine_power_off; + static void __init add_memory_hole(unsigned long start, unsigned long end) { -- GitLab From bcc132651d384ad115a275868effb49c64b348ce Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Sat, 14 Jan 2006 13:21:02 -0800 Subject: [PATCH 278/465] [PATCH] s390: fix blk_queue_ordered call in dasdc Add the missing third argument to the blk_queue_ordered call and use the constant QUEUE_ORDERED_DRAIN instead of "1". Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/block/dasd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 9c25654b1e7..b147beb9e1c 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -1635,7 +1635,7 @@ dasd_setup_queue(struct dasd_device * device) blk_queue_max_hw_segments(device->request_queue, -1L); blk_queue_max_segment_size(device->request_queue, -1L); blk_queue_segment_boundary(device->request_queue, -1L); - blk_queue_ordered(device->request_queue, 1); + blk_queue_ordered(device->request_queue, QUEUE_ORDERED_DRAIN, NULL); } /* -- GitLab From 1f1c12afe5c3e0ef901eec12dee09df4947462ee Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Sat, 14 Jan 2006 13:21:03 -0800 Subject: [PATCH 279/465] [PATCH] s390: cputime misaccounting finish_arch_switch needs to update the user cpu time as well, not just the system cpu time. Otherwise the partial user cpu time of a process that is stored in the lowcore will be (mis-)accounted to the next process. Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/kernel/time.c | 2 +- arch/s390/kernel/vtime.c | 27 ++++++++++++++++++++++++++- include/asm-s390/system.h | 5 +++-- include/linux/hardirq.h | 4 ---- 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index b0d8ca8e5ee..7c0fe152a11 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -214,7 +214,7 @@ void account_ticks(struct pt_regs *regs) #endif #ifdef CONFIG_VIRT_CPU_ACCOUNTING - account_user_vtime(current); + account_tick_vtime(current); #else while (ticks--) update_process_times(user_mode(regs)); diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index 22a895ecb7a..dfe6f085661 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c @@ -32,7 +32,7 @@ DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer); * Update process times based on virtual cpu times stored by entry.S * to the lowcore fields user_timer, system_timer & steal_clock. */ -void account_user_vtime(struct task_struct *tsk) +void account_tick_vtime(struct task_struct *tsk) { cputime_t cputime; __u64 timer, clock; @@ -72,6 +72,31 @@ void account_user_vtime(struct task_struct *tsk) run_posix_cpu_timers(tsk); } +/* + * Update process times based on virtual cpu times stored by entry.S + * to the lowcore fields user_timer, system_timer & steal_clock. + */ +void account_vtime(struct task_struct *tsk) +{ + cputime_t cputime; + __u64 timer; + + timer = S390_lowcore.last_update_timer; + asm volatile (" STPT %0" /* Store current cpu timer value */ + : "=m" (S390_lowcore.last_update_timer) ); + S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer; + + cputime = S390_lowcore.user_timer >> 12; + S390_lowcore.user_timer -= cputime << 12; + S390_lowcore.steal_clock -= cputime << 12; + account_user_time(tsk, cputime); + + cputime = S390_lowcore.system_timer >> 12; + S390_lowcore.system_timer -= cputime << 12; + S390_lowcore.steal_clock -= cputime << 12; + account_system_time(tsk, 0, cputime); +} + /* * Update process times based on virtual cpu times stored by entry.S * to the lowcore fields user_timer, system_timer & steal_clock. diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h index c7c3a9ad593..b2e65e8bf81 100644 --- a/include/asm-s390/system.h +++ b/include/asm-s390/system.h @@ -115,13 +115,14 @@ static inline void sched_cacheflush(void) } #ifdef CONFIG_VIRT_CPU_ACCOUNTING -extern void account_user_vtime(struct task_struct *); +extern void account_vtime(struct task_struct *); +extern void account_tick_vtime(struct task_struct *); extern void account_system_vtime(struct task_struct *); #endif #define finish_arch_switch(prev) do { \ set_fs(current->thread.mm_segment); \ - account_system_vtime(prev); \ + account_vtime(prev); \ } while (0) #define nop() __asm__ __volatile__ ("nop") diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h index 71d2b8a723b..eab537091f2 100644 --- a/include/linux/hardirq.h +++ b/include/linux/hardirq.h @@ -93,10 +93,6 @@ extern void synchronize_irq(unsigned int irq); struct task_struct; #ifndef CONFIG_VIRT_CPU_ACCOUNTING -static inline void account_user_vtime(struct task_struct *tsk) -{ -} - static inline void account_system_vtime(struct task_struct *tsk) { } -- GitLab From 871931c1eef1727d42ff3ecf993b1978cf1e209f Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Sat, 14 Jan 2006 13:21:03 -0800 Subject: [PATCH 280/465] [PATCH] s390: chps[] array too short The chps[] array in struct channel_subsystem is one too short; therefore the code doesn't realize the chpid ff is already known. When several devices on chpid ff become available, the message "new_channel_path: could not register ff" is displayed for every device but the first one. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/cio/css.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h index aa5ab5d4547..b6375861cb3 100644 --- a/drivers/s390/cio/css.h +++ b/drivers/s390/cio/css.h @@ -147,7 +147,7 @@ extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *); struct channel_subsystem { u8 cssid; int valid; - struct channel_path *chps[__MAX_CHPID]; + struct channel_path *chps[__MAX_CHPID + 1]; struct device device; struct pgid global_pgid; }; -- GitLab From 4ce3b30cf32c5c078518f0f3e6623bcb6eee9872 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Sat, 14 Jan 2006 13:21:04 -0800 Subject: [PATCH 281/465] [PATCH] s390: email-address change Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/cio/airq.c | 4 ++-- drivers/s390/cio/blacklist.c | 4 ++-- drivers/s390/cio/ccwgroup.c | 4 ++-- drivers/s390/cio/chsc.c | 4 ++-- drivers/s390/cio/cio.c | 4 ++-- drivers/s390/cio/css.c | 4 ++-- drivers/s390/cio/device.c | 4 ++-- drivers/s390/cio/device_fsm.c | 2 +- drivers/s390/cio/device_id.c | 2 +- drivers/s390/cio/device_ops.c | 4 ++-- drivers/s390/cio/device_pgid.c | 2 +- drivers/s390/cio/device_status.c | 2 +- drivers/s390/cio/qdio.c | 4 ++-- drivers/s390/net/ctcmain.c | 8 ++++---- drivers/s390/net/cu3088.c | 4 ++-- drivers/s390/net/netiucv.c | 9 +++++---- drivers/s390/s390_rdev.c | 4 ++-- include/asm-s390/s390_rdev.h | 2 +- 18 files changed, 36 insertions(+), 35 deletions(-) diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c index 83e6a060668..cd2cc28e16a 100644 --- a/drivers/s390/cio/airq.c +++ b/drivers/s390/cio/airq.c @@ -2,12 +2,12 @@ * drivers/s390/cio/airq.c * S/390 common I/O routines -- support for adapter interruptions * - * $Revision: 1.12 $ + * $Revision: 1.15 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation * Author(s): Ingo Adlung (adlung@de.ibm.com) - * Cornelia Huck (cohuck@de.ibm.com) + * Cornelia Huck (cornelia.huck@de.ibm.com) * Arnd Bergmann (arndb@de.ibm.com) */ diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c index daf21e03b21..72f27c151c0 100644 --- a/drivers/s390/cio/blacklist.c +++ b/drivers/s390/cio/blacklist.c @@ -1,12 +1,12 @@ /* * drivers/s390/cio/blacklist.c * S/390 common I/O routines -- blacklisting of specific devices - * $Revision: 1.39 $ + * $Revision: 1.42 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation * Author(s): Ingo Adlung (adlung@de.ibm.com) - * Cornelia Huck (cohuck@de.ibm.com) + * Cornelia Huck (cornelia.huck@de.ibm.com) * Arnd Bergmann (arndb@de.ibm.com) */ diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 503a568e47c..6c077ad71ed 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -1,12 +1,12 @@ /* * drivers/s390/cio/ccwgroup.c * bus driver for ccwgroup - * $Revision: 1.33 $ + * $Revision: 1.35 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation * Author(s): Arnd Bergmann (arndb@de.ibm.com) - * Cornelia Huck (cohuck@de.ibm.com) + * Cornelia Huck (cornelia.huck@de.ibm.com) */ #include #include diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 7270808c02d..2cbb724791a 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -1,12 +1,12 @@ /* * drivers/s390/cio/chsc.c * S/390 common I/O routines -- channel subsystem call - * $Revision: 1.126 $ + * $Revision: 1.128 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation * Author(s): Ingo Adlung (adlung@de.ibm.com) - * Cornelia Huck (cohuck@de.ibm.com) + * Cornelia Huck (cornelia.huck@de.ibm.com) * Arnd Bergmann (arndb@de.ibm.com) */ diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 7376bc87206..6223b06d27d 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -1,12 +1,12 @@ /* * drivers/s390/cio/cio.c * S/390 common I/O routines -- low level i/o calls - * $Revision: 1.138 $ + * $Revision: 1.140 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation * Author(s): Ingo Adlung (adlung@de.ibm.com) - * Cornelia Huck (cohuck@de.ibm.com) + * Cornelia Huck (cornelia.huck@de.ibm.com) * Arnd Bergmann (arndb@de.ibm.com) * Martin Schwidefsky (schwidefsky@de.ibm.com) */ diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 2d319fb812c..516108779f6 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -1,12 +1,12 @@ /* * drivers/s390/cio/css.c * driver for channel subsystem - * $Revision: 1.93 $ + * $Revision: 1.96 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation * Author(s): Arnd Bergmann (arndb@de.ibm.com) - * Cornelia Huck (cohuck@de.ibm.com) + * Cornelia Huck (cornelia.huck@de.ibm.com) */ #include #include diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index eb73605a052..a67e7e60e33 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -1,12 +1,12 @@ /* * drivers/s390/cio/device.c * bus driver for ccw devices - * $Revision: 1.137 $ + * $Revision: 1.140 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation * Author(s): Arnd Bergmann (arndb@de.ibm.com) - * Cornelia Huck (cohuck@de.ibm.com) + * Cornelia Huck (cornelia.huck@de.ibm.com) * Martin Schwidefsky (schwidefsky@de.ibm.com) */ #include diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 23d12b65e5f..b302779e7cf 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -4,7 +4,7 @@ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation - * Author(s): Cornelia Huck(cohuck@de.ibm.com) + * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com) * Martin Schwidefsky (schwidefsky@de.ibm.com) */ diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c index 04ceba343db..e60b2d8103b 100644 --- a/drivers/s390/cio/device_id.c +++ b/drivers/s390/cio/device_id.c @@ -3,7 +3,7 @@ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation - * Author(s): Cornelia Huck(cohuck@de.ibm.com) + * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com) * Martin Schwidefsky (schwidefsky@de.ibm.com) * * Sense ID functions. diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index 143b6c25a4e..8b0218949b6 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c @@ -1,12 +1,12 @@ /* * drivers/s390/cio/device_ops.c * - * $Revision: 1.58 $ + * $Revision: 1.61 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) - * Cornelia Huck (cohuck@de.ibm.com) + * Cornelia Huck (cornelia.huck@de.ibm.com) */ #include #include diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c index 052832d03d3..d2a5b04d7cb 100644 --- a/drivers/s390/cio/device_pgid.c +++ b/drivers/s390/cio/device_pgid.c @@ -3,7 +3,7 @@ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation - * Author(s): Cornelia Huck(cohuck@de.ibm.com) + * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com) * Martin Schwidefsky (schwidefsky@de.ibm.com) * * Path Group ID functions. diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c index db09c209098..dad4dd9887c 100644 --- a/drivers/s390/cio/device_status.c +++ b/drivers/s390/cio/device_status.c @@ -3,7 +3,7 @@ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation - * Author(s): Cornelia Huck(cohuck@de.ibm.com) + * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com) * Martin Schwidefsky (schwidefsky@de.ibm.com) * * Status accumulation and basic sense functions. diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index 30a836ffc31..77be2c39bfe 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c @@ -7,7 +7,7 @@ * * Copyright 2000,2002 IBM Corporation * Author(s): Utz Bacher - * 2.6 cio integration by Cornelia Huck + * 2.6 cio integration by Cornelia Huck * * Restriction: only 63 iqdio subchannels would have its own indicator, * after that, subsequent subchannels share one indicator @@ -56,7 +56,7 @@ #include "ioasm.h" #include "chsc.h" -#define VERSION_QDIO_C "$Revision: 1.114 $" +#define VERSION_QDIO_C "$Revision: 1.117 $" /****************** MODULE PARAMETER VARIABLES ********************/ MODULE_AUTHOR("Utz Bacher "); diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c index 0db4f57a6a9..1901feef07d 100644 --- a/drivers/s390/net/ctcmain.c +++ b/drivers/s390/net/ctcmain.c @@ -1,5 +1,5 @@ /* - * $Id: ctcmain.c,v 1.78 2005/09/07 12:18:02 pavlic Exp $ + * $Id: ctcmain.c,v 1.79 2006/01/11 11:32:18 cohuck Exp $ * * CTC / ESCON network driver * @@ -8,7 +8,7 @@ * Fixes by : Jochen Röhrig (roehrig@de.ibm.com) * Arnaldo Carvalho de Melo Peter Tiedemann (ptiedem@de.ibm.com) - * Driver Model stuff by : Cornelia Huck + * Driver Model stuff by : Cornelia Huck * * Documentation used: * - Principles of Operation (IBM doc#: SA22-7201-06) @@ -37,7 +37,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.78 $ + * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.79 $ * */ #undef DEBUG @@ -248,7 +248,7 @@ static void print_banner(void) { static int printed = 0; - char vbuf[] = "$Revision: 1.78 $"; + char vbuf[] = "$Revision: 1.79 $"; char *version = vbuf; if (printed) diff --git a/drivers/s390/net/cu3088.c b/drivers/s390/net/cu3088.c index 77dacb46573..2014fb7a488 100644 --- a/drivers/s390/net/cu3088.c +++ b/drivers/s390/net/cu3088.c @@ -1,11 +1,11 @@ /* - * $Id: cu3088.c,v 1.36 2005/10/25 14:37:17 cohuck Exp $ + * $Id: cu3088.c,v 1.38 2006/01/12 14:33:09 cohuck Exp $ * * CTC / LCS ccw_device driver * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation * Author(s): Arnd Bergmann - * Cornelia Huck + * Cornelia Huck * * 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 diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index 69425a7a6e9..ac4c4b83fe1 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -1,12 +1,13 @@ /* - * $Id: netiucv.c,v 1.66 2005/05/11 08:10:17 holzheu Exp $ + * $Id: netiucv.c,v 1.69 2006/01/12 14:33:09 cohuck Exp $ * * IUCV network driver * * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com) * - * Driverfs integration and all bugs therein by Cornelia Huck(cohuck@de.ibm.com) + * Sysfs integration and all bugs therein by Cornelia Huck + * (cornelia.huck@de.ibm.com) * * Documentation used: * the source of the original IUCV driver by: @@ -30,7 +31,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: IUCV network driver $Revision: 1.66 $ + * RELEASE-TAG: IUCV network driver $Revision: 1.69 $ * */ @@ -2076,7 +2077,7 @@ DRIVER_ATTR(remove, 0200, NULL, remove_write); static void netiucv_banner(void) { - char vbuf[] = "$Revision: 1.66 $"; + char vbuf[] = "$Revision: 1.69 $"; char *version = vbuf; if ((version = strchr(version, ':'))) { diff --git a/drivers/s390/s390_rdev.c b/drivers/s390/s390_rdev.c index 566cc3d185b..206518c7d33 100644 --- a/drivers/s390/s390_rdev.c +++ b/drivers/s390/s390_rdev.c @@ -1,11 +1,11 @@ /* * drivers/s390/s390_rdev.c * s390 root device - * $Revision: 1.2 $ + * $Revision: 1.4 $ * * Copyright (C) 2002, 2005 IBM Deutschland Entwicklung GmbH, * IBM Corporation - * Author(s): Cornelia Huck (cohuck@de.ibm.com) + * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com) * Carsten Otte (cotte@de.ibm.com) */ diff --git a/include/asm-s390/s390_rdev.h b/include/asm-s390/s390_rdev.h index 3ad78f2b9c4..6fa20442a48 100644 --- a/include/asm-s390/s390_rdev.h +++ b/include/asm-s390/s390_rdev.h @@ -2,7 +2,7 @@ * include/asm-s390/ccwdev.h * * Copyright (C) 2002,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation - * Author(s): Cornelia Huck + * Author(s): Cornelia Huck * Carsten Otte * * Interface for s390 root device -- GitLab From ed68cb3676bb179768529aeb808403d57295af56 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Sat, 14 Jan 2006 13:21:05 -0800 Subject: [PATCH 282/465] [PATCH] s390: fix blk_queue_ordered call in dasd.c fixup The QUEUE_ORDERED_* numbers got renumbered and by accident the dasd driver was changed to use QUEUE_ORDERED_DRAIN instead of QUEUE_ORDERED_TAG. Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/block/dasd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index b147beb9e1c..ef4c687e7c0 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -1635,7 +1635,7 @@ dasd_setup_queue(struct dasd_device * device) blk_queue_max_hw_segments(device->request_queue, -1L); blk_queue_max_segment_size(device->request_queue, -1L); blk_queue_segment_boundary(device->request_queue, -1L); - blk_queue_ordered(device->request_queue, QUEUE_ORDERED_DRAIN, NULL); + blk_queue_ordered(device->request_queue, QUEUE_ORDERED_TAG, NULL); } /* -- GitLab From 505970b96e3b7d22177c38e03435a68376628e7a Mon Sep 17 00:00:00 2001 From: Paul Jackson Date: Sat, 14 Jan 2006 13:21:06 -0800 Subject: [PATCH 283/465] [PATCH] cpuset oom lock fix The problem, reported in: http://bugzilla.kernel.org/show_bug.cgi?id=5859 and by various other email messages and lkml posts is that the cpuset hook in the oom (out of memory) code can try to take a cpuset semaphore while holding the tasklist_lock (a spinlock). One must not sleep while holding a spinlock. The fix seems easy enough - move the cpuset semaphore region outside the tasklist_lock region. This required a few lines of mechanism to implement. The oom code where the locking needs to be changed does not have access to the cpuset locks, which are internal to kernel/cpuset.c only. So I provided a couple more cpuset interface routines, available to the rest of the kernel, which simple take and drop the lock needed here (cpusets callback_sem). Signed-off-by: Paul Jackson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/cpuset.h | 6 ++++++ kernel/cpuset.c | 33 ++++++++++++++++++++++++++++----- mm/oom_kill.c | 3 +++ 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h index c472f972bd6..3bc60692711 100644 --- a/include/linux/cpuset.h +++ b/include/linux/cpuset.h @@ -48,6 +48,9 @@ extern void __cpuset_memory_pressure_bump(void); extern struct file_operations proc_cpuset_operations; extern char *cpuset_task_status_allowed(struct task_struct *task, char *buffer); +extern void cpuset_lock(void); +extern void cpuset_unlock(void); + #else /* !CONFIG_CPUSETS */ static inline int cpuset_init_early(void) { return 0; } @@ -93,6 +96,9 @@ static inline char *cpuset_task_status_allowed(struct task_struct *task, return buffer; } +static inline void cpuset_lock(void) {} +static inline void cpuset_unlock(void) {} + #endif /* !CONFIG_CPUSETS */ #endif /* _LINUX_CPUSET_H */ diff --git a/kernel/cpuset.c b/kernel/cpuset.c index d4b6bd7d74e..fe2f71f92ae 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -2149,6 +2149,33 @@ int __cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask) return allowed; } +/** + * cpuset_lock - lock out any changes to cpuset structures + * + * The out of memory (oom) code needs to lock down cpusets + * from being changed while it scans the tasklist looking for a + * task in an overlapping cpuset. Expose callback_sem via this + * cpuset_lock() routine, so the oom code can lock it, before + * locking the task list. The tasklist_lock is a spinlock, so + * must be taken inside callback_sem. + */ + +void cpuset_lock(void) +{ + down(&callback_sem); +} + +/** + * cpuset_unlock - release lock on cpuset changes + * + * Undo the lock taken in a previous cpuset_lock() call. + */ + +void cpuset_unlock(void) +{ + up(&callback_sem); +} + /** * cpuset_excl_nodes_overlap - Do we overlap @p's mem_exclusive ancestors? * @p: pointer to task_struct of some other task. @@ -2158,7 +2185,7 @@ int __cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask) * determine if task @p's memory usage might impact the memory * available to the current task. * - * Acquires callback_sem - not suitable for calling from a fast path. + * Call while holding callback_sem. **/ int cpuset_excl_nodes_overlap(const struct task_struct *p) @@ -2166,8 +2193,6 @@ int cpuset_excl_nodes_overlap(const struct task_struct *p) const struct cpuset *cs1, *cs2; /* my and p's cpuset ancestors */ int overlap = 0; /* do cpusets overlap? */ - down(&callback_sem); - task_lock(current); if (current->flags & PF_EXITING) { task_unlock(current); @@ -2186,8 +2211,6 @@ int cpuset_excl_nodes_overlap(const struct task_struct *p) overlap = nodes_intersects(cs1->mems_allowed, cs2->mems_allowed); done: - up(&callback_sem); - return overlap; } diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 4748b906aff..14bd4ec7959 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -274,6 +274,7 @@ void out_of_memory(gfp_t gfp_mask, int order) show_mem(); } + cpuset_lock(); read_lock(&tasklist_lock); retry: p = select_bad_process(); @@ -284,6 +285,7 @@ retry: /* Found nothing?!?! Either we hang forever, or we panic. */ if (!p) { read_unlock(&tasklist_lock); + cpuset_unlock(); panic("Out of memory and no killable processes...\n"); } @@ -293,6 +295,7 @@ retry: out: read_unlock(&tasklist_lock); + cpuset_unlock(); if (mm) mmput(mm); -- GitLab From 082a05c6f02e00982dd42ddae434fbc806a822e5 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Sat, 14 Jan 2006 13:21:07 -0800 Subject: [PATCH 284/465] [PATCH] ext2: remove d_splice_alias NULL check from ext2_lookup Remove redundant NULL check in ext2_lookup() as d_splice_alias() can take NULL inode as input. Signed-off-by: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext2/namei.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c index c5513953c82..ad1432a2a62 100644 --- a/fs/ext2/namei.c +++ b/fs/ext2/namei.c @@ -83,10 +83,7 @@ static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, str if (!inode) return ERR_PTR(-EACCES); } - if (inode) - return d_splice_alias(inode, dentry); - d_add(dentry, inode); - return NULL; + return d_splice_alias(inode, dentry); } struct dentry *ext2_get_parent(struct dentry *child) -- GitLab From ba7fe369875075c3b0def9887afb7a44fa88175e Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Sat, 14 Jan 2006 13:21:08 -0800 Subject: [PATCH 285/465] [PATCH] ext3: remove d_splice_alias NULL check from ext3_lookup Remove redundant NULL check in ext3_lookup() as d_splice_alias() can take NULL inode as input. Signed-off-by: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/namei.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index af193a304ee..8bd8ac07770 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -1005,10 +1005,7 @@ static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, str if (!inode) return ERR_PTR(-EACCES); } - if (inode) - return d_splice_alias(inode, dentry); - d_add(dentry, inode); - return NULL; + return d_splice_alias(inode, dentry); } -- GitLab From 2ff6b1c2575f13885c1d5291e4283682ad9a41cd Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Sat, 14 Jan 2006 13:21:09 -0800 Subject: [PATCH 286/465] [PATCH] isofs: remove d_splice_alias NULL check from isofs_lookup Remove redundant NULL check in isofs_lookup() as d_splice_alias() can take NULL inode as input. Signed-off-by: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/isofs/namei.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c index e37e82b7cbf..e7ba0c30e07 100644 --- a/fs/isofs/namei.c +++ b/fs/isofs/namei.c @@ -185,8 +185,5 @@ struct dentry *isofs_lookup(struct inode * dir, struct dentry * dentry, struct n } } unlock_kernel(); - if (inode) - return d_splice_alias(inode, dentry); - d_add(dentry, inode); - return NULL; + return d_splice_alias(inode, dentry); } -- GitLab From d9975d6ba0668aa21d9f0c565d7df56c805c8d5c Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Sat, 14 Jan 2006 13:21:09 -0800 Subject: [PATCH 287/465] [PATCH] reiserfs: remove d_splice_alias NULL check from reiserfs_lookup Remove redundant NULL check in reiserfs_lookup() as d_splice_alias() can take NULL inode as input. Signed-off-by: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/reiserfs/namei.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index 3549067c42d..8f8d8d01107 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c @@ -375,11 +375,7 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry, return ERR_PTR(-EIO); } - if (inode) - return d_splice_alias(inode, dentry); - - d_add(dentry, inode); - return NULL; + return d_splice_alias(inode, dentry); } /* -- GitLab From 3135806358e8d3d8ac61a13f58f148d0a98a7b9b Mon Sep 17 00:00:00 2001 From: "Valdis.Kletnieks@vt.edu" Date: Sat, 14 Jan 2006 13:21:10 -0800 Subject: [PATCH 288/465] [PATCH] quota: make useless quota error message informative fs/quota_v2.c can, under some conditions, issue a kernel message that says, in totality, 'failed read'. This patch does the following: 1) Gives a hint who issued the error message, so people reading the logs don't have to go grepping the entire kernel tree (with 11 false positives). 2) Say what amount of data we expected, and actually got. Signed-off-by: Valdis Kletnieks Cc: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/quota_v2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/quota_v2.c b/fs/quota_v2.c index 7afcbb1b937..a4ef91bb4f3 100644 --- a/fs/quota_v2.c +++ b/fs/quota_v2.c @@ -35,7 +35,8 @@ static int v2_check_quota_file(struct super_block *sb, int type) size = sb->s_op->quota_read(sb, type, (char *)&dqhead, sizeof(struct v2_disk_dqheader), 0); if (size != sizeof(struct v2_disk_dqheader)) { - printk("failed read\n"); + printk("quota_v2: failed read expected=%d got=%d\n", + sizeof(struct v2_disk_dqheader), size); return 0; } if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] || -- GitLab From 69c99ac17e2ee0eb45e2c9873e6e12d73260fc6b Mon Sep 17 00:00:00 2001 From: Coywolf Qi Hunt Date: Sat, 14 Jan 2006 13:21:11 -0800 Subject: [PATCH 289/465] [PATCH] abandon gcc 295x main.c tidy After abandon-gcc-295x.patch, this relocates the error-out-early comment. Signed-off-by: Coywolf Qi Hunt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- init/main.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/init/main.c b/init/main.c index e092b1979a9..7c79da57d3a 100644 --- a/init/main.c +++ b/init/main.c @@ -54,20 +54,18 @@ #include #include -/* - * This is one of the first .c files built. Error out early - * if we have compiler trouble.. - */ - #ifdef CONFIG_X86_LOCAL_APIC #include #endif /* - * Versions of gcc older than that listed below may actually compile - * and link okay, but the end product can have subtle run time bugs. - * To avoid associated bogus bug reports, we flatly refuse to compile - * with a gcc that is known to be too old from the very beginning. + * This is one of the first .c files built. Error out early if we have compiler + * trouble. + * + * Versions of gcc older than that listed below may actually compile and link + * okay, but the end product can have subtle run time bugs. To avoid associated + * bogus bug reports, we flatly refuse to compile with a gcc that is known to be + * too old from the very beginning. */ #if (__GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 2) #error Sorry, your GCC is too old. It builds incorrect kernels. -- GitLab From 44db77f33cc42c49f55ddb360f5e9a05581ffdc0 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Sat, 14 Jan 2006 13:21:12 -0800 Subject: [PATCH 290/465] [PATCH] ncpfs: remove kmalloc wrapper Remove remaining kmalloc wrapper bits from fs/ncpfs/. Signed-off-by: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ncpfs/inode.c | 19 ++----------------- fs/ncpfs/ioctl.c | 20 +++++++++++--------- include/linux/ncp_fs.h | 28 ---------------------------- 3 files changed, 13 insertions(+), 54 deletions(-) diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index 8c8839203cd..d277a58bd12 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -716,10 +716,8 @@ static void ncp_put_super(struct super_block *sb) fput(server->ncp_filp); kill_proc(server->m.wdog_pid, SIGTERM, 1); - if (server->priv.data) - ncp_kfree_s(server->priv.data, server->priv.len); - if (server->auth.object_name) - ncp_kfree_s(server->auth.object_name, server->auth.object_name_len); + kfree(server->priv.data); + kfree(server->auth.object_name); vfree(server->packet); sb->s_fs_info = NULL; kfree(server); @@ -958,11 +956,6 @@ out: return result; } -#ifdef DEBUG_NCP_MALLOC -int ncp_malloced; -int ncp_current_malloced; -#endif - static struct super_block *ncp_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { @@ -981,10 +974,6 @@ static int __init init_ncp_fs(void) int err; DPRINTK("ncpfs: init_module called\n"); -#ifdef DEBUG_NCP_MALLOC - ncp_malloced = 0; - ncp_current_malloced = 0; -#endif err = init_inodecache(); if (err) goto out1; @@ -1003,10 +992,6 @@ static void __exit exit_ncp_fs(void) DPRINTK("ncpfs: cleanup_module called\n"); unregister_filesystem(&ncp_fs_type); destroy_inodecache(); -#ifdef DEBUG_NCP_MALLOC - PRINTK("ncp_malloced: %d\n", ncp_malloced); - PRINTK("ncp_current_malloced: %d\n", ncp_current_malloced); -#endif } module_init(init_ncp_fs) diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c index d6e0c089e1b..eb3813ad136 100644 --- a/fs/ncpfs/ioctl.c +++ b/fs/ncpfs/ioctl.c @@ -518,10 +518,11 @@ outrel: if (user.object_name_len > NCP_OBJECT_NAME_MAX_LEN) return -ENOMEM; if (user.object_name_len) { - newname = ncp_kmalloc(user.object_name_len, GFP_USER); - if (!newname) return -ENOMEM; + newname = kmalloc(user.object_name_len, GFP_USER); + if (!newname) + return -ENOMEM; if (copy_from_user(newname, user.object_name, user.object_name_len)) { - ncp_kfree_s(newname, user.object_name_len); + kfree(newname); return -EFAULT; } } else { @@ -540,8 +541,8 @@ outrel: server->priv.len = 0; server->priv.data = NULL; /* leave critical section */ - if (oldprivate) ncp_kfree_s(oldprivate, oldprivatelen); - if (oldname) ncp_kfree_s(oldname, oldnamelen); + kfree(oldprivate); + kfree(oldname); return 0; } case NCP_IOC_GETPRIVATEDATA: @@ -581,10 +582,11 @@ outrel: if (user.len > NCP_PRIVATE_DATA_MAX_LEN) return -ENOMEM; if (user.len) { - new = ncp_kmalloc(user.len, GFP_USER); - if (!new) return -ENOMEM; + new = kmalloc(user.len, GFP_USER); + if (!new) + return -ENOMEM; if (copy_from_user(new, user.data, user.len)) { - ncp_kfree_s(new, user.len); + kfree(new); return -EFAULT; } } else { @@ -596,7 +598,7 @@ outrel: server->priv.len = user.len; server->priv.data = new; /* leave critical section */ - if (old) ncp_kfree_s(old, oldlen); + kfree(old); return 0; } diff --git a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h index 7297e4372c0..e0134256853 100644 --- a/include/linux/ncp_fs.h +++ b/include/linux/ncp_fs.h @@ -201,34 +201,6 @@ static inline struct ncp_inode_info *NCP_FINFO(struct inode *inode) return container_of(inode, struct ncp_inode_info, vfs_inode); } -#ifdef DEBUG_NCP_MALLOC - -#include - -extern int ncp_malloced; -extern int ncp_current_malloced; - -static inline void * - ncp_kmalloc(unsigned int size, int priority) -{ - ncp_malloced += 1; - ncp_current_malloced += 1; - return kmalloc(size, priority); -} - -static inline void ncp_kfree_s(void *obj, int size) -{ - ncp_current_malloced -= 1; - kfree(obj); -} - -#else /* DEBUG_NCP_MALLOC */ - -#define ncp_kmalloc(s,p) kmalloc(s,p) -#define ncp_kfree_s(o,s) kfree(o) - -#endif /* DEBUG_NCP_MALLOC */ - /* linux/fs/ncpfs/inode.c */ int ncp_notify_change(struct dentry *, struct iattr *); struct inode *ncp_iget(struct super_block *, struct ncp_entry_info *); -- GitLab From d063389ecf20e5c20be91a0007656deb9fc38a1c Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Sat, 14 Jan 2006 13:21:13 -0800 Subject: [PATCH 291/465] [PATCH] smbfs: remove kmalloc wrapper Remove the remaining kmalloc() wrapper bits from fs/smbfs/. Signed-off-by: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/smbfs/Makefile | 1 - fs/smbfs/inode.c | 32 +++++++--------------------- fs/smbfs/request.c | 13 +++++------- include/linux/smb_fs.h | 47 ------------------------------------------ 4 files changed, 12 insertions(+), 81 deletions(-) diff --git a/fs/smbfs/Makefile b/fs/smbfs/Makefile index 93246b7dd6f..6673ee82cb4 100644 --- a/fs/smbfs/Makefile +++ b/fs/smbfs/Makefile @@ -13,7 +13,6 @@ smbfs-objs := proc.o dir.o cache.o sock.o inode.o file.o ioctl.o getopt.o \ EXTRA_CFLAGS += -DSMBFS_PARANOIA #EXTRA_CFLAGS += -DSMBFS_DEBUG #EXTRA_CFLAGS += -DSMBFS_DEBUG_VERBOSE -#EXTRA_CFLAGS += -DDEBUG_SMB_MALLOC #EXTRA_CFLAGS += -DDEBUG_SMB_TIMESTAMP #EXTRA_CFLAGS += -Werror diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c index 6ec88bf59b2..02e3e82d465 100644 --- a/fs/smbfs/inode.c +++ b/fs/smbfs/inode.c @@ -487,11 +487,11 @@ smb_put_super(struct super_block *sb) if (server->conn_pid) kill_proc(server->conn_pid, SIGTERM, 1); - smb_kfree(server->ops); + kfree(server->ops); smb_unload_nls(server); sb->s_fs_info = NULL; smb_unlock_server(server); - smb_kfree(server); + kfree(server); } static int smb_fill_super(struct super_block *sb, void *raw_data, int silent) @@ -519,11 +519,10 @@ static int smb_fill_super(struct super_block *sb, void *raw_data, int silent) sb->s_op = &smb_sops; sb->s_time_gran = 100; - server = smb_kmalloc(sizeof(struct smb_sb_info), GFP_KERNEL); + server = kzalloc(sizeof(struct smb_sb_info), GFP_KERNEL); if (!server) goto out_no_server; sb->s_fs_info = server; - memset(server, 0, sizeof(struct smb_sb_info)); server->super_block = sb; server->mnt = NULL; @@ -542,8 +541,8 @@ static int smb_fill_super(struct super_block *sb, void *raw_data, int silent) /* FIXME: move these to the smb_sb_info struct */ VERBOSE("alloc chunk = %d\n", sizeof(struct smb_ops) + sizeof(struct smb_mount_data_kernel)); - mem = smb_kmalloc(sizeof(struct smb_ops) + - sizeof(struct smb_mount_data_kernel), GFP_KERNEL); + mem = kmalloc(sizeof(struct smb_ops) + + sizeof(struct smb_mount_data_kernel), GFP_KERNEL); if (!mem) goto out_no_mem; @@ -621,12 +620,12 @@ out_no_root: out_no_smbiod: smb_unload_nls(server); out_bad_option: - smb_kfree(mem); + kfree(mem); out_no_mem: if (!server->mnt) printk(KERN_ERR "smb_fill_super: allocation failure\n"); sb->s_fs_info = NULL; - smb_kfree(server); + kfree(server); goto out_fail; out_wrong_data: printk(KERN_ERR "smbfs: mount_data version %d is not supported\n", ver); @@ -782,12 +781,6 @@ out: return error; } -#ifdef DEBUG_SMB_MALLOC -int smb_malloced; -int smb_current_kmalloced; -int smb_current_vmalloced; -#endif - static struct super_block *smb_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { @@ -807,12 +800,6 @@ static int __init init_smb_fs(void) int err; DEBUG1("registering ...\n"); -#ifdef DEBUG_SMB_MALLOC - smb_malloced = 0; - smb_current_kmalloced = 0; - smb_current_vmalloced = 0; -#endif - err = init_inodecache(); if (err) goto out_inode; @@ -837,11 +824,6 @@ static void __exit exit_smb_fs(void) unregister_filesystem(&smb_fs_type); smb_destroy_request_cache(); destroy_inodecache(); -#ifdef DEBUG_SMB_MALLOC - printk(KERN_DEBUG "smb_malloced: %d\n", smb_malloced); - printk(KERN_DEBUG "smb_current_kmalloced: %d\n",smb_current_kmalloced); - printk(KERN_DEBUG "smb_current_vmalloced: %d\n",smb_current_vmalloced); -#endif } module_init(init_smb_fs) diff --git a/fs/smbfs/request.c b/fs/smbfs/request.c index a0f296d9928..c71c375863c 100644 --- a/fs/smbfs/request.c +++ b/fs/smbfs/request.c @@ -68,7 +68,7 @@ static struct smb_request *smb_do_alloc_request(struct smb_sb_info *server, goto out; if (bufsize > 0) { - buf = smb_kmalloc(bufsize, GFP_NOFS); + buf = kmalloc(bufsize, GFP_NOFS); if (!buf) { kmem_cache_free(req_cachep, req); return NULL; @@ -124,9 +124,8 @@ static void smb_free_request(struct smb_request *req) { atomic_dec(&req->rq_server->nr_requests); if (req->rq_buffer && !(req->rq_flags & SMB_REQ_STATIC)) - smb_kfree(req->rq_buffer); - if (req->rq_trans2buffer) - smb_kfree(req->rq_trans2buffer); + kfree(req->rq_buffer); + kfree(req->rq_trans2buffer); kmem_cache_free(req_cachep, req); } @@ -183,8 +182,7 @@ static int smb_setup_request(struct smb_request *req) req->rq_err = 0; req->rq_errno = 0; req->rq_fragment = 0; - if (req->rq_trans2buffer) - smb_kfree(req->rq_trans2buffer); + kfree(req->rq_trans2buffer); return 0; } @@ -647,10 +645,9 @@ static int smb_recv_trans2(struct smb_sb_info *server, struct smb_request *req) goto out_too_long; req->rq_trans2bufsize = buf_len; - req->rq_trans2buffer = smb_kmalloc(buf_len, GFP_NOFS); + req->rq_trans2buffer = kzalloc(buf_len, GFP_NOFS); if (!req->rq_trans2buffer) goto out_no_mem; - memset(req->rq_trans2buffer, 0, buf_len); req->rq_parm = req->rq_trans2buffer; req->rq_data = req->rq_trans2buffer + parm_tot; diff --git a/include/linux/smb_fs.h b/include/linux/smb_fs.h index c4153120ade..621a3d3662f 100644 --- a/include/linux/smb_fs.h +++ b/include/linux/smb_fs.h @@ -58,53 +58,6 @@ static inline struct smb_inode_info *SMB_I(struct inode *inode) /* where to find the base of the SMB packet proper */ #define smb_base(buf) ((u8 *)(((u8 *)(buf))+4)) -#ifdef DEBUG_SMB_MALLOC - -#include - -extern int smb_malloced; -extern int smb_current_vmalloced; -extern int smb_current_kmalloced; - -static inline void * -smb_vmalloc(unsigned int size) -{ - smb_malloced += 1; - smb_current_vmalloced += 1; - return vmalloc(size); -} - -static inline void -smb_vfree(void *obj) -{ - smb_current_vmalloced -= 1; - vfree(obj); -} - -static inline void * -smb_kmalloc(size_t size, int flags) -{ - smb_malloced += 1; - smb_current_kmalloced += 1; - return kmalloc(size, flags); -} - -static inline void -smb_kfree(void *obj) -{ - smb_current_kmalloced -= 1; - kfree(obj); -} - -#else /* DEBUG_SMB_MALLOC */ - -#define smb_kmalloc(s,p) kmalloc(s,p) -#define smb_kfree(o) kfree(o) -#define smb_vmalloc(s) vmalloc(s) -#define smb_vfree(o) vfree(o) - -#endif /* DEBUG_SMB_MALLOC */ - /* * Flags for the in-memory inode */ -- GitLab From 2c5608404e66047bbcd9b7788e7f3ee2555c8639 Mon Sep 17 00:00:00 2001 From: Abhay Salunke Date: Sat, 14 Jan 2006 13:21:14 -0800 Subject: [PATCH 292/465] [PATCH] dell_rbu: fix Bug 5854 This fixes http://bugzilla.kernel.org/show_bug.cgi?id=5854 Root cause: The dell_rbu driver creates entries in /sys/class/firmware/dell_rbu/ by calling request_firmware_nowait (without hotplug ) this function inturn starts a kernel thread which creates the entries in /sys/class/firmware/dell_rbu/loading , data and the thread waits on the user action to return control back to the callback fucntion of dell_rbu. The thread calls wait_on_completion which puts it in a D state until the user action happens. If there is no user action happening the load average goes up as the thread D state is taken in to account. Also after downloading the BIOS image the enrties go away momentarily but they are recreated from the callback function in dell_rbu. This causes the thread to get recreated causing the load average to permenently stay around 1. Fix: The dell_rbu also creates the entry /sys/devices/platform/dell_rbu/image_type at driver load time. The image type by default is mono if required the user can echo packet to image_type to make the BIOS update mechanism using packets. Also by echoing init in to image_type the /sys/class/firmware/dell_rbu entries can be created. The driver code was changed to not create /sys/class/firmware/dell_rbu entries during load time, and also to not create the above entries from the callback function. The entries are only created by echoing init to /sys/devices/platform/dell_rbu/image_type The user now needs to create the entries to download the image monolithic or packet. This fixes the issue since the kernel thread only is created when ever the user is ready to download the BIOS image; this minimizes the life span of the kernel thread and the load average goes back to normal. Signed off by Abhay Salunke Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/firmware/dell_rbu.c | 26 ++++---------------------- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c index dfedb777d8c..fdb8b042e64 100644 --- a/drivers/firmware/dell_rbu.c +++ b/drivers/firmware/dell_rbu.c @@ -49,7 +49,7 @@ MODULE_AUTHOR("Abhay Salunke "); MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems"); MODULE_LICENSE("GPL"); -MODULE_VERSION("3.1"); +MODULE_VERSION("3.2"); #define BIOS_SCAN_LIMIT 0xffffffff #define MAX_IMAGE_LENGTH 16 @@ -564,12 +564,10 @@ static ssize_t read_rbu_data(struct kobject *kobj, char *buffer, static void callbackfn_rbu(const struct firmware *fw, void *context) { - int rc = 0; + rbu_data.entry_created = 0; - if (!fw || !fw->size) { - rbu_data.entry_created = 0; + if (!fw || !fw->size) return; - } spin_lock(&rbu_data.lock); if (!strcmp(image_type, "mono")) { @@ -592,15 +590,6 @@ static void callbackfn_rbu(const struct firmware *fw, void *context) } else pr_debug("invalid image type specified.\n"); spin_unlock(&rbu_data.lock); - - rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, - "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu); - if (rc) - printk(KERN_ERR - "dell_rbu:%s request_firmware_nowait failed" - " %d\n", __FUNCTION__, rc); - else - rbu_data.entry_created = 1; } static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer, @@ -735,14 +724,7 @@ static int __init dcdrbu_init(void) sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_packet_size_attr); - rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, - "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu); - if (rc) - printk(KERN_ERR "dell_rbu:%s:request_firmware_nowait" - " failed %d\n", __FUNCTION__, rc); - else - rbu_data.entry_created = 1; - + rbu_data.entry_created = 0; return rc; } -- GitLab From 032874e49271f8c9c53c137cb60cf12617a953a0 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sat, 14 Jan 2006 13:21:15 -0800 Subject: [PATCH 293/465] [PATCH] cs89x0: credit Dmitry Pervushin Credit Dmitry Pervushin for the PNX010X platform support. Signed-off-by: Lennert Buytenhek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/cs89x0.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index e2cfde7e31e..494c71e05c8 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c @@ -87,6 +87,9 @@ Deepak Saxena : dsaxena@plexity.net : Intel IXDP2x01 (XScale ixp2x00 NPU) platform support + Dmitry Pervushin : dpervushin@ru.mvista.com + : PNX010X platform support + */ /* Always include 'config.h' first in case the user wants to turn on -- GitLab From 580d7b8cc59d68a3d26bfcc64c2053b464782c9a Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sat, 14 Jan 2006 13:21:16 -0800 Subject: [PATCH 294/465] [PATCH] cs89x0: use #elif instead of #else/#if/#endif Signed-off-by: Lennert Buytenhek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/cs89x0.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index 494c71e05c8..a7ef8a66ba0 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c @@ -353,8 +353,7 @@ writeword(unsigned long base_addr, int portno, int value) { __raw_writel((u16)value, base_addr + (portno << 1)); } -#else -#if defined(CONFIG_ARCH_PNX010X) +#elif defined(CONFIG_ARCH_PNX010X) static int readword(unsigned long base_addr, int portno) { @@ -379,7 +378,6 @@ writeword(unsigned long base_addr, int portno, int value) outw(value, base_addr + portno); } #endif -#endif static void readwords(unsigned long base_addr, int portno, void *buf, int length) -- GitLab From a07f0dbec01fda6d88f5089e21454b8df53d36fc Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sat, 14 Jan 2006 13:21:17 -0800 Subject: [PATCH 295/465] [PATCH] cs89x0: use u16 for device register data cs89x0 inconsistently used 'int' and 'u32' for device register data. As the cs89x0 is a 16-bit chip, change the I/O accessors over to 'u16'. (Spotted by Deepak Saxena.) Signed-off-by: Lennert Buytenhek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/cs89x0.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index a7ef8a66ba0..2687b3e0994 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c @@ -342,38 +342,38 @@ out: #endif #if defined(CONFIG_ARCH_IXDP2X01) -static int +static u16 readword(unsigned long base_addr, int portno) { - return (u16)__raw_readl(base_addr + (portno << 1)); + return __raw_readl(base_addr + (portno << 1)); } static void -writeword(unsigned long base_addr, int portno, int value) +writeword(unsigned long base_addr, int portno, u16 value) { - __raw_writel((u16)value, base_addr + (portno << 1)); + __raw_writel(value, base_addr + (portno << 1)); } #elif defined(CONFIG_ARCH_PNX010X) -static int +static u16 readword(unsigned long base_addr, int portno) { return inw(base_addr + (portno << 1)); } static void -writeword(unsigned long base_addr, int portno, int value) +writeword(unsigned long base_addr, int portno, u16 value) { outw(value, base_addr + (portno << 1)); } #else -static int +static u16 readword(unsigned long base_addr, int portno) { return inw(base_addr + portno); } static void -writeword(unsigned long base_addr, int portno, int value) +writeword(unsigned long base_addr, int portno, u16 value) { outw(value, base_addr + portno); } @@ -385,11 +385,11 @@ readwords(unsigned long base_addr, int portno, void *buf, int length) u8 *buf8 = (u8 *)buf; do { - u32 tmp32; + u16 tmp16; - tmp32 = readword(base_addr, portno); - *buf8++ = (u8)tmp32; - *buf8++ = (u8)(tmp32 >> 8); + tmp16 = readword(base_addr, portno); + *buf8++ = (u8)tmp16; + *buf8++ = (u8)(tmp16 >> 8); } while (--length); } @@ -399,23 +399,23 @@ writewords(unsigned long base_addr, int portno, void *buf, int length) u8 *buf8 = (u8 *)buf; do { - u32 tmp32; + u16 tmp16; - tmp32 = *buf8++; - tmp32 |= (*buf8++) << 8; - writeword(base_addr, portno, tmp32); + tmp16 = *buf8++; + tmp16 |= (*buf8++) << 8; + writeword(base_addr, portno, tmp16); } while (--length); } -static int -readreg(struct net_device *dev, int regno) +static u16 +readreg(struct net_device *dev, u16 regno) { writeword(dev->base_addr, ADD_PORT, regno); return readword(dev->base_addr, DATA_PORT); } static void -writereg(struct net_device *dev, int regno, int value) +writereg(struct net_device *dev, u16 regno, u16 value) { writeword(dev->base_addr, ADD_PORT, regno); writeword(dev->base_addr, DATA_PORT, value); -- GitLab From 9c878967d32a10cb604718f7608efa0ea3d8b596 Mon Sep 17 00:00:00 2001 From: Deepak Saxena Date: Sat, 14 Jan 2006 13:21:18 -0800 Subject: [PATCH 296/465] [PATCH] cs89x0: add ixdp2351 support This patch adds support for the Intel IXDP2351 to the CS89x0 driver. Signed-off-by: Deepak Saxena Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/Kconfig | 2 +- drivers/net/cs89x0.c | 29 ++++++++++++++++++++++++----- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 5c15f3e9ea0..171999e67ee 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1387,7 +1387,7 @@ config FORCEDETH config CS89x0 tristate "CS89x0 support" - depends on NET_PCI && (ISA || ARCH_IXDP2X01 || ARCH_PNX010X) + depends on NET_PCI && (ISA || MACH_IXDP2351 || ARCH_IXDP2X01 || ARCH_PNX010X) ---help--- Support for CS89x0 chipset based Ethernet cards. If you have a network (Ethernet) card of this type, say Y and read the diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index 2687b3e0994..fab6586d87e 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c @@ -90,6 +90,9 @@ Dmitry Pervushin : dpervushin@ru.mvista.com : PNX010X platform support + Deepak Saxena : dsaxena@plexity.net + : Intel IXDP2351 platform support + */ /* Always include 'config.h' first in case the user wants to turn on @@ -174,6 +177,10 @@ static unsigned int cs8900_irq_map[] = {12,0,0,0}; static unsigned int netcard_portlist[] __initdata = { 0x0300, 0}; static unsigned int cs8900_irq_map[] = {1,0,0,0}; +#elif defined(CONFIG_MACH_IXDP2351) +static unsigned int netcard_portlist[] __initdata = {IXDP2351_VIRT_CS8900_BASE, 0}; +static unsigned int cs8900_irq_map[] = {IRQ_IXDP2351_CS8900, 0, 0, 0}; +#include #elif defined(CONFIG_ARCH_IXDP2X01) #include static unsigned int netcard_portlist[] __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0}; @@ -341,7 +348,19 @@ out: } #endif -#if defined(CONFIG_ARCH_IXDP2X01) +#if defined(CONFIG_MACH_IXDP2351) +static u16 +readword(unsigned long base_addr, int portno) +{ + return __raw_readw(base_addr + (portno << 1)); +} + +static void +writeword(unsigned long base_addr, int portno, u16 value) +{ + __raw_writew(value, base_addr + (portno << 1)); +} +#elif defined(CONFIG_ARCH_IXDP2X01) static u16 readword(unsigned long base_addr, int portno) { @@ -781,7 +800,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) } else { i = lp->isa_config & INT_NO_MASK; if (lp->chip_type == CS8900) { -#if defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX010X) +#if defined(CONFIG_MACH_IXDP2351) || defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX010X) i = cs8900_irq_map[0]; #else /* Translate the IRQ using the IRQ mapping table. */ @@ -1013,7 +1032,7 @@ skip_this_frame: void __init reset_chip(struct net_device *dev) { -#ifndef CONFIG_ARCH_IXDP2X01 +#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) struct net_local *lp = netdev_priv(dev); int ioaddr = dev->base_addr; #endif @@ -1024,7 +1043,7 @@ void __init reset_chip(struct net_device *dev) /* wait 30 ms */ msleep(30); -#ifndef CONFIG_ARCH_IXDP2X01 +#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) if (lp->chip_type != CS8900) { /* Hardware problem requires PNP registers to be reconfigured after a reset */ writeword(ioaddr, ADD_PORT, PP_CS8920_ISAINT); @@ -1288,7 +1307,7 @@ net_open(struct net_device *dev) else #endif { -#if !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX010X) +#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX010X) if (((1 << dev->irq) & lp->irq_map) == 0) { printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n", dev->name, dev->irq, lp->irq_map); -- GitLab From a6b25b675db9f9f1af640b928f5476e8454b391c Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 14 Jan 2006 13:21:19 -0800 Subject: [PATCH 297/465] [PATCH] nlm kernel-parameters update Add 2 lockd kernel parameters and spell 2 others correctly. Signed-off-by: Randy Dunlap Cc: Neil Brown Cc: Olaf Kirch Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/kernel-parameters.txt | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index fe11fccf7e4..e88e348886f 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -712,9 +712,17 @@ running once the system is up. load_ramdisk= [RAM] List of ramdisks to load from floppy See Documentation/ramdisk.txt. - lockd.udpport= [NFS] + lockd.nlm_grace_period=P [NFS] Assign grace period. + Format: + + lockd.nlm_tcpport=N [NFS] Assign TCP port. + Format: - lockd.tcpport= [NFS] + lockd.nlm_timeout=T [NFS] Assign timeout value. + Format: + + lockd.nlm_udpport=M [NFS] Assign UDP port. + Format: logibm.irq= [HW,MOUSE] Logitech Bus Mouse Driver Format: -- GitLab From 16ab3adf562fb723d9085c998637f214b10072c5 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 14 Jan 2006 13:21:20 -0800 Subject: [PATCH 298/465] [PATCH] Update kernel-parameters.txt IOSCHED to spell out 'anticipatory' Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/kernel-parameters.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index e88e348886f..1cbcf65b764 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -471,7 +471,7 @@ running once the system is up. arch/i386/kernel/cpu/cpufreq/elanfreq.c. elevator= [IOSCHED] - Format: {"as" | "cfq" | "deadline" | "noop"} + Format: {"anticipatory" | "cfq" | "deadline" | "noop"} See Documentation/block/as-iosched.txt and Documentation/block/deadline-iosched.txt for details. -- GitLab From 4836f5749e55663f884ea25920ff88de7822f0a8 Mon Sep 17 00:00:00 2001 From: Christian Trefzer Date: Sat, 14 Jan 2006 13:21:21 -0800 Subject: [PATCH 299/465] [PATCH] neofb: take existing display configuration as default On a Dell Latitude CPi-A I noticed a strangeness wrt. the handling of an external monitor by the neomagic framebuffer driver, namely when the laptop is docked in a C/Dock II with the lid shut. A cold boot would result in the BIOS configuring the video chip to use the "external monitor only" mode, yet neofb would default to "internal LCD only". An attempt for a quick fix by using the Fn-F8 keystroke to toggle the display combination modes resulted in a reproductible hard lock, powering down being the only solution. The attached patch makes neofb probe the register for the current display mode, using that value as a default if nothing was specified as kernel/module parameter. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/neofb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c index e18c9f98a40..747602aa561 100644 --- a/drivers/video/neofb.c +++ b/drivers/video/neofb.c @@ -853,7 +853,7 @@ static int neofb_set_par(struct fb_info *info) /* If the user did not specify any display devices, then... */ if (par->PanelDispCntlReg1 == 0x00) { /* Default to internal (i.e., LCD) only. */ - par->PanelDispCntlReg1 |= 0x02; + par->PanelDispCntlReg1 = vga_rgfx(NULL, 0x20) & 0x03; } /* If we are using a fixed mode, then tell the chip we are. */ -- GitLab From a80da7389891d0eeacbd568a9b54f665fd424d14 Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Sat, 14 Jan 2006 13:21:23 -0800 Subject: [PATCH 300/465] [PATCH] gx1fb: (try to) play nicer with various BIOSes Seems that the CS5530A chip used in Geode GX1 systems has some crazy feature that causes SMI traps when accessing the PCI configuration space of the video device. Various GX1 BIOSes seem to use this 'feature' to hide the real BARs of the device. This patch disables these traps (in an early PCI fixup) so that Linux sees the real, physical BARs and not the virtual ones provided by the BIOS. This should allow the GX1 framebuffer driver to work on more systems that have different BIOSes as the driver no longer guesses at what the virtual BARs mean. I'm not entirely sure it the correct solution as I can neither test regular VGA console nor the X's 'cyrix' video driver so there might be some breakage there -- probably best to get some more testers before applying it. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/pci/fixup.c | 16 ++++++++++++++++ drivers/video/geode/gx1fb_core.c | 11 ++++------- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c index 65f67070db6..83c3645ccc4 100644 --- a/arch/i386/pci/fixup.c +++ b/arch/i386/pci/fixup.c @@ -449,3 +449,19 @@ static void __devinit pci_post_fixup_toshiba_ohci1394(struct pci_dev *dev) } DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_TI, 0x8032, pci_post_fixup_toshiba_ohci1394); + + +/* + * Prevent the BIOS trapping accesses to the Cyrix CS5530A video device + * configuration space. + */ +static void __devinit pci_early_fixup_cyrix_5530(struct pci_dev *dev) +{ + u8 r; + /* clear 'F4 Video Configuration Trap' bit */ + pci_read_config_byte(dev, 0x42, &r); + r &= 0xfd; + pci_write_config_byte(dev, 0x42, r); +} +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, + pci_early_fixup_cyrix_5530); diff --git a/drivers/video/geode/gx1fb_core.c b/drivers/video/geode/gx1fb_core.c index 8e8da743399..20e69156d72 100644 --- a/drivers/video/geode/gx1fb_core.c +++ b/drivers/video/geode/gx1fb_core.c @@ -215,11 +215,11 @@ static int __init gx1fb_map_video_memory(struct fb_info *info, struct pci_dev *d if (ret < 0) return ret; - ret = pci_request_region(dev, 1, "gx1fb (video)"); + ret = pci_request_region(dev, 0, "gx1fb (video)"); if (ret < 0) return ret; - par->vid_regs = ioremap(pci_resource_start(dev, 1), - pci_resource_len(dev, 1)); + par->vid_regs = ioremap(pci_resource_start(dev, 0), + pci_resource_len(dev, 0)); if (!par->vid_regs) return -ENOMEM; @@ -229,12 +229,9 @@ static int __init gx1fb_map_video_memory(struct fb_info *info, struct pci_dev *d if (!par->dc_regs) return -ENOMEM; - ret = pci_request_region(dev, 0, "gx1fb (frame buffer)"); - if (ret < 0 ) - return -EBUSY; if ((fb_len = gx1_frame_buffer_size()) < 0) return -ENOMEM; - info->fix.smem_start = pci_resource_start(dev, 0); + info->fix.smem_start = gx_base + 0x800000; info->fix.smem_len = fb_len; info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); if (!info->screen_base) -- GitLab From 67a6680d64e18c7a1901f31ef747ea53b6cd986d Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 14 Jan 2006 13:21:25 -0800 Subject: [PATCH 301/465] [PATCH] fbdev: Sanitize ->fb_ioctl prototype The ioctl and file arguments to ->fb_mmap are totally unused and there's not reason a driver should need them. Also update the ->fb_compat_ioctl prototype to be the same as ->fb_mmap. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/amifb.c | 9 +++------ drivers/video/arcfb.c | 5 ++--- drivers/video/atafb.c | 3 +-- drivers/video/aty/aty128fb.c | 6 ++---- drivers/video/aty/atyfb_base.c | 6 ++---- drivers/video/aty/radeon_base.c | 4 ++-- drivers/video/bw2.c | 6 ++---- drivers/video/cg14.c | 6 ++---- drivers/video/cg3.c | 6 ++---- drivers/video/cg6.c | 6 ++---- drivers/video/fbmem.c | 4 ++-- drivers/video/ffb.c | 6 ++---- drivers/video/imsttfb.c | 3 +-- drivers/video/intelfb/intelfbdrv.c | 8 +++----- drivers/video/kyro/fbdev.c | 5 ++--- drivers/video/leo.c | 6 ++---- drivers/video/matrox/matroxfb_base.c | 5 ++--- drivers/video/matrox/matroxfb_crtc2.c | 9 ++++----- drivers/video/p9100.c | 7 +++---- drivers/video/pm3fb.c | 8 ++------ drivers/video/pmag-aa-fb.c | 3 +-- drivers/video/radeonfb.c | 4 ++-- drivers/video/sis/sis_main.c | 28 ++++++++------------------- drivers/video/sis/sis_main.h | 5 +++++ drivers/video/sstfb.c | 3 +-- drivers/video/tcx.c | 7 +++---- include/linux/fb.h | 8 ++++---- 27 files changed, 67 insertions(+), 109 deletions(-) diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index 2c42a812655..3033c72dea2 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c @@ -1131,9 +1131,7 @@ static void amifb_copyarea(struct fb_info *info, const struct fb_copyarea *region); static void amifb_imageblit(struct fb_info *info, const struct fb_image *image); -static int amifb_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, - struct fb_info *info); +static int amifb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg); /* @@ -2172,9 +2170,8 @@ static void amifb_imageblit(struct fb_info *info, const struct fb_image *image) * Amiga Frame Buffer Specific ioctls */ -static int amifb_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, - struct fb_info *info) +static int amifb_ioctl(struct fb_info *info, + unsigned int cmd, unsigned long arg) { union { struct fb_fix_cursorinfo fix; diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c index 89060b2db8e..df8e5667b34 100644 --- a/drivers/video/arcfb.c +++ b/drivers/video/arcfb.c @@ -399,9 +399,8 @@ static void arcfb_imageblit(struct fb_info *info, const struct fb_image *image) image->height); } -static int arcfb_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, - struct fb_info *info) +static int arcfb_ioctl(struct fb_info *info, + unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; struct arcfb_par *par = info->par; diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c index 15ec1295bc2..e69ab65f784 100644 --- a/drivers/video/atafb.c +++ b/drivers/video/atafb.c @@ -2571,8 +2571,7 @@ atafb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info) } static int -atafb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg, int con, struct fb_info *info) +atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { switch (cmd) { #ifdef FBCMD_GET_CURRENTPAR diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index e686185a076..bfc8a93b2c7 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -431,8 +431,7 @@ static int aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, static int aty128fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fb); static int aty128fb_blank(int blank, struct fb_info *fb); -static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg, struct fb_info *info); +static int aty128fb_ioctl(struct fb_info *info, u_int cmd, unsigned long arg); static int aty128fb_sync(struct fb_info *info); /* @@ -2108,8 +2107,7 @@ static int aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, /* in param: u32* backlight value: 0 to 15 */ #define FBIO_ATY128_SET_MIRROR _IOW('@', 2, __u32) -static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg, struct fb_info *info) +static int aty128fb_ioctl(struct fb_info *info, u_int cmd, u_long arg) { struct aty128fb_par *par = info->par; u32 value; diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index ed81005cbdb..75b463ad4c7 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -238,8 +238,7 @@ static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info); static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); static int atyfb_blank(int blank, struct fb_info *info); -static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg, struct fb_info *info); +static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg); extern void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect); extern void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area); extern void atyfb_imageblit(struct fb_info *info, const struct fb_image *image); @@ -1739,8 +1738,7 @@ struct atyclk { #define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) #endif -static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg, struct fb_info *info) +static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg) { struct atyfb_par *par = (struct atyfb_par *) info->par; #ifdef __sparc__ diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 156db84cb36..c9f0c5a07e6 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -864,8 +864,8 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var, } -static int radeonfb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg, struct fb_info *info) +static int radeonfb_ioctl (struct fb_info *info, unsigned int cmd, + unsigned long arg) { struct radeonfb_info *rinfo = info->par; unsigned int tmp; diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c index 9248fe1fbb1..641a6c1fbf2 100644 --- a/drivers/video/bw2.c +++ b/drivers/video/bw2.c @@ -36,8 +36,7 @@ static int bw2_blank(int, struct fb_info *); static int bw2_mmap(struct fb_info *, struct file *, struct vm_area_struct *); -static int bw2_ioctl(struct inode *, struct file *, unsigned int, - unsigned long, struct fb_info *); +static int bw2_ioctl(struct fb_info *, unsigned int, unsigned long); /* * Frame buffer operations @@ -181,8 +180,7 @@ static int bw2_mmap(struct fb_info *info, struct file *file, struct vm_area_stru vma); } -static int bw2_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg, struct fb_info *info) +static int bw2_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { struct bw2_par *par = (struct bw2_par *) info->par; diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c index a56147102ab..edb9936673c 100644 --- a/drivers/video/cg14.c +++ b/drivers/video/cg14.c @@ -32,8 +32,7 @@ static int cg14_setcolreg(unsigned, unsigned, unsigned, unsigned, unsigned, struct fb_info *); static int cg14_mmap(struct fb_info *, struct file *, struct vm_area_struct *); -static int cg14_ioctl(struct inode *, struct file *, unsigned int, - unsigned long, struct fb_info *); +static int cg14_ioctl(struct fb_info *, unsigned int, unsigned long); static int cg14_pan_display(struct fb_var_screeninfo *, struct fb_info *); /* @@ -277,8 +276,7 @@ static int cg14_mmap(struct fb_info *info, struct file *file, struct vm_area_str par->iospace, vma); } -static int cg14_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg, struct fb_info *info) +static int cg14_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { struct cg14_par *par = (struct cg14_par *) info->par; struct cg14_regs __iomem *regs = par->regs; diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c index 9fcd89608ed..027f707fa5d 100644 --- a/drivers/video/cg3.c +++ b/drivers/video/cg3.c @@ -34,8 +34,7 @@ static int cg3_setcolreg(unsigned, unsigned, unsigned, unsigned, static int cg3_blank(int, struct fb_info *); static int cg3_mmap(struct fb_info *, struct file *, struct vm_area_struct *); -static int cg3_ioctl(struct inode *, struct file *, unsigned int, - unsigned long, struct fb_info *); +static int cg3_ioctl(struct fb_info *, unsigned int, unsigned long); /* * Frame buffer operations @@ -240,8 +239,7 @@ static int cg3_mmap(struct fb_info *info, struct file *file, struct vm_area_stru vma); } -static int cg3_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg, struct fb_info *info) +static int cg3_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { struct cg3_par *par = (struct cg3_par *) info->par; diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c index 050835e39aa..678e335d2b0 100644 --- a/drivers/video/cg6.c +++ b/drivers/video/cg6.c @@ -37,8 +37,7 @@ static void cg6_imageblit(struct fb_info *, const struct fb_image *); static void cg6_fillrect(struct fb_info *, const struct fb_fillrect *); static int cg6_sync(struct fb_info *); static int cg6_mmap(struct fb_info *, struct file *, struct vm_area_struct *); -static int cg6_ioctl(struct inode *, struct file *, unsigned int, - unsigned long, struct fb_info *); +static int cg6_ioctl(struct fb_info *, unsigned int, unsigned long); /* * Frame buffer operations @@ -534,8 +533,7 @@ static int cg6_mmap(struct fb_info *info, struct file *file, struct vm_area_stru vma); } -static int cg6_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg, struct fb_info *info) +static int cg6_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { struct cg6_par *par = (struct cg6_par *) info->par; diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 32a9b69becc..80c16fb61e1 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -957,7 +957,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, default: if (fb->fb_ioctl == NULL) return -EINVAL; - return fb->fb_ioctl(inode, file, cmd, arg, info); + return fb->fb_ioctl(info, cmd, arg); } } @@ -1107,7 +1107,7 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) default: if (fb->fb_compat_ioctl) - ret = fb->fb_compat_ioctl(file, cmd, arg, info); + ret = fb->fb_compat_ioctl(info, cmd, arg); break; } unlock_kernel(); diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c index c4870d559af..d096c129d20 100644 --- a/drivers/video/ffb.c +++ b/drivers/video/ffb.c @@ -38,8 +38,7 @@ static void ffb_fillrect(struct fb_info *, const struct fb_fillrect *); static void ffb_copyarea(struct fb_info *, const struct fb_copyarea *); static int ffb_sync(struct fb_info *); static int ffb_mmap(struct fb_info *, struct file *, struct vm_area_struct *); -static int ffb_ioctl(struct inode *, struct file *, unsigned int, - unsigned long, struct fb_info *); +static int ffb_ioctl(struct fb_info *, unsigned int, unsigned long); static int ffb_pan_display(struct fb_var_screeninfo *, struct fb_info *); /* @@ -848,8 +847,7 @@ static int ffb_mmap(struct fb_info *info, struct file *file, struct vm_area_stru 0, vma); } -static int ffb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg, struct fb_info *info) +static int ffb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { struct ffb_par *par = (struct ffb_par *) info->par; diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c index a5d813050db..ad416ae4759 100644 --- a/drivers/video/imsttfb.c +++ b/drivers/video/imsttfb.c @@ -1267,8 +1267,7 @@ imsttfb_cursor(struct fb_info *info, struct fb_cursor *cursor) #define FBIMSTT_GETIDXREG 0x545406 static int -imsttfb_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg, struct fb_info *info) +imsttfb_ioctl(struct fb_info *info, u_int cmd, u_long arg) { struct imstt_par *par = info->par; void __user *argp = (void __user *)arg; diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c index 0090544842f..6b8bd3cdf9c 100644 --- a/drivers/video/intelfb/intelfbdrv.c +++ b/drivers/video/intelfb/intelfbdrv.c @@ -157,9 +157,8 @@ static int intelfb_cursor(struct fb_info *info, static int intelfb_sync(struct fb_info *info); -static int intelfb_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, - struct fb_info *info); +static int intelfb_ioctl(struct fb_info *info, + unsigned int cmd, unsigned long arg); static int __devinit intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent); @@ -1380,8 +1379,7 @@ intelfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) /* When/if we have our own ioctls. */ static int -intelfb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg, struct fb_info *info) +intelfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { int retval = 0; diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c index bcd359b6d4f..477ad297de4 100644 --- a/drivers/video/kyro/fbdev.c +++ b/drivers/video/kyro/fbdev.c @@ -586,9 +586,8 @@ static int __init kyrofb_setup(char *options) } #endif -static int kyrofb_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, - struct fb_info *info) +static int kyrofb_ioctl(struct fb_info *info, + unsigned int cmd, unsigned long arg) { overlay_create ol_create; overlay_viewport_set ol_viewport_set; diff --git a/drivers/video/leo.c b/drivers/video/leo.c index 494287f8f8b..fb14787e13b 100644 --- a/drivers/video/leo.c +++ b/drivers/video/leo.c @@ -33,8 +33,7 @@ static int leo_setcolreg(unsigned, unsigned, unsigned, unsigned, static int leo_blank(int, struct fb_info *); static int leo_mmap(struct fb_info *, struct file *, struct vm_area_struct *); -static int leo_ioctl(struct inode *, struct file *, unsigned int, - unsigned long, struct fb_info *); +static int leo_ioctl(struct fb_info *, unsigned int, unsigned long); static int leo_pan_display(struct fb_var_screeninfo *, struct fb_info *); /* @@ -373,8 +372,7 @@ static int leo_mmap(struct fb_info *info, struct file *file, struct vm_area_stru vma); } -static int leo_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg, struct fb_info *info) +static int leo_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { struct leo_par *par = (struct leo_par *) info->par; diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 1e74f4cca53..4055ff6f5a8 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -865,9 +865,8 @@ static struct matrox_altout panellink_output = { .name = "Panellink output", }; -static int matroxfb_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, - struct fb_info *info) +static int matroxfb_ioctl(struct fb_info *info, + unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; MINFO_FROM_INFO(info); diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c index d52d7d825c4..27eb4bb4f89 100644 --- a/drivers/video/matrox/matroxfb_crtc2.c +++ b/drivers/video/matrox/matroxfb_crtc2.c @@ -419,11 +419,10 @@ static int matroxfb_dh_get_vblank(const struct matroxfb_dh_fb_info* m2info, stru return 0; } -static int matroxfb_dh_ioctl(struct inode* inode, - struct file* file, +static int matroxfb_dh_ioctl(struct fb_info *info, unsigned int cmd, - unsigned long arg, - struct fb_info* info) { + unsigned long arg) +{ #define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon)) MINFO_FROM(m2info->primary_dev); @@ -457,7 +456,7 @@ static int matroxfb_dh_ioctl(struct inode* inode, case MATROXFB_GET_OUTPUT_MODE: case MATROXFB_GET_ALL_OUTPUTS: { - return ACCESS_FBINFO(fbcon.fbops)->fb_ioctl(inode, file, cmd, arg, &ACCESS_FBINFO(fbcon)); + return ACCESS_FBINFO(fbcon.fbops)->fb_ioctl(&ACCESS_FBINFO(fbcon), cmd, arg); } case MATROXFB_SET_OUTPUT_CONNECTION: { diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c index b251e754e16..a1025e9606f 100644 --- a/drivers/video/p9100.c +++ b/drivers/video/p9100.c @@ -32,8 +32,7 @@ static int p9100_setcolreg(unsigned, unsigned, unsigned, unsigned, static int p9100_blank(int, struct fb_info *); static int p9100_mmap(struct fb_info *, struct file *, struct vm_area_struct *); -static int p9100_ioctl(struct inode *, struct file *, unsigned int, - unsigned long, struct fb_info *); +static int p9100_ioctl(struct fb_info *, unsigned int, unsigned long); /* * Frame buffer operations @@ -232,8 +231,8 @@ static int p9100_mmap(struct fb_info *info, struct file *file, struct vm_area_st vma); } -static int p9100_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg, struct fb_info *info) +static int p9100_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg) { struct p9100_par *par = (struct p9100_par *) info->par; diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c index 2e11b601c48..0e78ddc8158 100644 --- a/drivers/video/pm3fb.c +++ b/drivers/video/pm3fb.c @@ -657,9 +657,7 @@ static void pm3fb_set_disp(const void *par, struct display *disp, static void pm3fb_detect(void); static int pm3fb_pan_display(const struct fb_var_screeninfo *var, struct fb_info_gen *info); -static int pm3fb_ioctl(struct inode *inode, struct file *file, - u_int cmd, u_long arg, int con, - struct fb_info *info); +static int pm3fb_ioctl(struct fb_info *info, u_int cmd, u_long arg); /* the struct that hold them together */ @@ -3438,9 +3436,7 @@ static int pm3fb_pan_display(const struct fb_var_screeninfo *var, return 0; } -static int pm3fb_ioctl(struct inode *inode, struct file *file, - u_int cmd, u_long arg, int con, - struct fb_info *info) +static int pm3fb_ioctl(struct fb_info *info, u_int cmd, u_long arg) { struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info; u32 cm, i; diff --git a/drivers/video/pmag-aa-fb.c b/drivers/video/pmag-aa-fb.c index 28d1fe5fe34..d92f352211e 100644 --- a/drivers/video/pmag-aa-fb.c +++ b/drivers/video/pmag-aa-fb.c @@ -299,8 +299,7 @@ static int aafb_set_cmap(struct fb_cmap *cmap, int kspc, int con, return -EINVAL; } -static int aafb_ioctl(struct inode *inode, struct file *file, u32 cmd, - unsigned long arg, int con, struct fb_info *info) +static int aafb_ioctl(struct fb_info *info, u32 cmd, unsigned long arg) { /* TODO: Not yet implemented */ return -ENOIOCTLCMD; diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c index 600318f708f..db9fb9074db 100644 --- a/drivers/video/radeonfb.c +++ b/drivers/video/radeonfb.c @@ -1497,8 +1497,8 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var, } -static int radeonfb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg, struct fb_info *info) +static int radeonfb_ioctl (struct fb_info *info, unsigned int cmd, + unsigned long arg) { struct radeonfb_info *rinfo = (struct radeonfb_info *) info; unsigned int tmp; diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index dea1a46c67c..8adf5bf91ee 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c @@ -1743,13 +1743,14 @@ sisfb_blank(int blank, struct fb_info *info) /* ----------- FBDev related routines for all series ---------- */ -static int -sisfb_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - int con, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) +static int sisfb_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg) +#else +static int sisfb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, + struct fb_info *info) #endif - struct fb_info *info) { struct sis_video_info *ivideo = (struct sis_video_info *)info->par; struct sis_memreq sismemreq; @@ -1924,19 +1925,6 @@ sisfb_ioctl(struct inode *inode, struct file *file, return 0; } -#ifdef SIS_NEW_CONFIG_COMPAT -static long -sisfb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg, struct fb_info *info) -{ - int ret; - - lock_kernel(); - ret = sisfb_ioctl(NULL, f, cmd, arg, info); - unlock_kernel(); - return ret; -} -#endif - static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) { @@ -2007,7 +1995,7 @@ static struct fb_ops sisfb_ops = { #endif .fb_sync = fbcon_sis_sync, #ifdef SIS_NEW_CONFIG_COMPAT - .fb_compat_ioctl= sisfb_compat_ioctl, + .fb_compat_ioctl= sisfb_ioctl, #endif .fb_ioctl = sisfb_ioctl }; diff --git a/drivers/video/sis/sis_main.h b/drivers/video/sis/sis_main.h index 445bcbba03a..70b6df371b8 100644 --- a/drivers/video/sis/sis_main.h +++ b/drivers/video/sis/sis_main.h @@ -727,9 +727,14 @@ static int sisfb_ioctl(struct inode *inode, struct file *file, #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) +static int sisfb_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg); +#else static int sisfb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg, struct fb_info *info); +#endif static int sisfb_set_par(struct fb_info *info); static int sisfb_blank(int blank, struct fb_info *info); diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c index 8a5ce210bb2..99921df3547 100644 --- a/drivers/video/sstfb.c +++ b/drivers/video/sstfb.c @@ -771,8 +771,7 @@ static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, return 0; } -static int sstfb_ioctl(struct inode *inode, struct file *file, - u_int cmd, u_long arg, struct fb_info *info ) +static int sstfb_ioctl(struct fb_info *info, u_int cmd, u_long arg) { struct sstfb_par *par = info->par; struct pci_dev *sst_dev = par->dev; diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c index 2b27b447400..cb940771ec5 100644 --- a/drivers/video/tcx.c +++ b/drivers/video/tcx.c @@ -34,8 +34,7 @@ static int tcx_setcolreg(unsigned, unsigned, unsigned, unsigned, static int tcx_blank(int, struct fb_info *); static int tcx_mmap(struct fb_info *, struct file *, struct vm_area_struct *); -static int tcx_ioctl(struct inode *, struct file *, unsigned int, - unsigned long, struct fb_info *); +static int tcx_ioctl(struct fb_info *, unsigned int, unsigned long); static int tcx_pan_display(struct fb_var_screeninfo *, struct fb_info *); /* @@ -312,8 +311,8 @@ static int tcx_mmap(struct fb_info *info, struct file *file, struct vm_area_stru vma); } -static int tcx_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg, struct fb_info *info) +static int tcx_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg) { struct tcx_par *par = (struct tcx_par *) info->par; diff --git a/include/linux/fb.h b/include/linux/fb.h index a973be2cfe6..6da8a80a266 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -608,12 +608,12 @@ struct fb_ops { int (*fb_sync)(struct fb_info *info); /* perform fb specific ioctl (optional) */ - int (*fb_ioctl)(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg, struct fb_info *info); + int (*fb_ioctl)(struct fb_info *info, unsigned int cmd, + unsigned long arg); /* Handle 32bit compat ioctl (optional) */ - long (*fb_compat_ioctl)(struct file *f, unsigned cmd, unsigned long arg, - struct fb_info *info); + int (*fb_compat_ioctl)(struct fb_info *info, unsigned cmd, + unsigned long arg); /* perform fb specific mmap */ int (*fb_mmap)(struct fb_info *info, struct file *file, struct vm_area_struct *vma); -- GitLab From 216d526c89d144928f095f2800bc6c67e968d628 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 14 Jan 2006 13:21:25 -0800 Subject: [PATCH 302/465] [PATCH] fbdev: Sanitize ->fb_mmap prototype No need for a file argument. If we'd really need it it's in vma->vm_file already. gbefb and sgivwfb used to set vma->vm_file to the file argument, but the kernel alrady did that. Signed-off-by: Christoph Hellwig Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/68328fb.c | 6 ++---- drivers/video/acornfb.c | 2 +- drivers/video/amba-clcd.c | 2 +- drivers/video/aty/atyfb_base.c | 4 ++-- drivers/video/au1100fb.c | 2 +- drivers/video/bw2.c | 4 ++-- drivers/video/cg14.c | 4 ++-- drivers/video/cg3.c | 4 ++-- drivers/video/cg6.c | 4 ++-- drivers/video/controlfb.c | 4 ++-- drivers/video/fbmem.c | 2 +- drivers/video/ffb.c | 4 ++-- drivers/video/gbefb.c | 3 +-- drivers/video/igafb.c | 2 +- drivers/video/leo.c | 4 ++-- drivers/video/p9100.c | 4 ++-- drivers/video/pxafb.c | 2 +- drivers/video/sa1100fb.c | 2 +- drivers/video/sgivwfb.c | 5 ++--- drivers/video/tcx.c | 4 ++-- drivers/video/vfb.c | 4 ++-- include/linux/fb.h | 2 +- 22 files changed, 35 insertions(+), 39 deletions(-) diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c index 3b0ddc55236..78488bb41ae 100644 --- a/drivers/video/68328fb.c +++ b/drivers/video/68328fb.c @@ -102,8 +102,7 @@ static int mc68x328fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info); static int mc68x328fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); -static int mc68x328fb_mmap(struct fb_info *info, struct file *file, - struct vm_area_struct *vma); +static int mc68x328fb_mmap(struct fb_info *info, struct vm_area_struct *vma); static struct fb_ops mc68x328fb_ops = { .fb_check_var = mc68x328fb_check_var, @@ -398,8 +397,7 @@ static int mc68x328fb_pan_display(struct fb_var_screeninfo *var, * Most drivers don't need their own mmap function */ -static int mc68x328fb_mmap(struct fb_info *info, struct file *file, - struct vm_area_struct *vma) +static int mc68x328fb_mmap(struct fb_info *info, struct vm_area_struct *vma) { #ifndef MMU /* this is uClinux (no MMU) specific code */ diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c index 750cebb1830..b058273527b 100644 --- a/drivers/video/acornfb.c +++ b/drivers/video/acornfb.c @@ -883,7 +883,7 @@ acornfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) * Note that we are entered with the kernel locked. */ static int -acornfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) +acornfb_mmap(struct fb_info *info, struct vm_area_struct *vma) { unsigned long off, start; u32 len; diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c index 0da4083ba90..b2187175d03 100644 --- a/drivers/video/amba-clcd.c +++ b/drivers/video/amba-clcd.c @@ -307,7 +307,7 @@ static int clcdfb_blank(int blank_mode, struct fb_info *info) return 0; } -static int clcdfb_mmap(struct fb_info *info, struct file *file, +static int clcdfb_mmap(struct fb_info *info, struct vm_area_struct *vma) { struct clcd_fb *fb = to_clcd(info); diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 75b463ad4c7..485be386a8f 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -243,7 +243,7 @@ extern void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) extern void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area); extern void atyfb_imageblit(struct fb_info *info, const struct fb_image *image); #ifdef __sparc__ -static int atyfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma); +static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma); #endif static int atyfb_sync(struct fb_info *info); @@ -1843,7 +1843,7 @@ static int atyfb_sync(struct fb_info *info) } #ifdef __sparc__ -static int atyfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) +static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma) { struct atyfb_par *par = (struct atyfb_par *) info->par; unsigned int size, page, map_size = 0; diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c index a5129806172..2406899f120 100644 --- a/drivers/video/au1100fb.c +++ b/drivers/video/au1100fb.c @@ -379,7 +379,7 @@ void au1100fb_fb_rotate(struct fb_info *fbi, int angle) * Map video memory in user space. We don't use the generic fb_mmap method mainly * to allow the use of the TLB streaming flag (CCA=6) */ -int au1100fb_fb_mmap(struct fb_info *fbi, struct file *file, struct vm_area_struct *vma) +int au1100fb_fb_mmap(struct fb_info *fbi, struct vm_area_struct *vma) { struct au1100fb_device *fbdev = to_au1100fb_device(fbi); unsigned int len; diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c index 641a6c1fbf2..c029db4646f 100644 --- a/drivers/video/bw2.c +++ b/drivers/video/bw2.c @@ -35,7 +35,7 @@ static int bw2_blank(int, struct fb_info *); -static int bw2_mmap(struct fb_info *, struct file *, struct vm_area_struct *); +static int bw2_mmap(struct fb_info *, struct vm_area_struct *); static int bw2_ioctl(struct fb_info *, unsigned int, unsigned long); /* @@ -168,7 +168,7 @@ static struct sbus_mmap_map bw2_mmap_map[] = { { .size = 0 } }; -static int bw2_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) +static int bw2_mmap(struct fb_info *info, struct vm_area_struct *vma) { struct bw2_par *par = (struct bw2_par *)info->par; diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c index edb9936673c..63b6c79c8a0 100644 --- a/drivers/video/cg14.c +++ b/drivers/video/cg14.c @@ -31,7 +31,7 @@ static int cg14_setcolreg(unsigned, unsigned, unsigned, unsigned, unsigned, struct fb_info *); -static int cg14_mmap(struct fb_info *, struct file *, struct vm_area_struct *); +static int cg14_mmap(struct fb_info *, struct vm_area_struct *); static int cg14_ioctl(struct fb_info *, unsigned int, unsigned long); static int cg14_pan_display(struct fb_var_screeninfo *, struct fb_info *); @@ -267,7 +267,7 @@ static int cg14_setcolreg(unsigned regno, return 0; } -static int cg14_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) +static int cg14_mmap(struct fb_info *info, struct vm_area_struct *vma) { struct cg14_par *par = (struct cg14_par *) info->par; diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c index 027f707fa5d..3de6e1b5ab2 100644 --- a/drivers/video/cg3.c +++ b/drivers/video/cg3.c @@ -33,7 +33,7 @@ static int cg3_setcolreg(unsigned, unsigned, unsigned, unsigned, unsigned, struct fb_info *); static int cg3_blank(int, struct fb_info *); -static int cg3_mmap(struct fb_info *, struct file *, struct vm_area_struct *); +static int cg3_mmap(struct fb_info *, struct vm_area_struct *); static int cg3_ioctl(struct fb_info *, unsigned int, unsigned long); /* @@ -229,7 +229,7 @@ static struct sbus_mmap_map cg3_mmap_map[] = { { .size = 0 } }; -static int cg3_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) +static int cg3_mmap(struct fb_info *info, struct vm_area_struct *vma) { struct cg3_par *par = (struct cg3_par *)info->par; diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c index 678e335d2b0..7aab91ead68 100644 --- a/drivers/video/cg6.c +++ b/drivers/video/cg6.c @@ -36,7 +36,7 @@ static int cg6_blank(int, struct fb_info *); static void cg6_imageblit(struct fb_info *, const struct fb_image *); static void cg6_fillrect(struct fb_info *, const struct fb_fillrect *); static int cg6_sync(struct fb_info *); -static int cg6_mmap(struct fb_info *, struct file *, struct vm_area_struct *); +static int cg6_mmap(struct fb_info *, struct vm_area_struct *); static int cg6_ioctl(struct fb_info *, unsigned int, unsigned long); /* @@ -523,7 +523,7 @@ static struct sbus_mmap_map cg6_mmap_map[] = { { .size = 0 } }; -static int cg6_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) +static int cg6_mmap(struct fb_info *info, struct vm_area_struct *vma) { struct cg6_par *par = (struct cg6_par *)info->par; diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c index 03798e9c882..655301a8671 100644 --- a/drivers/video/controlfb.c +++ b/drivers/video/controlfb.c @@ -128,7 +128,7 @@ static int controlfb_pan_display(struct fb_var_screeninfo *var, static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info); static int controlfb_blank(int blank_mode, struct fb_info *info); -static int controlfb_mmap(struct fb_info *info, struct file *file, +static int controlfb_mmap(struct fb_info *info, struct vm_area_struct *vma); static int controlfb_set_par (struct fb_info *info); static int controlfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info); @@ -280,7 +280,7 @@ static int controlfb_pan_display(struct fb_var_screeninfo *var, * for controlfb. * Note there's no locking in here; it's done in fb_mmap() in fbmem.c. */ -static int controlfb_mmap(struct fb_info *info, struct file *file, +static int controlfb_mmap(struct fb_info *info, struct vm_area_struct *vma) { unsigned long off, start; diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 80c16fb61e1..d2dede6ed3e 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1135,7 +1135,7 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) if (fb->fb_mmap) { int res; lock_kernel(); - res = fb->fb_mmap(info, file, vma); + res = fb->fb_mmap(info, vma); unlock_kernel(); return res; } diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c index d096c129d20..9c9b21d469a 100644 --- a/drivers/video/ffb.c +++ b/drivers/video/ffb.c @@ -37,7 +37,7 @@ static void ffb_imageblit(struct fb_info *, const struct fb_image *); static void ffb_fillrect(struct fb_info *, const struct fb_fillrect *); static void ffb_copyarea(struct fb_info *, const struct fb_copyarea *); static int ffb_sync(struct fb_info *); -static int ffb_mmap(struct fb_info *, struct file *, struct vm_area_struct *); +static int ffb_mmap(struct fb_info *, struct vm_area_struct *); static int ffb_ioctl(struct fb_info *, unsigned int, unsigned long); static int ffb_pan_display(struct fb_var_screeninfo *, struct fb_info *); @@ -838,7 +838,7 @@ static struct sbus_mmap_map ffb_mmap_map[] = { { .size = 0 } }; -static int ffb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) +static int ffb_mmap(struct fb_info *info, struct vm_area_struct *vma) { struct ffb_par *par = (struct ffb_par *)info->par; diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c index d744c51807b..38d22729b12 100644 --- a/drivers/video/gbefb.c +++ b/drivers/video/gbefb.c @@ -979,7 +979,7 @@ static int gbefb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) return 0; } -static int gbefb_mmap(struct fb_info *info, struct file *file, +static int gbefb_mmap(struct fb_info *info, struct vm_area_struct *vma) { unsigned long size = vma->vm_end - vma->vm_start; @@ -1000,7 +1000,6 @@ static int gbefb_mmap(struct fb_info *info, struct file *file, pgprot_fb(pgprot_val(vma->vm_page_prot)); vma->vm_flags |= VM_IO | VM_RESERVED; - vma->vm_file = file; /* look for the starting tile */ tile = &gbe_tiles.cpu[offset >> TILE_SHIFT]; diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c index e326f44f652..6b88050d21b 100644 --- a/drivers/video/igafb.c +++ b/drivers/video/igafb.c @@ -219,7 +219,7 @@ static void iga_blank_border(struct iga_par *par) } #ifdef __sparc__ -static int igafb_mmap(struct fb_info *info, struct file *file, +static int igafb_mmap(struct fb_info *info, struct vm_area_struct *vma) { struct iga_par *par = (struct iga_par *)info->par; diff --git a/drivers/video/leo.c b/drivers/video/leo.c index fb14787e13b..a23cfdb9d82 100644 --- a/drivers/video/leo.c +++ b/drivers/video/leo.c @@ -32,7 +32,7 @@ static int leo_setcolreg(unsigned, unsigned, unsigned, unsigned, unsigned, struct fb_info *); static int leo_blank(int, struct fb_info *); -static int leo_mmap(struct fb_info *, struct file *, struct vm_area_struct *); +static int leo_mmap(struct fb_info *, struct vm_area_struct *); static int leo_ioctl(struct fb_info *, unsigned int, unsigned long); static int leo_pan_display(struct fb_var_screeninfo *, struct fb_info *); @@ -362,7 +362,7 @@ static struct sbus_mmap_map leo_mmap_map[] = { { .size = 0 } }; -static int leo_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) +static int leo_mmap(struct fb_info *info, struct vm_area_struct *vma) { struct leo_par *par = (struct leo_par *)info->par; diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c index a1025e9606f..0d195750535 100644 --- a/drivers/video/p9100.c +++ b/drivers/video/p9100.c @@ -31,7 +31,7 @@ static int p9100_setcolreg(unsigned, unsigned, unsigned, unsigned, unsigned, struct fb_info *); static int p9100_blank(int, struct fb_info *); -static int p9100_mmap(struct fb_info *, struct file *, struct vm_area_struct *); +static int p9100_mmap(struct fb_info *, struct vm_area_struct *); static int p9100_ioctl(struct fb_info *, unsigned int, unsigned long); /* @@ -221,7 +221,7 @@ static struct sbus_mmap_map p9100_mmap_map[] = { { 0, 0, 0 } }; -static int p9100_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) +static int p9100_mmap(struct fb_info *info, struct vm_area_struct *vma) { struct p9100_par *par = (struct p9100_par *)info->par; diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 9fc10b9e6f5..53ad61f1038 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -395,7 +395,7 @@ static int pxafb_blank(int blank, struct fb_info *info) return 0; } -static int pxafb_mmap(struct fb_info *info, struct file *file, +static int pxafb_mmap(struct fb_info *info, struct vm_area_struct *vma) { struct pxafb_info *fbi = (struct pxafb_info *)info; diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index 087e58689e4..8a893ce7040 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c @@ -815,7 +815,7 @@ static int sa1100fb_blank(int blank, struct fb_info *info) return 0; } -static int sa1100fb_mmap(struct fb_info *info, struct file *file, +static int sa1100fb_mmap(struct fb_info *info, struct vm_area_struct *vma) { struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c index 7054660767e..2e6df1fcb2b 100644 --- a/drivers/video/sgivwfb.c +++ b/drivers/video/sgivwfb.c @@ -115,7 +115,7 @@ static int sgivwfb_set_par(struct fb_info *info); static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info); -static int sgivwfb_mmap(struct fb_info *info, struct file *file, +static int sgivwfb_mmap(struct fb_info *info, struct vm_area_struct *vma); static struct fb_ops sgivwfb_ops = { @@ -706,7 +706,7 @@ static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green, return 0; } -static int sgivwfb_mmap(struct fb_info *info, struct file *file, +static int sgivwfb_mmap(struct fb_info *info, struct vm_area_struct *vma) { unsigned long size = vma->vm_end - vma->vm_start; @@ -723,7 +723,6 @@ static int sgivwfb_mmap(struct fb_info *info, struct file *file, if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT, size, vma->vm_page_prot)) return -EAGAIN; - vma->vm_file = file; printk(KERN_DEBUG "sgivwfb: mmap framebuffer P(%lx)->V(%lx)\n", offset, vma->vm_start); return 0; diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c index cb940771ec5..95b918229d9 100644 --- a/drivers/video/tcx.c +++ b/drivers/video/tcx.c @@ -33,7 +33,7 @@ static int tcx_setcolreg(unsigned, unsigned, unsigned, unsigned, unsigned, struct fb_info *); static int tcx_blank(int, struct fb_info *); -static int tcx_mmap(struct fb_info *, struct file *, struct vm_area_struct *); +static int tcx_mmap(struct fb_info *, struct vm_area_struct *); static int tcx_ioctl(struct fb_info *, unsigned int, unsigned long); static int tcx_pan_display(struct fb_var_screeninfo *, struct fb_info *); @@ -301,7 +301,7 @@ static struct sbus_mmap_map __tcx_mmap_map[TCX_MMAP_ENTRIES] = { { .size = 0 } }; -static int tcx_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) +static int tcx_mmap(struct fb_info *info, struct vm_area_struct *vma) { struct tcx_par *par = (struct tcx_par *)info->par; diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c index ffa1ad47422..53208cb5839 100644 --- a/drivers/video/vfb.c +++ b/drivers/video/vfb.c @@ -81,7 +81,7 @@ static int vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info); static int vfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); -static int vfb_mmap(struct fb_info *info, struct file *file, +static int vfb_mmap(struct fb_info *info, struct vm_area_struct *vma); static struct fb_ops vfb_ops = { @@ -368,7 +368,7 @@ static int vfb_pan_display(struct fb_var_screeninfo *var, * Most drivers don't need their own mmap function */ -static int vfb_mmap(struct fb_info *info, struct file *file, +static int vfb_mmap(struct fb_info *info, struct vm_area_struct *vma) { return -EINVAL; diff --git a/include/linux/fb.h b/include/linux/fb.h index 6da8a80a266..2cb19e6503a 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -616,7 +616,7 @@ struct fb_ops { unsigned long arg); /* perform fb specific mmap */ - int (*fb_mmap)(struct fb_info *info, struct file *file, struct vm_area_struct *vma); + int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma); /* save current hardware state */ void (*fb_save_state)(struct fb_info *info); -- GitLab From 9eb8ef7479b6df59645af5d89d293727b521975e Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Sat, 14 Jan 2006 13:21:26 -0800 Subject: [PATCH 303/465] [PATCH] fbdev: Update maintainers list Update maintainers list. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 71693c5c313..513f3b6c35b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1300,6 +1300,12 @@ M: ttb@tentacle.dhs.org and rml@novell.com L: linux-kernel@vger.kernel.org S: Maintained +INTEL FRAMEBUFFER DRIVER (excluding 810 and 815) +P: Sylvain Meyer +M: sylvain.meyer@worldonline.fr +L: linux-fbdev-devel@lists.sourceforge.net +S: Maintained + INTEL 810/815 FRAMEBUFFER DRIVER P: Antonino Daplas M: adaplas@pol.net @@ -1889,11 +1895,11 @@ W: http://linux-ntfs.sf.net/ T: git kernel.org:/pub/scm/linux/kernel/git/aia21/ntfs-2.6.git S: Maintained -NVIDIA (RIVA) FRAMEBUFFER DRIVER -P: Ani Joshi -M: ajoshi@shell.unixbox.com -L: linux-nvidia@lists.surfsouth.com -S: Maintained +NVIDIA (rivafb and nvidiafb) FRAMEBUFFER DRIVER +P: Antonino Daplas +M: adaplas@pol.net +L: linux-fbdev-devel@lists.sourceforge.net +S: Maintained ORACLE CLUSTER FILESYSTEM 2 (OCFS2) P: Mark Fasheh @@ -2188,6 +2194,12 @@ L: rtl@rtlinux.org W: www.rtlinux.org S: Maintained +S3 SAVAGE FRAMEBUFFER DRIVER +P: Antonino Daplas +M: adaplas@pol.net +L: linux-fbdev-devel@lists.sourceforge.net +S: Maintained + S390 P: Martin Schwidefsky M: schwidefsky@de.ibm.com -- GitLab From 40fc55cb69c0386504ab5184e9bea0a7aecb2bd3 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 14 Jan 2006 13:21:28 -0800 Subject: [PATCH 304/465] [PATCH] Make __always_inline actually force always inlining This patch is the first in a series that tries to optimize the kernel in terms of size (and thus cache behavior, both cpu and pagecache). This first patch changes __always_inline to be a forced inline instead of the "regular" inline it was on everything except alpha. This forced inline matches the intention of the define better as a matter of documentation. There is no change in behavior by this patch, since "inline" currently is mapped to a forced inline anyway. Signed-off-by: Ingo Molnar Signed-off-by: Arjan van de Ven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/compiler-gcc3.h | 1 + include/linux/compiler-gcc4.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/compiler-gcc3.h b/include/linux/compiler-gcc3.h index 4209082ee93..1698b845761 100644 --- a/include/linux/compiler-gcc3.h +++ b/include/linux/compiler-gcc3.h @@ -13,3 +13,4 @@ #define __must_check __attribute__((warn_unused_result)) #endif +#define __always_inline inline __attribute__((always_inline)) diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h index e913e9beaf6..8249115a1f7 100644 --- a/include/linux/compiler-gcc4.h +++ b/include/linux/compiler-gcc4.h @@ -6,4 +6,4 @@ #define __attribute_used__ __attribute__((__used__)) #define __must_check __attribute__((warn_unused_result)) #define __compiler_offsetof(a,b) __builtin_offsetof(a,b) - +#define __always_inline inline __attribute__((always_inline)) -- GitLab From 9ab34fe76114b9538bfcaf3a9d112dee0feb5f17 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 14 Jan 2006 13:21:29 -0800 Subject: [PATCH 305/465] [PATCH] enable unit-at-a-time optimisations for gcc4 Allow gcc4 compilers to optimize unit-at-a-time. This flag enables gcc to "see" the entire C file before making optimisation decisions such as inline, which results in gcc making better decisions. One of the immediate effects of this is that static functions that are used only once now get inlined. gcc 3.4 has this flag as well, however gcc 3.x have a problem with inlining and stacks and as a result, enabling this flag there would cause excessive and unacceptable stack use. This problem is fixed in the gcc 4.x series. The x86-64 architecture already enables this feature so it's well tested already. Signed-off-by: Ingo Molnar Signed-off-by: Arjan van de Ven Acked-by: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/i386/Makefile b/arch/i386/Makefile index d3c0409d201..bd2d53a9dd2 100644 --- a/arch/i386/Makefile +++ b/arch/i386/Makefile @@ -42,9 +42,9 @@ include $(srctree)/arch/i386/Makefile.cpu cflags-$(CONFIG_REGPARM) += $(shell if [ $(call cc-version) -ge 0300 ] ; then \ echo "-mregparm=3"; fi ;) -# Disable unit-at-a-time mode, it makes gcc use a lot more stack -# due to the lack of sharing of stacklots. -CFLAGS += $(call cc-option,-fno-unit-at-a-time) +# Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use +# a lot more stack due to the lack of sharing of stacklots: +CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then echo $(call cc-option,-fno-unit-at-a-time); fi ;) CFLAGS += $(cflags-y) -- GitLab From 652050aec936fdd70ed9cbce1cd1ef30a7c9d117 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 14 Jan 2006 13:21:30 -0800 Subject: [PATCH 306/465] [PATCH] mark several functions __always_inline Arjan van de Ven Mark a number of functions as 'must inline'. The functions affected by this patch need to be inlined because they use knowledge that their arguments are constant so that most of the function optimizes away. At this point this patch does not change behavior, it's for documentation only (and for future patches in the inline series) Signed-off-by: Ingo Molnar Signed-off-by: Arjan van de Ven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-i386/bitops.h | 2 +- include/asm-i386/current.h | 2 +- include/asm-i386/string.h | 8 ++++---- include/asm-i386/uaccess.h | 8 ++++---- include/asm-x86_64/fixmap.h | 2 +- include/asm-x86_64/uaccess.h | 6 +++--- include/linux/mm.h | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/include/asm-i386/bitops.h b/include/asm-i386/bitops.h index fe0819fe9c6..88e6ca248cd 100644 --- a/include/asm-i386/bitops.h +++ b/include/asm-i386/bitops.h @@ -247,7 +247,7 @@ static inline int test_and_change_bit(int nr, volatile unsigned long* addr) static int test_bit(int nr, const volatile void * addr); #endif -static inline int constant_test_bit(int nr, const volatile unsigned long *addr) +static __always_inline int constant_test_bit(int nr, const volatile unsigned long *addr) { return ((1UL << (nr & 31)) & (addr[nr >> 5])) != 0; } diff --git a/include/asm-i386/current.h b/include/asm-i386/current.h index d97328951f5..3cbbecd7901 100644 --- a/include/asm-i386/current.h +++ b/include/asm-i386/current.h @@ -5,7 +5,7 @@ struct task_struct; -static inline struct task_struct * get_current(void) +static __always_inline struct task_struct * get_current(void) { return current_thread_info()->task; } diff --git a/include/asm-i386/string.h b/include/asm-i386/string.h index 02c8f5d2206..bb5f88a27f7 100644 --- a/include/asm-i386/string.h +++ b/include/asm-i386/string.h @@ -201,7 +201,7 @@ __asm__ __volatile__( return __res; } -static inline void * __memcpy(void * to, const void * from, size_t n) +static __always_inline void * __memcpy(void * to, const void * from, size_t n) { int d0, d1, d2; __asm__ __volatile__( @@ -223,7 +223,7 @@ return (to); * This looks ugly, but the compiler can optimize it totally, * as the count is constant. */ -static inline void * __constant_memcpy(void * to, const void * from, size_t n) +static __always_inline void * __constant_memcpy(void * to, const void * from, size_t n) { long esi, edi; if (!n) return to; @@ -367,7 +367,7 @@ return s; * things 32 bits at a time even when we don't know the size of the * area at compile-time.. */ -static inline void * __constant_c_memset(void * s, unsigned long c, size_t count) +static __always_inline void * __constant_c_memset(void * s, unsigned long c, size_t count) { int d0, d1; __asm__ __volatile__( @@ -416,7 +416,7 @@ extern char *strstr(const char *cs, const char *ct); * This looks horribly ugly, but the compiler can optimize it totally, * as we by now know that both pattern and count is constant.. */ -static inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count) +static __always_inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count) { switch (count) { case 0: diff --git a/include/asm-i386/uaccess.h b/include/asm-i386/uaccess.h index 89ab7e2bc5a..3f1337c3420 100644 --- a/include/asm-i386/uaccess.h +++ b/include/asm-i386/uaccess.h @@ -411,7 +411,7 @@ unsigned long __must_check __copy_from_user_ll(void *to, * Returns number of bytes that could not be copied. * On success, this will be zero. */ -static inline unsigned long __must_check +static __always_inline unsigned long __must_check __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n) { if (__builtin_constant_p(n)) { @@ -432,7 +432,7 @@ __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n) return __copy_to_user_ll(to, from, n); } -static inline unsigned long __must_check +static __always_inline unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n) { might_sleep(); @@ -456,7 +456,7 @@ __copy_to_user(void __user *to, const void *from, unsigned long n) * If some data could not be copied, this function will pad the copied * data to the requested size using zero bytes. */ -static inline unsigned long +static __always_inline unsigned long __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) { if (__builtin_constant_p(n)) { @@ -477,7 +477,7 @@ __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) return __copy_from_user_ll(to, from, n); } -static inline unsigned long +static __always_inline unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n) { might_sleep(); diff --git a/include/asm-x86_64/fixmap.h b/include/asm-x86_64/fixmap.h index a582cfcf223..7b286bd21d1 100644 --- a/include/asm-x86_64/fixmap.h +++ b/include/asm-x86_64/fixmap.h @@ -76,7 +76,7 @@ extern void __this_fixmap_does_not_exist(void); * directly without translation, we catch the bug with a NULL-deference * kernel oops. Illegal ranges of incoming indices are caught too. */ -static inline unsigned long fix_to_virt(const unsigned int idx) +static __always_inline unsigned long fix_to_virt(const unsigned int idx) { /* * this branch gets completely eliminated after inlining, diff --git a/include/asm-x86_64/uaccess.h b/include/asm-x86_64/uaccess.h index 2892c4b7a28..bddffcb591b 100644 --- a/include/asm-x86_64/uaccess.h +++ b/include/asm-x86_64/uaccess.h @@ -244,7 +244,7 @@ extern unsigned long copy_to_user(void __user *to, const void *from, unsigned le extern unsigned long copy_from_user(void *to, const void __user *from, unsigned len); extern unsigned long copy_in_user(void __user *to, const void __user *from, unsigned len); -static inline int __copy_from_user(void *dst, const void __user *src, unsigned size) +static __always_inline int __copy_from_user(void *dst, const void __user *src, unsigned size) { int ret = 0; if (!__builtin_constant_p(size)) @@ -273,7 +273,7 @@ static inline int __copy_from_user(void *dst, const void __user *src, unsigned s } } -static inline int __copy_to_user(void __user *dst, const void *src, unsigned size) +static __always_inline int __copy_to_user(void __user *dst, const void *src, unsigned size) { int ret = 0; if (!__builtin_constant_p(size)) @@ -305,7 +305,7 @@ static inline int __copy_to_user(void __user *dst, const void *src, unsigned siz } -static inline int __copy_in_user(void __user *dst, const void __user *src, unsigned size) +static __always_inline int __copy_in_user(void __user *dst, const void __user *src, unsigned size) { int ret = 0; if (!__builtin_constant_p(size)) diff --git a/include/linux/mm.h b/include/linux/mm.h index c643016499a..85854b86746 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -512,7 +512,7 @@ static inline void set_page_links(struct page *page, unsigned long zone, extern struct page *mem_map; #endif -static inline void *lowmem_page_address(struct page *page) +static __always_inline void *lowmem_page_address(struct page *page) { return __va(page_to_pfn(page) << PAGE_SHIFT); } -- GitLab From f16623569e2ec055b489462315f5296f153d119b Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sat, 14 Jan 2006 13:21:31 -0800 Subject: [PATCH 307/465] [PATCH] Mark some key VFS functions as __always_inline Mark a few VFS functions as mandatory inline (based on Al Viro's request); these must be inline due to stack usage issues during a recursive loop that happens during the recursive symlink resolution (symlink to a symlink to a symlink ..) This patch at this point does not change behavior and is for documentation purposes only (but this changes later in the series) Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/namei.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 7bde381fa49..33fb5bd34a8 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -486,7 +486,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s static int __emul_lookup_dentry(const char *, struct nameidata *); /* SMP-safe */ -static inline int +static __always_inline int walk_init_root(const char *name, struct nameidata *nd) { read_lock(¤t->fs->lock); @@ -504,7 +504,7 @@ walk_init_root(const char *name, struct nameidata *nd) return 1; } -static inline int __vfs_follow_link(struct nameidata *nd, const char *link) +static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *link) { int res = 0; char *name; @@ -544,7 +544,7 @@ struct path { struct dentry *dentry; }; -static inline int __do_follow_link(struct path *path, struct nameidata *nd) +static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd) { int error; void *cookie; @@ -690,7 +690,7 @@ int follow_down(struct vfsmount **mnt, struct dentry **dentry) return 0; } -static inline void follow_dotdot(struct nameidata *nd) +static __always_inline void follow_dotdot(struct nameidata *nd) { while(1) { struct vfsmount *parent; -- GitLab From ac893963030ad70e528dc23270d499d650546a38 Mon Sep 17 00:00:00 2001 From: Peter Osterlund Date: Sat, 14 Jan 2006 13:21:32 -0800 Subject: [PATCH 308/465] [PATCH] pktcdvd: un-inline some functions Un-inline two functions in the pktcdvd driver. This makes the compiled code 172 bytes smaller on my system. Signed-off-by: Peter Osterlund Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/pktcdvd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 51b7a5c5b77..93affeeef7b 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -247,7 +247,7 @@ static inline struct pkt_rb_node *pkt_rbtree_next(struct pkt_rb_node *node) return rb_entry(n, struct pkt_rb_node, rb_node); } -static inline void pkt_rbtree_erase(struct pktcdvd_device *pd, struct pkt_rb_node *node) +static void pkt_rbtree_erase(struct pktcdvd_device *pd, struct pkt_rb_node *node) { rb_erase(&node->rb_node, &pd->bio_queue); mempool_free(node, pd->rb_pool); @@ -315,7 +315,7 @@ static void pkt_rbtree_insert(struct pktcdvd_device *pd, struct pkt_rb_node *nod /* * Add a bio to a single linked list defined by its head and tail pointers. */ -static inline void pkt_add_list_last(struct bio *bio, struct bio **list_head, struct bio **list_tail) +static void pkt_add_list_last(struct bio *bio, struct bio **list_head, struct bio **list_tail) { bio->bi_next = NULL; if (*list_tail) { -- GitLab From a9df3d0f312f4b1aefec76ae5ee86cccbf7cd4e0 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 14 Jan 2006 13:21:33 -0800 Subject: [PATCH 309/465] [PATCH] When CONFIG_CC_OPTIMIZE_FOR_SIZE, allow gcc4 to control inlining If optimizing for size (CONFIG_CC_OPTIMIZE_FOR_SIZE), allow gcc4 compilers to decide what to inline and what not - instead of the kernel forcing gcc to inline all the time. This requires several places that require to be inlined to be marked as such, previous patches in this series do that. Signed-off-by: Ingo Molnar Signed-off-by: Arjan van de Ven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/feature-removal-schedule.txt | 9 +++++++++ include/linux/compiler-gcc4.h | 9 +++++++++ lib/Kconfig.debug | 14 ++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 9474501dd6c..b4a1ea76269 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -123,6 +123,15 @@ Who: Christoph Hellwig --------------------------- +What: CONFIG_FORCED_INLINING +When: June 2006 +Why: Config option is there to see if gcc is good enough. (in january + 2006). If it is, the behavior should just be the default. If it's not, + the option should just go away entirely. +Who: Arjan van de Ven + +--------------------------- + What: START_ARRAY ioctl for md When: July 2006 Files: drivers/md/md.c diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h index 8249115a1f7..6f5cc6f0e7a 100644 --- a/include/linux/compiler-gcc4.h +++ b/include/linux/compiler-gcc4.h @@ -3,6 +3,15 @@ /* These definitions are for GCC v4.x. */ #include +#ifdef CONFIG_FORCED_INLINING +# undef inline +# undef __inline__ +# undef __inline +# define inline inline __attribute__((always_inline)) +# define __inline__ __inline__ __attribute__((always_inline)) +# define __inline __inline __attribute__((always_inline)) +#endif + #define __attribute_used__ __attribute__((__used__)) #define __must_check __attribute__((warn_unused_result)) #define __compiler_offsetof(a,b) __builtin_offsetof(a,b) diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index a609235a517..a314e663d51 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -195,6 +195,20 @@ config FRAME_POINTER some architectures or if you use external debuggers. If you don't debug the kernel, you can say N. +config FORCED_INLINING + bool "Force gcc to inline functions marked 'inline'" + depends on DEBUG_KERNEL + default y + help + This option determines if the kernel forces gcc to inline the functions + developers have marked 'inline'. Doing so takes away freedom from gcc to + do what it thinks is best, which is desirable for the gcc 3.x series of + compilers. The gcc 4.x series have a rewritten inlining algorithm and + disabling this option will generate a smaller kernel there. Hopefully + this algorithm is so good that allowing gcc4 to make the decision can + become the default in the future, until then this option is there to + test gcc for this. + config RCU_TORTURE_TEST tristate "torture tests for RCU" depends on DEBUG_KERNEL -- GitLab From 4683b54c1dae749a0fb8d8ec46d84dd4fefe41d3 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sat, 14 Jan 2006 16:46:47 +1100 Subject: [PATCH 310/465] [PATCH] powerpc: Update pmac32_defconfig Signed-off-by: Paul Mackerras --- arch/powerpc/configs/pmac32_defconfig | 105 +++++++++++++++----------- 1 file changed, 60 insertions(+), 45 deletions(-) diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig index 398203bd98e..2ace57d1e33 100644 --- a/arch/powerpc/configs/pmac32_defconfig +++ b/arch/powerpc/configs/pmac32_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.15-rc5 -# Tue Dec 13 17:24:05 2005 +# Linux kernel version: 2.6.15 +# Sat Jan 14 16:26:08 2006 # # CONFIG_PPC64 is not set CONFIG_PPC32=y @@ -15,11 +15,15 @@ CONFIG_EARLY_PRINTK=y CONFIG_GENERIC_NVRAM=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +# CONFIG_PPC_UDBG_16550 is not set +# CONFIG_CRASH_DUMP is not set +# CONFIG_GENERIC_TBSYNC is not set # # Processor support # -CONFIG_6xx=y +CONFIG_CLASSIC32=y # CONFIG_PPC_52xx is not set # CONFIG_PPC_82xx is not set # CONFIG_PPC_83xx is not set @@ -28,6 +32,7 @@ CONFIG_6xx=y # CONFIG_8xx is not set # CONFIG_E200 is not set # CONFIG_E500 is not set +CONFIG_6xx=y CONFIG_PPC_FPU=y CONFIG_ALTIVEC=y CONFIG_PPC_STD_MMU=y @@ -53,17 +58,18 @@ CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # CONFIG_AUDIT is not set -CONFIG_HOTPLUG=y -CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y +CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y @@ -72,8 +78,10 @@ CONFIG_CC_ALIGN_FUNCTIONS=0 CONFIG_CC_ALIGN_LABELS=0 CONFIG_CC_ALIGN_LOOPS=0 CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_SLAB=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set # # Loadable module support @@ -113,13 +121,10 @@ CONFIG_PPC_MULTIPLATFORM=y # CONFIG_APUS is not set # CONFIG_PPC_CHRP is not set CONFIG_PPC_PMAC=y -CONFIG_PPC_OF=y CONFIG_MPIC=y # CONFIG_PPC_RTAS is not set # CONFIG_MMIO_NVRAM is not set -# CONFIG_CRASH_DUMP is not set CONFIG_PPC_MPC106=y -# CONFIG_GENERIC_TBSYNC is not set CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_TABLE=y # CONFIG_CPU_FREQ_DEBUG is not set @@ -195,6 +200,11 @@ CONFIG_CARDBUS=y # PC-card bridges # CONFIG_YENTA=m +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_TOSHIBA=y # CONFIG_PD6729 is not set # CONFIG_I82092 is not set CONFIG_PCCARD_NONSTATIC=m @@ -464,7 +474,7 @@ CONFIG_IEEE80211_CRYPT_TKIP=m # # CONFIG_STANDALONE is not set CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=m +CONFIG_FW_LOADER=y # CONFIG_DEBUG_DRIVER is not set # @@ -491,7 +501,7 @@ CONFIG_PROC_EVENTS=y # Block devices # # CONFIG_BLK_DEV_FD is not set -CONFIG_MAC_FLOPPY=y +CONFIG_MAC_FLOPPY=m # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set @@ -603,7 +613,7 @@ CONFIG_SCSI_CONSTANTS=y # SCSI Transport Attributes # CONFIG_SCSI_SPI_ATTRS=y -# CONFIG_SCSI_FC_ATTRS is not set +CONFIG_SCSI_FC_ATTRS=y # CONFIG_SCSI_ISCSI_ATTRS is not set # CONFIG_SCSI_SAS_ATTRS is not set @@ -645,12 +655,7 @@ CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set CONFIG_SCSI_QLA2XXX=y -# CONFIG_SCSI_QLA21XX is not set -# CONFIG_SCSI_QLA22XX is not set -# CONFIG_SCSI_QLA2300 is not set -# CONFIG_SCSI_QLA2322 is not set -# CONFIG_SCSI_QLA6312 is not set -# CONFIG_SCSI_QLA24XX is not set +# CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE is not set # CONFIG_SCSI_LPFC is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set @@ -658,7 +663,7 @@ CONFIG_SCSI_QLA2XXX=y # CONFIG_SCSI_DEBUG is not set CONFIG_SCSI_MESH=y CONFIG_SCSI_MESH_SYNC_RATE=5 -CONFIG_SCSI_MESH_RESET_DELAY_MS=1000 +CONFIG_SCSI_MESH_RESET_DELAY_MS=4000 CONFIG_SCSI_MAC53C94=y # @@ -727,7 +732,6 @@ CONFIG_IEEE1394_SBP2=m CONFIG_IEEE1394_ETH1394=m CONFIG_IEEE1394_DV1394=m CONFIG_IEEE1394_RAWIO=m -# CONFIG_IEEE1394_CMP is not set # # I2O device support @@ -740,7 +744,7 @@ CONFIG_IEEE1394_RAWIO=m CONFIG_ADB=y CONFIG_ADB_CUDA=y CONFIG_ADB_PMU=y -CONFIG_PMAC_APM_EMU=y +CONFIG_PMAC_APM_EMU=m CONFIG_PMAC_MEDIABAY=y CONFIG_PMAC_BACKLIGHT=y CONFIG_INPUT_ADBHID=y @@ -819,6 +823,7 @@ CONFIG_PCNET32=y # CONFIG_R8169 is not set # CONFIG_SIS190 is not set # CONFIG_SKGE is not set +# CONFIG_SKY2 is not set # CONFIG_SK98LIN is not set # CONFIG_VIA_VELOCITY is not set # CONFIG_TIGON3 is not set @@ -978,14 +983,14 @@ CONFIG_HW_CONSOLE=y CONFIG_SERIAL_8250=m # CONFIG_SERIAL_8250_CS is not set CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 # CONFIG_SERIAL_8250_EXTENDED is not set # # Non-8250 serial port support # CONFIG_SERIAL_CORE=m -# CONFIG_SERIAL_PMACZILOG is not set -# CONFIG_SERIAL_JSM is not set +CONFIG_SERIAL_PMACZILOG=m CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -1058,7 +1063,7 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_I801 is not set # CONFIG_I2C_I810 is not set # CONFIG_I2C_PIIX4 is not set -CONFIG_I2C_KEYWEST=m +CONFIG_I2C_POWERMAC=y # CONFIG_I2C_MPC is not set # CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_PARPORT_LIGHT is not set @@ -1160,7 +1165,6 @@ CONFIG_FB_ATY128=y CONFIG_FB_ATY=y CONFIG_FB_ATY_CT=y # CONFIG_FB_ATY_GENERIC_LCD is not set -# CONFIG_FB_ATY_XL_INIT is not set CONFIG_FB_ATY_GX=y # CONFIG_FB_SAVAGE is not set # CONFIG_FB_SIS is not set @@ -1169,7 +1173,6 @@ CONFIG_FB_ATY_GX=y CONFIG_FB_3DFX=y # CONFIG_FB_3DFX_ACCEL is not set # CONFIG_FB_VOODOO1 is not set -# CONFIG_FB_CYBLA is not set # CONFIG_FB_TRIDENT is not set # CONFIG_FB_VIRTUAL is not set @@ -1214,9 +1217,10 @@ CONFIG_SND_OSSEMUL=y CONFIG_SND_MIXER_OSS=m CONFIG_SND_PCM_OSS=m CONFIG_SND_SEQUENCER_OSS=y +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set -CONFIG_SND_GENERIC_DRIVER=y # # Generic devices @@ -1230,6 +1234,8 @@ CONFIG_SND_DUMMY=m # # PCI devices # +# CONFIG_SND_AD1889 is not set +# CONFIG_SND_ALS4000 is not set # CONFIG_SND_ALI5451 is not set # CONFIG_SND_ATIIXP is not set # CONFIG_SND_ATIIXP_MODEM is not set @@ -1238,45 +1244,44 @@ CONFIG_SND_DUMMY=m # CONFIG_SND_AU8830 is not set # CONFIG_SND_AZT3328 is not set # CONFIG_SND_BT87X is not set -# CONFIG_SND_CS46XX is not set +# CONFIG_SND_CA0106 is not set +# CONFIG_SND_CMIPCI is not set # CONFIG_SND_CS4281 is not set +# CONFIG_SND_CS46XX is not set # CONFIG_SND_EMU10K1 is not set # CONFIG_SND_EMU10K1X is not set -# CONFIG_SND_CA0106 is not set -# CONFIG_SND_KORG1212 is not set -# CONFIG_SND_MIXART is not set -# CONFIG_SND_NM256 is not set -# CONFIG_SND_RME32 is not set -# CONFIG_SND_RME96 is not set -# CONFIG_SND_RME9652 is not set -# CONFIG_SND_HDSP is not set -# CONFIG_SND_HDSPM is not set -# CONFIG_SND_TRIDENT is not set -# CONFIG_SND_YMFPCI is not set -# CONFIG_SND_AD1889 is not set -# CONFIG_SND_ALS4000 is not set -# CONFIG_SND_CMIPCI is not set # CONFIG_SND_ENS1370 is not set # CONFIG_SND_ENS1371 is not set # CONFIG_SND_ES1938 is not set # CONFIG_SND_ES1968 is not set -# CONFIG_SND_MAESTRO3 is not set # CONFIG_SND_FM801 is not set +# CONFIG_SND_HDA_INTEL is not set +# CONFIG_SND_HDSP is not set +# CONFIG_SND_HDSPM is not set # CONFIG_SND_ICE1712 is not set # CONFIG_SND_ICE1724 is not set # CONFIG_SND_INTEL8X0 is not set # CONFIG_SND_INTEL8X0M is not set +# CONFIG_SND_KORG1212 is not set +# CONFIG_SND_MAESTRO3 is not set +# CONFIG_SND_MIXART is not set +# CONFIG_SND_NM256 is not set +# CONFIG_SND_PCXHR is not set +# CONFIG_SND_RME32 is not set +# CONFIG_SND_RME96 is not set +# CONFIG_SND_RME9652 is not set # CONFIG_SND_SONICVIBES is not set +# CONFIG_SND_TRIDENT is not set # CONFIG_SND_VIA82XX is not set # CONFIG_SND_VIA82XX_MODEM is not set # CONFIG_SND_VX222 is not set -# CONFIG_SND_HDA_INTEL is not set +# CONFIG_SND_YMFPCI is not set # # ALSA PowerMac devices # CONFIG_SND_POWERMAC=m -# CONFIG_SND_POWERMAC_AUTO_DRC is not set +CONFIG_SND_POWERMAC_AUTO_DRC=y # # USB devices @@ -1336,6 +1341,7 @@ CONFIG_USB_PRINTER=m # may also be needed; see USB_STORAGE Help for more information # # CONFIG_USB_STORAGE is not set +# CONFIG_USB_LIBUSUAL is not set # # USB Input Devices @@ -1355,6 +1361,7 @@ CONFIG_USB_HIDINPUT=y # CONFIG_USB_YEALINK is not set # CONFIG_USB_XPAD is not set # CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_ATI_REMOTE2 is not set # CONFIG_USB_KEYSPAN_REMOTE is not set CONFIG_USB_APPLETOUCH=y @@ -1501,6 +1508,7 @@ CONFIG_FS_MBCACHE=y # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set # CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y @@ -1540,6 +1548,7 @@ CONFIG_TMPFS=y # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y CONFIG_RELAYFS_FS=m +# CONFIG_CONFIGFS_FS is not set # # Miscellaneous filesystems @@ -1670,12 +1679,13 @@ CONFIG_OPROFILE=y # Kernel hacking # # CONFIG_PRINTK_TIME is not set -CONFIG_DEBUG_KERNEL=y # CONFIG_MAGIC_SYSRQ is not set +CONFIG_DEBUG_KERNEL=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_MUTEXES is not set # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_KOBJECT is not set @@ -1688,6 +1698,11 @@ CONFIG_XMON=y CONFIG_XMON_DEFAULT=y # CONFIG_BDI_SWITCH is not set CONFIG_BOOTX_TEXT=y +# CONFIG_PPC_EARLY_DEBUG_LPAR is not set +# CONFIG_PPC_EARLY_DEBUG_G5 is not set +# CONFIG_PPC_EARLY_DEBUG_RTAS is not set +# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set +# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set # # Security options -- GitLab From e8625d463560198cff7cb3eb22886c47d728d501 Mon Sep 17 00:00:00 2001 From: Haren Myneni Date: Sat, 14 Jan 2006 13:48:25 -0800 Subject: [PATCH 311/465] [PATCH] powerpc: Kconfig changes for CRASH_DUMP Noticed in 2.6.15-git9 that CRASH_DUMP option is moved to top level. Moved CRASH_DUMP into "kernel options" next to KEXEC and this config option supports only for PPC64 at this time. Signed-off-by: Haren Myneni Signed-off-by: Paul Mackerras --- arch/powerpc/Kconfig | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 01feed0e2a1..df338c5cc91 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -78,17 +78,6 @@ config PPC_UDBG_16550 bool default n -config CRASH_DUMP - bool "kernel crash dumps (EXPERIMENTAL)" - depends on PPC_MULTIPLATFORM - depends on EXPERIMENTAL - help - Build a kernel suitable for use as a kdump capture kernel. - The kernel will be linked at a different address than normal, and - so can only be used for Kdump. - - Don't change this unless you know what you are doing. - config GENERIC_TBSYNC bool default y if PPC32 && SMP @@ -584,6 +573,16 @@ config KEXEC support. As of this writing the exact hardware interface is strongly in flux, so no good recommendation can be made. +config CRASH_DUMP + bool "kernel crash dumps (EXPERIMENTAL)" + depends on PPC_MULTIPLATFORM && PPC64 && EXPERIMENTAL + help + Build a kernel suitable for use as a kdump capture kernel. + The kernel will be linked at a different address than normal, and + so can only be used for Kdump. + + Don't change this unless you know what you are doing. + config EMBEDDEDBOOT bool depends on 8xx || 8260 -- GitLab From caf5b04c82f05c65843b2d7189845d6c3df5a41e Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 14 Jan 2006 22:08:28 -0800 Subject: [PATCH 312/465] x86: Work around compiler code generation bug with -Os Some versions of gcc generate incorrect code for the inet_check_attr() function, apparently due to a totally bogus index -> pointer comparison transformation. At least "gcc version 4.0.1 20050727 (Red Hat 4.0.1-5)" from FC4 is affected, possibly others too. This changes the function subtly so that the buggy gcc transformation doesn't trigger. Signed-off-by: Linus Torvalds --- net/ipv4/fib_frontend.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 5b25fc0d980..4e3d3811dea 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -289,13 +289,13 @@ static int inet_check_attr(struct rtmsg *r, struct rtattr **rta) { int i; - for (i=1; i<=RTA_MAX; i++) { - struct rtattr *attr = rta[i-1]; + for (i=1; i<=RTA_MAX; i++, rta++) { + struct rtattr *attr = *rta; if (attr) { if (RTA_PAYLOAD(attr) < 4) return -EINVAL; if (i != RTA_MULTIPATH && i != RTA_METRICS) - rta[i-1] = (struct rtattr*)RTA_DATA(attr); + *rta = (struct rtattr*)RTA_DATA(attr); } } return 0; -- GitLab From a7fdd90bc43e3e9cb08bc1b13650024d419b89e5 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sun, 15 Jan 2006 17:30:44 +1100 Subject: [PATCH 313/465] [PATCH] ppc: Remove powermac support from ARCH=ppc This makes it possible to build kernels for PReP and/or CHRP with ARCH=ppc by removing the (non-building) powermac support. It's now also possible to select PReP and CHRP independently. Powermac users should now build with ARCH=powerpc instead of ARCH=ppc. (This does mean that it is no longer possible to build a 32-bit kernel for a G5.) Signed-off-by: Paul Mackerras --- arch/ppc/Kconfig | 73 +- arch/ppc/boot/Makefile | 2 +- arch/ppc/boot/openfirmware/Makefile | 96 +- arch/ppc/boot/openfirmware/coffmain.c | 101 - arch/ppc/boot/openfirmware/newworldmain.c | 94 - arch/ppc/kernel/Makefile | 2 - arch/ppc/kernel/misc.S | 72 - arch/ppc/kernel/pci.c | 240 +- arch/ppc/kernel/ppc_ksyms.c | 9 - arch/ppc/kernel/setup.c | 34 +- arch/ppc/kernel/traps.c | 13 +- arch/ppc/mm/init.c | 29 - arch/ppc/platforms/Makefile | 11 +- arch/ppc/platforms/chrp_pci.c | 2 +- arch/ppc/platforms/chrp_setup.c | 73 +- arch/ppc/platforms/chrp_time.c | 64 +- arch/ppc/platforms/pmac_backlight.c | 202 -- arch/ppc/platforms/pmac_cache.S | 359 --- arch/ppc/platforms/pmac_cpufreq.c | 735 ----- arch/ppc/platforms/pmac_feature.c | 3023 --------------------- arch/ppc/platforms/pmac_low_i2c.c | 511 ---- arch/ppc/platforms/pmac_nvram.c | 584 ---- arch/ppc/platforms/pmac_pci.c | 1124 -------- arch/ppc/platforms/pmac_pic.c | 693 ----- arch/ppc/platforms/pmac_pic.h | 11 - arch/ppc/platforms/pmac_setup.c | 745 ----- arch/ppc/platforms/pmac_sleep.S | 396 --- arch/ppc/platforms/pmac_smp.c | 692 ----- arch/ppc/platforms/pmac_time.c | 291 -- arch/ppc/syslib/Makefile | 2 - arch/ppc/syslib/prom.c | 21 +- arch/ppc/xmon/start.c | 161 +- arch/ppc/xmon/xmon.c | 13 - drivers/video/aty/radeon_pm.c | 6 +- include/asm-ppc/prom.h | 8 + 35 files changed, 206 insertions(+), 10286 deletions(-) delete mode 100644 arch/ppc/boot/openfirmware/coffmain.c delete mode 100644 arch/ppc/boot/openfirmware/newworldmain.c delete mode 100644 arch/ppc/platforms/pmac_backlight.c delete mode 100644 arch/ppc/platforms/pmac_cache.S delete mode 100644 arch/ppc/platforms/pmac_cpufreq.c delete mode 100644 arch/ppc/platforms/pmac_feature.c delete mode 100644 arch/ppc/platforms/pmac_low_i2c.c delete mode 100644 arch/ppc/platforms/pmac_nvram.c delete mode 100644 arch/ppc/platforms/pmac_pci.c delete mode 100644 arch/ppc/platforms/pmac_pic.c delete mode 100644 arch/ppc/platforms/pmac_pic.h delete mode 100644 arch/ppc/platforms/pmac_setup.c delete mode 100644 arch/ppc/platforms/pmac_sleep.S delete mode 100644 arch/ppc/platforms/pmac_smp.c delete mode 100644 arch/ppc/platforms/pmac_time.c diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index d65810108bc..11899f06bf0 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig @@ -58,11 +58,11 @@ config 6xx help There are four types of PowerPC chips supported. The more common types (601, 603, 604, 740, 750, 7400), the Motorola embedded - versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the IBM embedded - versions (403 and 405) and the high end 64 bit Power processors - (POWER 3, POWER4, and IBM 970 also known as G5) + versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the IBM + embedded versions (403 and 405) and the POWER3 processor. + (For support for more recent 64-bit processors, set ARCH=powerpc.) Unless you are building a kernel for one of the embedded processor - systems, 64 bit IBM RS/6000 or an Apple G5, choose 6xx. + systems or a POWER3-based IBM RS/6000, choose 6xx. Note that the kernel runs in 32-bit mode even on 64-bit chips. Also note that because the 52xx, 82xx, & 83xx family has a 603e core, specific support for that chipset is asked later on. @@ -77,10 +77,6 @@ config POWER3 select PPC_FPU bool "POWER3" -config POWER4 - select PPC_FPU - bool "POWER4 and 970 (G5)" - config 8xx bool "8xx" @@ -123,7 +119,7 @@ config PHYS_64BIT config ALTIVEC bool "AltiVec Support" - depends on 6xx || POWER4 + depends on 6xx depends on !8260 && !83xx ---help--- This option enables kernel support for the Altivec extensions to the @@ -235,18 +231,9 @@ config KEXEC source "drivers/cpufreq/Kconfig" -config CPU_FREQ_PMAC - bool "Support for Apple PowerBooks" - depends on CPU_FREQ && ADB_PMU - select CPU_FREQ_TABLE - help - This adds support for frequency switching on Apple PowerBooks, - this currently includes some models of iBook & Titanium - PowerBook. - config PPC601_SYNC_FIX bool "Workarounds for PPC601 bugs" - depends on 6xx && (PPC_PREP || PPC_PMAC) + depends on 6xx && PPC_PREP help Some versions of the PPC601 (the first PowerPC chip) have bugs which mean that extra synchronization instructions are required near @@ -258,26 +245,17 @@ config PPC601_SYNC_FIX If in doubt, say Y here. -config HOTPLUG_CPU - bool "Support for enabling/disabling CPUs" - depends on SMP && HOTPLUG && EXPERIMENTAL && PPC_PMAC - ---help--- - Say Y here to be able to disable and re-enable individual - CPUs at runtime on SMP machines. - - Say N if you are unsure. - source arch/ppc/platforms/4xx/Kconfig source arch/ppc/platforms/85xx/Kconfig config PPC64BRIDGE bool - depends on POWER3 || POWER4 + depends on POWER3 default y config PPC_STD_MMU bool - depends on 6xx || POWER3 || POWER4 + depends on 6xx || POWER3 default y config NOT_COHERENT_CACHE @@ -505,7 +483,7 @@ endchoice choice prompt "Machine Type" - depends on 6xx || POWER3 || POWER4 + depends on 6xx || POWER3 default PPC_MULTIPLATFORM ---help--- Linux currently supports several different kinds of PowerPC-based @@ -516,11 +494,15 @@ choice Platform) machines (including all of the recent IBM RS/6000 and pSeries machines), and several embedded PowerPC systems containing 4xx, 6xx, 7xx, 8xx, 74xx, and 82xx processors. Currently, the - default option is to build a kernel which works on the first three. + default option is to build a kernel which works on PReP and CHRP. - Select CHRP/PowerMac/PReP if configuring for an IBM RS/6000 or - pSeries machine, a Power Macintosh (including iMacs, iBooks and - Powerbooks), or a PReP machine. + Note that support for Apple machines is now only available with + ARCH=powerpc, and has been removed from this menu. If you wish + to build a kernel for an Apple machine, exit this configuration + process and re-run it with ARCH=powerpc. + + Select CHRP/PReP if configuring for an IBM RS/6000 or + pSeries machine, or a PReP machine. Select Gemini if configuring for a Synergy Microsystems' Gemini series Single Board Computer. More information is available at: @@ -530,7 +512,7 @@ choice available at: . config PPC_MULTIPLATFORM - bool "CHRP/PowerMac/PReP" + bool "CHRP/PReP" config APUS bool "Amiga-APUS" @@ -768,25 +750,14 @@ config CPM2 on it (826x, 827x, 8560). config PPC_CHRP - bool + bool "Support for CHRP (Common Hardware Reference Platform) machines" depends on PPC_MULTIPLATFORM select PPC_I8259 select PPC_INDIRECT_PCI default y -config PPC_PMAC - bool - depends on PPC_MULTIPLATFORM - select PPC_INDIRECT_PCI - default y - -config PPC_PMAC64 - bool - depends on PPC_PMAC && POWER4 - default y - config PPC_PREP - bool + bool "Support for PReP (PowerPC Reference Platform) machines" depends on PPC_MULTIPLATFORM select PPC_I8259 select PPC_INDIRECT_PCI @@ -794,7 +765,7 @@ config PPC_PREP config PPC_OF bool - depends on PPC_PMAC || PPC_CHRP + depends on PPC_CHRP default y config PPC_GEN550 @@ -1166,7 +1137,7 @@ config ISA config GENERIC_ISA_DMA bool - depends on POWER3 || POWER4 || 6xx && !CPM2 + depends on POWER3 || 6xx && !CPM2 default y config PPC_I8259 diff --git a/arch/ppc/boot/Makefile b/arch/ppc/boot/Makefile index 995f89bb049..efd8ce515d5 100644 --- a/arch/ppc/boot/Makefile +++ b/arch/ppc/boot/Makefile @@ -18,7 +18,7 @@ BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd bootdir-y := simple bootdir-$(CONFIG_PPC_OF) += openfirmware subdir-y := lib common images -subdir-$(CONFIG_PPC_OF) += of1275 +subdir-$(CONFIG_PPC_MULTIPLATFORM) += of1275 # for cleaning subdir- += simple openfirmware diff --git a/arch/ppc/boot/openfirmware/Makefile b/arch/ppc/boot/openfirmware/Makefile index 83a6433459c..2a411ec2e65 100644 --- a/arch/ppc/boot/openfirmware/Makefile +++ b/arch/ppc/boot/openfirmware/Makefile @@ -21,26 +21,16 @@ bootlib := $(boot)/lib of1275 := $(boot)/of1275 images := $(boot)/images -OBJCOPY_ARGS := -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment -COFF_LD_ARGS := -T $(srctree)/$(boot)/ld.script -e _start -Ttext 0x00500000 \ - -Bstatic CHRP_LD_ARGS := -T $(srctree)/$(boot)/ld.script -e _start -Ttext 0x00800000 -NEWWORLD_LD_ARGS:= -T $(srctree)/$(boot)/ld.script -e _start -Ttext 0x01000000 COMMONOBJS := start.o misc.o common.o -COFFOBJS := coffcrt0.o $(COMMONOBJS) coffmain.o CHRPOBJS := crt0.o $(COMMONOBJS) chrpmain.o -NEWWORLDOBJS := crt0.o $(COMMONOBJS) newworldmain.o -targets := $(COFFOBJS) $(CHRPOBJS) $(NEWWORLDOBJS) dummy.o -COFFOBJS := $(addprefix $(obj)/, $(COFFOBJS)) +targets := $(CHRPOBJS) dummy.o CHRPOBJS := $(addprefix $(obj)/, $(CHRPOBJS)) -NEWWORLDOBJS := $(addprefix $(obj)/, $(NEWWORLDOBJS)) LIBS := lib/lib.a $(bootlib)/lib.a $(of1275)/lib.a $(common)/lib.a -HACKCOFF := $(utils)/hack-coff - ifdef CONFIG_SMP END := .smp endif @@ -72,56 +62,11 @@ targets += image.initrd.o $(obj)/image.initrd.o: $(obj)/image.o $(images)/ramdisk.image.gz FORCE $(call if_changed,genimage-initrd) -# Create the note section for New-World PowerMacs. -quiet_cmd_mknote = MKNOTE $@ - cmd_mknote = $(utils)/mknote > $@ -targets += note -$(obj)/note: $(utils)/mknote FORCE - $(call if_changed,mknote) - -$(obj)/coffcrt0.o: EXTRA_AFLAGS := -DXCOFF -targets += coffcrt0.o crt0.o -$(obj)/coffcrt0.o $(obj)/crt0.o: $(common)/crt0.S FORCE +targets += crt0.o +$(obj)/crt0.o: $(common)/crt0.S FORCE $(call if_changed_dep,as_o_S) -quiet_cmd_gencoffb = COFF $@ - cmd_gencoffb = $(LD) -o $@ $(COFF_LD_ARGS) $(COFFOBJS) $< $(LIBS) && \ - $(OBJCOPY) $@ $@ -R .comment $(del-ramdisk-sec) -targets += coffboot -$(obj)/coffboot: $(obj)/image.o $(COFFOBJS) $(LIBS) $(srctree)/$(boot)/ld.script FORCE - $(call if_changed,gencoffb) -targets += coffboot.initrd -$(obj)/coffboot.initrd: $(obj)/image.initrd.o $(COFFOBJS) $(LIBS) \ - $(srctree)/$(boot)/ld.script FORCE - $(call if_changed,gencoffb) - - -quiet_cmd_gen-coff = COFF $@ - cmd_gen-coff = $(OBJCOPY) $(OBJCOPY_ARGS) $< $@ && \ - $(HACKCOFF) $@ && \ - ln -sf $(notdir $@) $(images)/zImage$(initrd).pmac - -$(images)/vmlinux.coff: $(obj)/coffboot - $(call cmd,gen-coff) - -$(images)/vmlinux.initrd.coff: $(obj)/coffboot.initrd - $(call cmd,gen-coff) - -quiet_cmd_gen-elf-pmac = ELF $@ - cmd_gen-elf-pmac = $(LD) $(NEWWORLD_LD_ARGS) -o $@ \ - $(NEWWORLDOBJS) $(LIBS) $< && \ - $(OBJCOPY) $@ $@ --add-section=.note=$(obj)/note \ - -R .comment $(del-ramdisk-sec) - -$(images)/vmlinux.elf-pmac: $(obj)/image.o $(NEWWORLDOBJS) $(LIBS) \ - $(obj)/note $(srctree)/$(boot)/ld.script - $(call cmd,gen-elf-pmac) -$(images)/vmlinux.initrd.elf-pmac: $(obj)/image.initrd.o $(NEWWORLDOBJS) \ - $(LIBS) $(obj)/note \ - $(srctree)/$(boot)/ld.script - $(call cmd,gen-elf-pmac) - quiet_cmd_gen-chrp = CHRP $@ cmd_gen-chrp = $(LD) $(CHRP_LD_ARGS) -o $@ $(CHRPOBJS) $< $(LIBS) && \ $(OBJCOPY) $@ $@ -R .comment $(del-ramdisk-sec) @@ -139,46 +84,23 @@ $(images)/zImage.chrp-rs6k $(images)/zImage.initrd.chrp-rs6k: \ %-rs6k: % $(call cmd,addnote) -quiet_cmd_gen-miboot = GEN $@ - cmd_gen-miboot = $(OBJCOPY) $(OBJCOPY_ARGS) \ - --add-section=$1=$(word 2, $^) $< $@ -$(images)/miboot.image: $(obj)/dummy.o $(images)/vmlinux.gz - $(call cmd,gen-miboot,image) - -$(images)/miboot.initrd.image: $(images)/miboot.image $(images)/ramdisk.image.gz - $(call cmd,gen-miboot,initrd) - # The targets used on the make command-line .PHONY: zImage zImage.initrd -zImage: $(images)/vmlinux.coff \ - $(images)/vmlinux.elf-pmac \ - $(images)/zImage.chrp \ - $(images)/zImage.chrp-rs6k \ - $(images)/miboot.image +zImage: $(images)/zImage.chrp \ + $(images)/zImage.chrp-rs6k @echo ' kernel: $@ is ready ($<)' -zImage.initrd: $(images)/vmlinux.initrd.coff \ - $(images)/vmlinux.initrd.elf-pmac \ - $(images)/zImage.initrd.chrp \ - $(images)/zImage.initrd.chrp-rs6k \ - $(images)/miboot.initrd.image +zImage.initrd: $(images)/zImage.initrd.chrp \ + $(images)/zImage.initrd.chrp-rs6k @echo ' kernel: $@ is ready ($<)' TFTPIMAGE := /tftpboot/zImage .PHONY: znetboot znetboot.initrd -znetboot: $(images)/vmlinux.coff \ - $(images)/vmlinux.elf-pmac \ - $(images)/zImage.chrp - cp $(images)/vmlinux.coff $(TFTPIMAGE).pmac$(END) - cp $(images)/vmlinux.elf-pmac $(TFTPIMAGE).pmac$(END).elf +znetboot: $(images)/zImage.chrp cp $(images)/zImage.chrp $(TFTPIMAGE).chrp$(END) @echo ' kernel: $@ is ready ($<)' -znetboot.initrd:$(images)/vmlinux.initrd.coff \ - $(images)/vmlinux.initrd.elf-pmac \ - $(images)/zImage.initrd.chrp - cp $(images)/vmlinux.initrd.coff $(TFTPIMAGE).pmac$(END) - cp $(images)/vmlinux.initrd.elf-pmac $(TFTPIMAGE).pmac$(END).elf +znetboot.initrd:$(images)/zImage.initrd.chrp cp $(images)/zImage.initrd.chrp $(TFTPIMAGE).chrp$(END) @echo ' kernel: $@ is ready ($<)' diff --git a/arch/ppc/boot/openfirmware/coffmain.c b/arch/ppc/boot/openfirmware/coffmain.c deleted file mode 100644 index 2da8855e2be..00000000000 --- a/arch/ppc/boot/openfirmware/coffmain.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) Paul Mackerras 1997. - * - * 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 -#include -#include - -#include "nonstdio.h" -#include "of1275.h" - -/* Passed from the linker */ -extern char __image_begin, __image_end; -extern char __ramdisk_begin[], __ramdisk_end; -extern char _start, _end; - -extern char image_data[], initrd_data[]; -extern int initrd_len, image_len; -extern unsigned int heap_max; -extern void flush_cache(void *start, unsigned int len); -extern void gunzip(void *, int, unsigned char *, int *); -extern void make_bi_recs(unsigned long addr, char *name, unsigned int mach, - unsigned int progend); -extern void setup_bats(unsigned long start); - -char *avail_ram; -char *begin_avail, *end_avail; -char *avail_high; - -#define SCRATCH_SIZE (128 << 10) - -static char heap[SCRATCH_SIZE]; - -static unsigned long ram_start = 0; -static unsigned long ram_end = 0x1000000; - -static unsigned long prog_start = 0x800000; -static unsigned long prog_size = 0x700000; - -typedef void (*kernel_start_t)(int, int, void *); - -void boot(int a1, int a2, void *prom) -{ - unsigned sa, len; - void *dst; - unsigned char *im; - unsigned initrd_start, initrd_size; - - printf("coffboot starting: loaded at 0x%p\n", &_start); - setup_bats(ram_start); - - initrd_size = (char *)(&__ramdisk_end) - (char *)(&__ramdisk_begin); - if (initrd_size) { - initrd_start = (ram_end - initrd_size) & ~0xFFF; - a1 = initrd_start; - a2 = initrd_size; - claim(initrd_start, ram_end - initrd_start, 0); - printf("initial ramdisk moving 0x%x <- 0x%p (%x bytes)\n\r", - initrd_start, (char *)(&__ramdisk_begin), initrd_size); - memcpy((char *)initrd_start, (char *)(&__ramdisk_begin), initrd_size); - prog_size = initrd_start - prog_start; - } else - a2 = 0xdeadbeef; - - im = (char *)(&__image_begin); - len = (char *)(&__image_end) - (char *)(&__image_begin); - /* claim 4MB starting at PROG_START */ - claim(prog_start, prog_size, 0); - map(prog_start, prog_start, prog_size); - dst = (void *) prog_start; - if (im[0] == 0x1f && im[1] == 0x8b) { - /* set up scratch space */ - begin_avail = avail_high = avail_ram = heap; - end_avail = heap + sizeof(heap); - printf("heap at 0x%p\n", avail_ram); - printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len); - gunzip(dst, prog_size, im, &len); - printf("done %u bytes\n", len); - printf("%u bytes of heap consumed, max in use %u\n", - avail_high - begin_avail, heap_max); - } else { - memmove(dst, im, len); - } - - flush_cache(dst, len); - make_bi_recs(((unsigned long) dst + len), "coffboot", _MACH_Pmac, - (prog_start + prog_size)); - - sa = (unsigned long)prog_start; - printf("start address = 0x%x\n", sa); - - (*(kernel_start_t)sa)(a1, a2, prom); - - printf("returned?\n"); - - pause(); -} diff --git a/arch/ppc/boot/openfirmware/newworldmain.c b/arch/ppc/boot/openfirmware/newworldmain.c deleted file mode 100644 index fa8a8f9313f..00000000000 --- a/arch/ppc/boot/openfirmware/newworldmain.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) Paul Mackerras 1997. - * - * 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 -#include "nonstdio.h" -#include "of1275.h" -#include -#include - -/* Passed from the linker */ -extern char __image_begin, __image_end; -extern char __ramdisk_begin[], __ramdisk_end; -extern char _start, _end; - -extern unsigned int heap_max; -extern void flush_cache(void *start, unsigned int len); -extern void gunzip(void *, int, unsigned char *, int *); -extern void make_bi_recs(unsigned long addr, char *name, unsigned int mach, - unsigned int progend); - -char *avail_ram; -char *begin_avail, *end_avail; -char *avail_high; - - -#define RAM_END (16 << 20) - -#define PROG_START 0x00010000 -#define PROG_SIZE 0x007f0000 - -#define SCRATCH_SIZE (128 << 10) - -typedef void (*kernel_start_t)(int, int, void *); - -void boot(int a1, int a2, void *prom) -{ - unsigned sa, len; - void *dst; - unsigned char *im; - unsigned initrd_start, initrd_size; - - printf("chrpboot starting: loaded at 0x%p\n", &_start); - - initrd_size = (char *)(&__ramdisk_end) - (char *)(&__ramdisk_begin); - if (initrd_size) { - initrd_start = (RAM_END - initrd_size) & ~0xFFF; - a1 = initrd_start; - a2 = initrd_size; - claim(initrd_start, RAM_END - initrd_start, 0); - printf("initial ramdisk moving 0x%x <- 0x%p (%x bytes)\n\r", - initrd_start, (char *)(&__ramdisk_begin), initrd_size); - memcpy((char *)initrd_start, (char *)(&__ramdisk_begin), initrd_size); - } else - a2 = 0xdeadbeef; - - im = (char *)(&__image_begin); - len = (char *)(&__image_end) - (char *)(&__image_begin); - /* claim 3MB starting at PROG_START */ - claim(PROG_START, PROG_SIZE, 0); - dst = (void *) PROG_START; - if (im[0] == 0x1f && im[1] == 0x8b) { - /* claim some memory for scratch space */ - avail_ram = (char *) claim(0, SCRATCH_SIZE, 0x10); - begin_avail = avail_high = avail_ram; - end_avail = avail_ram + SCRATCH_SIZE; - printf("heap at 0x%p\n", avail_ram); - printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len); - gunzip(dst, PROG_SIZE, im, &len); - printf("done %u bytes\n", len); - printf("%u bytes of heap consumed, max in use %u\n", - avail_high - begin_avail, heap_max); - release(begin_avail, SCRATCH_SIZE); - } else { - memmove(dst, im, len); - } - - flush_cache(dst, len); - make_bi_recs(((unsigned long) dst + len), "chrpboot", _MACH_Pmac, - (PROG_START + PROG_SIZE)); - - sa = (unsigned long)PROG_START; - printf("start address = 0x%x\n", sa); - - (*(kernel_start_t)sa)(a1, a2, prom); - - printf("returned?\n"); - - pause(); -} diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index ca020130086..647da4c1d21 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -9,7 +9,6 @@ extra-$(CONFIG_44x) := head_44x.o extra-$(CONFIG_FSL_BOOKE) := head_fsl_booke.o extra-$(CONFIG_8xx) := head_8xx.o extra-$(CONFIG_6xx) += idle_6xx.o -extra-$(CONFIG_POWER4) += idle_power4.o extra-y += vmlinux.lds obj-y := entry.o traps.o idle.o time.o misc.o \ @@ -17,7 +16,6 @@ obj-y := entry.o traps.o idle.o time.o misc.o \ ppc_htab.o obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o -obj-$(CONFIG_POWER4) += cpu_setup_power4.o obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-mapping.o obj-$(CONFIG_PCI) += pci.o diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index fb5658bba28..c3427eed834 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S @@ -204,78 +204,6 @@ _GLOBAL(call_setup_cpu) mtctr r5 bctr -#if defined(CONFIG_CPU_FREQ_PMAC) && defined(CONFIG_6xx) - -/* This gets called by via-pmu.c to switch the PLL selection - * on 750fx CPU. This function should really be moved to some - * other place (as most of the cpufreq code in via-pmu - */ -_GLOBAL(low_choose_750fx_pll) - /* Clear MSR:EE */ - mfmsr r7 - rlwinm r0,r7,0,17,15 - mtmsr r0 - - /* If switching to PLL1, disable HID0:BTIC */ - cmplwi cr0,r3,0 - beq 1f - mfspr r5,SPRN_HID0 - rlwinm r5,r5,0,27,25 - sync - mtspr SPRN_HID0,r5 - isync - sync - -1: - /* Calc new HID1 value */ - mfspr r4,SPRN_HID1 /* Build a HID1:PS bit from parameter */ - rlwinm r5,r3,16,15,15 /* Clear out HID1:PS from value read */ - rlwinm r4,r4,0,16,14 /* Could have I used rlwimi here ? */ - or r4,r4,r5 - mtspr SPRN_HID1,r4 - - /* Store new HID1 image */ - rlwinm r6,r1,0,0,18 - lwz r6,TI_CPU(r6) - slwi r6,r6,2 - addis r6,r6,nap_save_hid1@ha - stw r4,nap_save_hid1@l(r6) - - /* If switching to PLL0, enable HID0:BTIC */ - cmplwi cr0,r3,0 - bne 1f - mfspr r5,SPRN_HID0 - ori r5,r5,HID0_BTIC - sync - mtspr SPRN_HID0,r5 - isync - sync - -1: - /* Return */ - mtmsr r7 - blr - -_GLOBAL(low_choose_7447a_dfs) - /* Clear MSR:EE */ - mfmsr r7 - rlwinm r0,r7,0,17,15 - mtmsr r0 - - /* Calc new HID1 value */ - mfspr r4,SPRN_HID1 - insrwi r4,r3,1,9 /* insert parameter into bit 9 */ - sync - mtspr SPRN_HID1,r4 - sync - isync - - /* Return */ - mtmsr r7 - blr - -#endif /* CONFIG_CPU_FREQ_PMAC && CONFIG_6xx */ - /* * complement mask on the msr then "or" some values on. * _nmask_and_or_msr(nmask, value_to_or) diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c index 704c846b2b0..04d04c5bfdd 100644 --- a/arch/ppc/kernel/pci.c +++ b/arch/ppc/kernel/pci.c @@ -1,5 +1,5 @@ /* - * Common pmac/prep/chrp pci routines. -- Cort + * Common prep/chrp pci routines. -- Cort */ #include @@ -50,8 +50,7 @@ static void fixup_cpc710_pci64(struct pci_dev* dev); static u8* pci_to_OF_bus_map; #endif -/* By default, we don't re-assign bus numbers. We do this only on - * some pmacs +/* By default, we don't re-assign bus numbers. */ int pci_assign_all_buses; @@ -780,17 +779,6 @@ pci_busdev_to_OF_node(struct pci_bus *bus, int devfn) return NULL; /* Fixup bus number according to what OF think it is. */ -#ifdef CONFIG_PPC_PMAC - /* The G5 need a special case here. Basically, we don't remap all - * busses on it so we don't create the pci-OF-map. However, we do - * remap the AGP bus and so have to deal with it. A future better - * fix has to be done by making the remapping per-host and always - * filling the pci_to_OF map. --BenH - */ - if (_machine == _MACH_Pmac && busnr >= 0xf0) - busnr -= 0xf0; - else -#endif if (pci_to_OF_bus_map) busnr = pci_to_OF_bus_map[busnr]; if (busnr == 0xff) @@ -1040,216 +1028,6 @@ void pcibios_add_platform_entries(struct pci_dev *pdev) } -#ifdef CONFIG_PPC_PMAC -/* - * This set of routines checks for PCI<->PCI bridges that have closed - * IO resources and have child devices. It tries to re-open an IO - * window on them. - * - * This is a _temporary_ fix to workaround a problem with Apple's OF - * closing IO windows on P2P bridges when the OF drivers of cards - * below this bridge don't claim any IO range (typically ATI or - * Adaptec). - * - * A more complete fix would be to use drivers/pci/setup-bus.c, which - * involves a working pcibios_fixup_pbus_ranges(), some more care about - * ordering when creating the host bus resources, and maybe a few more - * minor tweaks - */ - -/* Initialize bridges with base/limit values we have collected */ -static void __init -do_update_p2p_io_resource(struct pci_bus *bus, int enable_vga) -{ - struct pci_dev *bridge = bus->self; - struct pci_controller* hose = (struct pci_controller *)bridge->sysdata; - u32 l; - u16 w; - struct resource res; - - if (bus->resource[0] == NULL) - return; - res = *(bus->resource[0]); - - DBG("Remapping Bus %d, bridge: %s\n", bus->number, pci_name(bridge)); - res.start -= ((unsigned long) hose->io_base_virt - isa_io_base); - res.end -= ((unsigned long) hose->io_base_virt - isa_io_base); - DBG(" IO window: %08lx-%08lx\n", res.start, res.end); - - /* Set up the top and bottom of the PCI I/O segment for this bus. */ - pci_read_config_dword(bridge, PCI_IO_BASE, &l); - l &= 0xffff000f; - l |= (res.start >> 8) & 0x00f0; - l |= res.end & 0xf000; - pci_write_config_dword(bridge, PCI_IO_BASE, l); - - if ((l & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) { - l = (res.start >> 16) | (res.end & 0xffff0000); - pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, l); - } - - pci_read_config_word(bridge, PCI_COMMAND, &w); - w |= PCI_COMMAND_IO; - pci_write_config_word(bridge, PCI_COMMAND, w); - -#if 0 /* Enabling this causes XFree 4.2.0 to hang during PCI probe */ - if (enable_vga) { - pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &w); - w |= PCI_BRIDGE_CTL_VGA; - pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, w); - } -#endif -} - -/* This function is pretty basic and actually quite broken for the - * general case, it's enough for us right now though. It's supposed - * to tell us if we need to open an IO range at all or not and what - * size. - */ -static int __init -check_for_io_childs(struct pci_bus *bus, struct resource* res, int *found_vga) -{ - struct pci_dev *dev; - int i; - int rc = 0; - -#define push_end(res, size) do { unsigned long __sz = (size) ; \ - res->end = ((res->end + __sz) / (__sz + 1)) * (__sz + 1) + __sz; \ - } while (0) - - list_for_each_entry(dev, &bus->devices, bus_list) { - u16 class = dev->class >> 8; - - if (class == PCI_CLASS_DISPLAY_VGA || - class == PCI_CLASS_NOT_DEFINED_VGA) - *found_vga = 1; - if (class >> 8 == PCI_BASE_CLASS_BRIDGE && dev->subordinate) - rc |= check_for_io_childs(dev->subordinate, res, found_vga); - if (class == PCI_CLASS_BRIDGE_CARDBUS) - push_end(res, 0xfff); - - for (i=0; iclass >> 8 == PCI_CLASS_BRIDGE_PCI - && i >= PCI_BRIDGE_RESOURCES) - continue; - r = &dev->resource[i]; - r_size = r->end - r->start; - if (r_size < 0xfff) - r_size = 0xfff; - if (r->flags & IORESOURCE_IO && (r_size) != 0) { - rc = 1; - push_end(res, r_size); - } - } - } - - return rc; -} - -/* Here we scan all P2P bridges of a given level that have a closed - * IO window. Note that the test for the presence of a VGA card should - * be improved to take into account already configured P2P bridges, - * currently, we don't see them and might end up configuring 2 bridges - * with VGA pass through enabled - */ -static void __init -do_fixup_p2p_level(struct pci_bus *bus) -{ - struct pci_bus *b; - int i, parent_io; - int has_vga = 0; - - for (parent_io=0; parent_io<4; parent_io++) - if (bus->resource[parent_io] - && bus->resource[parent_io]->flags & IORESOURCE_IO) - break; - if (parent_io >= 4) - return; - - list_for_each_entry(b, &bus->children, node) { - struct pci_dev *d = b->self; - struct pci_controller* hose = (struct pci_controller *)d->sysdata; - struct resource *res = b->resource[0]; - struct resource tmp_res; - unsigned long max; - int found_vga = 0; - - memset(&tmp_res, 0, sizeof(tmp_res)); - tmp_res.start = bus->resource[parent_io]->start; - - /* We don't let low addresses go through that closed P2P bridge, well, - * that may not be necessary but I feel safer that way - */ - if (tmp_res.start == 0) - tmp_res.start = 0x1000; - - if (!list_empty(&b->devices) && res && res->flags == 0 && - res != bus->resource[parent_io] && - (d->class >> 8) == PCI_CLASS_BRIDGE_PCI && - check_for_io_childs(b, &tmp_res, &found_vga)) { - u8 io_base_lo; - - printk(KERN_INFO "Fixing up IO bus %s\n", b->name); - - if (found_vga) { - if (has_vga) { - printk(KERN_WARNING "Skipping VGA, already active" - " on bus segment\n"); - found_vga = 0; - } else - has_vga = 1; - } - pci_read_config_byte(d, PCI_IO_BASE, &io_base_lo); - - if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) - max = ((unsigned long) hose->io_base_virt - - isa_io_base) + 0xffffffff; - else - max = ((unsigned long) hose->io_base_virt - - isa_io_base) + 0xffff; - - *res = tmp_res; - res->flags = IORESOURCE_IO; - res->name = b->name; - - /* Find a resource in the parent where we can allocate */ - for (i = 0 ; i < 4; i++) { - struct resource *r = bus->resource[i]; - if (!r) - continue; - if ((r->flags & IORESOURCE_IO) == 0) - continue; - DBG("Trying to allocate from %08lx, size %08lx from parent" - " res %d: %08lx -> %08lx\n", - res->start, res->end, i, r->start, r->end); - - if (allocate_resource(r, res, res->end + 1, res->start, max, - res->end + 1, NULL, NULL) < 0) { - DBG("Failed !\n"); - continue; - } - do_update_p2p_io_resource(b, found_vga); - break; - } - } - do_fixup_p2p_level(b); - } -} - -static void -pcibios_fixup_p2p_bridges(void) -{ - struct pci_bus *b; - - list_for_each_entry(b, &pci_root_buses, node) - do_fixup_p2p_level(b); -} - -#endif /* CONFIG_PPC_PMAC */ - static int __init pcibios_init(void) { @@ -1290,9 +1068,6 @@ pcibios_init(void) pcibios_allocate_bus_resources(&pci_root_buses); pcibios_allocate_resources(0); pcibios_allocate_resources(1); -#ifdef CONFIG_PPC_PMAC - pcibios_fixup_p2p_bridges(); -#endif /* CONFIG_PPC_PMAC */ pcibios_assign_resources(); /* Call machine dependent post-init code */ @@ -1722,17 +1497,6 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn) struct pci_controller* hose; long result = -EOPNOTSUPP; - /* Argh ! Please forgive me for that hack, but that's the - * simplest way to get existing XFree to not lockup on some - * G5 machines... So when something asks for bus 0 io base - * (bus 0 is HT root), we return the AGP one instead. - */ -#ifdef CONFIG_PPC_PMAC - if (_machine == _MACH_Pmac && machine_is_compatible("MacRISC4")) - if (bus == 0) - bus = 0xf0; -#endif /* CONFIG_PPC_PMAC */ - hose = pci_bus_to_hose(bus); if (!hose) return -ENODEV; diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index fb0da7c209d..3a6e4bcb3c5 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -58,7 +57,6 @@ extern void machine_check_exception(struct pt_regs *regs); extern void alignment_exception(struct pt_regs *regs); extern void program_check_exception(struct pt_regs *regs); extern void single_step_exception(struct pt_regs *regs); -extern int pmac_newworld; extern int sys_sigreturn(struct pt_regs *regs); long long __ashrdi3(long long, int); @@ -213,10 +211,6 @@ EXPORT_SYMBOL(adb_try_handler_change); EXPORT_SYMBOL(cuda_request); EXPORT_SYMBOL(cuda_poll); #endif /* CONFIG_ADB_CUDA */ -#ifdef CONFIG_PPC_PMAC -EXPORT_SYMBOL(sys_ctrler); -EXPORT_SYMBOL(pmac_newworld); -#endif #ifdef CONFIG_PPC_OF EXPORT_SYMBOL(find_devices); EXPORT_SYMBOL(find_type_devices); @@ -241,9 +235,6 @@ EXPORT_SYMBOL(of_node_put); #if defined(CONFIG_BOOTX_TEXT) EXPORT_SYMBOL(btext_update_display); #endif -#if defined(CONFIG_SCSI) && defined(CONFIG_PPC_PMAC) -EXPORT_SYMBOL(note_scsi_host); -#endif #ifdef CONFIG_VT EXPORT_SYMBOL(kd_mksound); #endif diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index e707c6f6e61..c08ab432e95 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c @@ -1,5 +1,5 @@ /* - * Common prep/pmac/chrp boot and setup code. + * Common prep/chrp boot and setup code. */ #include @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -55,7 +54,6 @@ extern void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7); -extern void bootx_init(unsigned long r4, unsigned long phys); extern void identify_cpu(unsigned long offset, unsigned long cpu); extern void do_cpu_ftr_fixups(unsigned long offset); extern void reloc_got2(unsigned long offset); @@ -80,8 +78,6 @@ EXPORT_SYMBOL(_machine); extern void prep_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7); -extern void pmac_init(unsigned long r3, unsigned long r4, - unsigned long r5, unsigned long r6, unsigned long r7); extern void chrp_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7); @@ -324,20 +320,15 @@ early_init(int r3, int r4, int r5) identify_cpu(offset, 0); do_cpu_ftr_fixups(offset); -#if defined(CONFIG_PPC_MULTIPLATFORM) +#if defined(CONFIG_PPC_OF) reloc_got2(offset); - /* If we came here from BootX, clear the screen, - * set up some pointers and return. */ - if ((r3 == 0x426f6f58) && (r5 == 0)) - bootx_init(r4, phys); - /* * don't do anything on prep * for now, don't use bootinfo because it breaks yaboot 0.5 * and assume that if we didn't find a magic number, we have OF */ - else if (*(unsigned long *)(0) != 0xdeadc0de) + if (*(unsigned long *)(0) != 0xdeadc0de) phys = prom_init(r3, r4, (prom_entry)r5); reloc_got2(-offset); @@ -424,6 +415,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, } #endif +#ifdef CONFIG_PPC_OF have_of = 1; /* prom_init has already been called from __start */ @@ -495,19 +487,17 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, #endif /* CONFIG_ADB */ switch (_machine) { -#ifdef CONFIG_PPC_PMAC - case _MACH_Pmac: - pmac_init(r3, r4, r5, r6, r7); - break; -#endif #ifdef CONFIG_PPC_CHRP case _MACH_chrp: chrp_init(r3, r4, r5, r6, r7); break; #endif } +#endif /* CONFIG_PPC_OF */ } +#endif /* CONFIG_PPC_MULTIPLATFORM */ +#ifdef CONFIG_PPC_OF #ifdef CONFIG_SERIAL_CORE_CONSOLE extern char *of_stdout_device; @@ -564,7 +554,7 @@ static int __init set_preferred_console(void) } console_initcall(set_preferred_console); #endif /* CONFIG_SERIAL_CORE_CONSOLE */ -#endif /* CONFIG_PPC_MULTIPLATFORM */ +#endif /* CONFIG_PPC_OF */ struct bi_record *find_bootinfo(void) { @@ -747,14 +737,6 @@ void __init setup_arch(char **cmdline_p) if (ppc_md.init_early) ppc_md.init_early(); -#ifdef CONFIG_PPC_MULTIPLATFORM - /* This could be called "early setup arch", it must be done - * now because xmon need it - */ - if (_machine == _MACH_Pmac) - pmac_feature_init(); /* New cool way */ -#endif - #ifdef CONFIG_XMON xmon_init(1); if (strstr(cmd_line, "xmon")) diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index 9dbc4d28fa2..6d0a1838d94 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -38,9 +38,6 @@ #include #include #include -#ifdef CONFIG_PMAC_BACKLIGHT -#include -#endif #include #ifdef CONFIG_XMON @@ -85,12 +82,6 @@ int die(const char * str, struct pt_regs * fp, long err) int nl = 0; console_verbose(); spin_lock_irq(&die_lock); -#ifdef CONFIG_PMAC_BACKLIGHT - if (_machine == _MACH_Pmac) { - set_backlight_enable(1); - set_backlight_level(BACKLIGHT_MAX); - } -#endif printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter); #ifdef CONFIG_PREEMPT printk("PREEMPT "); @@ -159,7 +150,7 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) */ static inline int check_io_access(struct pt_regs *regs) { -#if defined CONFIG_PPC_PMAC || defined CONFIG_8xx +#if defined CONFIG_8xx unsigned long msr = regs->msr; const struct exception_table_entry *entry; unsigned int *nip = (unsigned int *)regs->nip; @@ -196,7 +187,7 @@ static inline int check_io_access(struct pt_regs *regs) return 1; } } -#endif /* CONFIG_PPC_PMAC */ +#endif /* CONFIG_8xx */ return 0; } diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c index 45f0782059f..134db5c0420 100644 --- a/arch/ppc/mm/init.c +++ b/arch/ppc/mm/init.c @@ -67,10 +67,6 @@ unsigned long ppc_memoffset = PAGE_OFFSET; int mem_init_done; int init_bootmem_done; int boot_mapsize; -#ifdef CONFIG_PPC_PMAC -unsigned long agp_special_page; -EXPORT_SYMBOL(agp_special_page); -#endif extern char _end[]; extern char etext[], _stext[]; @@ -423,10 +419,6 @@ void __init mem_init(void) addr < PAGE_ALIGN((ulong)__va(rtas_data)+rtas_size) ; addr += PAGE_SIZE) SetPageReserved(virt_to_page(addr)); -#endif -#ifdef CONFIG_PPC_PMAC - if (agp_special_page) - SetPageReserved(virt_to_page(agp_special_page)); #endif for (addr = PAGE_OFFSET; addr < (unsigned long)high_memory; addr += PAGE_SIZE) { @@ -463,11 +455,6 @@ void __init mem_init(void) initpages<< (PAGE_SHIFT-10), (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))); -#ifdef CONFIG_PPC_PMAC - if (agp_special_page) - printk(KERN_INFO "AGP special page: 0x%08lx\n", agp_special_page); -#endif - mem_init_done = 1; } @@ -512,22 +499,6 @@ set_phys_avail(unsigned long total_memory) if (rtas_data) mem_pieces_remove(&phys_avail, rtas_data, rtas_size, 1); #endif -#ifdef CONFIG_PPC_PMAC - /* Because of some uninorth weirdness, we need a page of - * memory as high as possible (it must be outside of the - * bus address seen as the AGP aperture). It will be used - * by the r128 DRM driver - * - * FIXME: We need to make sure that page doesn't overlap any of the\ - * above. This could be done by improving mem_pieces_find to be able - * to do a backward search from the end of the list. - */ - if (_machine == _MACH_Pmac && find_devices("uni-north-agp")) { - agp_special_page = (total_memory - PAGE_SIZE); - mem_pieces_remove(&phys_avail, agp_special_page, PAGE_SIZE, 0); - agp_special_page = (unsigned long)__va(agp_special_page); - } -#endif /* CONFIG_PPC_PMAC */ } /* Mark some memory as reserved by removing it from phys_avail. */ diff --git a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile index 7c5cdabf6f3..51430e294b3 100644 --- a/arch/ppc/platforms/Makefile +++ b/arch/ppc/platforms/Makefile @@ -3,26 +3,18 @@ # # Extra CFLAGS so we don't have to do relative includes -CFLAGS_pmac_setup.o += -Iarch/$(ARCH)/mm +CFLAGS_chrp_setup.o += -Iarch/$(ARCH)/mm obj-$(CONFIG_APUS) += apus_setup.o ifeq ($(CONFIG_APUS),y) obj-$(CONFIG_PCI) += apus_pci.o endif -obj-$(CONFIG_PPC_PMAC) += pmac_pic.o pmac_setup.o pmac_time.o \ - pmac_feature.o pmac_pci.o pmac_sleep.o \ - pmac_low_i2c.o pmac_cache.o obj-$(CONFIG_PPC_CHRP) += chrp_setup.o chrp_time.o chrp_pci.o \ chrp_pegasos_eth.o ifeq ($(CONFIG_PPC_CHRP),y) obj-$(CONFIG_NVRAM) += chrp_nvram.o endif obj-$(CONFIG_PPC_PREP) += prep_pci.o prep_setup.o -ifeq ($(CONFIG_PPC_PMAC),y) -obj-$(CONFIG_NVRAM) += pmac_nvram.o -obj-$(CONFIG_CPU_FREQ_PMAC) += pmac_cpufreq.o -endif -obj-$(CONFIG_PMAC_BACKLIGHT) += pmac_backlight.o obj-$(CONFIG_PREP_RESIDUAL) += residual.o obj-$(CONFIG_PQ2ADS) += pq2ads.o obj-$(CONFIG_TQM8260) += tqm8260_setup.o @@ -47,6 +39,5 @@ obj-$(CONFIG_LITE5200) += lite5200.o obj-$(CONFIG_EV64360) += ev64360.o ifeq ($(CONFIG_SMP),y) -obj-$(CONFIG_PPC_PMAC) += pmac_smp.o obj-$(CONFIG_PPC_CHRP) += chrp_smp.o endif diff --git a/arch/ppc/platforms/chrp_pci.c b/arch/ppc/platforms/chrp_pci.c index bd047aac01b..c7fe6182bb7 100644 --- a/arch/ppc/platforms/chrp_pci.c +++ b/arch/ppc/platforms/chrp_pci.c @@ -275,7 +275,7 @@ chrp_find_bridges(void) setup_python(hose, dev); } else if (is_mot || strncmp(model, "Motorola, Grackle", 17) == 0) { - setup_grackle(hose); + setup_indirect_pci(hose, 0xfec00000, 0xfee00000); } else if (is_longtrail) { void __iomem *p = ioremap(GG2_PCI_CONFIG_BASE, 0x80000); hose->ops = &gg2_pci_ops; diff --git a/arch/ppc/platforms/chrp_setup.c b/arch/ppc/platforms/chrp_setup.c index 056ac2a7b5c..48996b78737 100644 --- a/arch/ppc/platforms/chrp_setup.c +++ b/arch/ppc/platforms/chrp_setup.c @@ -53,6 +53,7 @@ #include #include #include +#include "mem_pieces.h" unsigned long chrp_get_rtc_time(void); int chrp_set_rtc_time(unsigned long nowtime); @@ -65,7 +66,6 @@ void rtas_display_progress(char *, unsigned short); void rtas_indicator_progress(char *, unsigned short); void btext_progress(char *, unsigned short); -extern unsigned long pmac_find_end_of_memory(void); extern int of_show_percpuinfo(struct seq_file *, int); int _chrp_type; @@ -467,6 +467,75 @@ chrp_init2(void) ppc_md.progress(" Have fun! ", 0x7777); } +static struct device_node *memory_node; + +static int __init get_mem_prop(char *name, struct mem_pieces *mp) +{ + struct reg_property *rp; + int i, s; + unsigned int *ip; + int nac = prom_n_addr_cells(memory_node); + int nsc = prom_n_size_cells(memory_node); + + ip = (unsigned int *) get_property(memory_node, name, &s); + if (ip == NULL) { + printk(KERN_ERR "error: couldn't get %s property on /memory\n", + name); + return 0; + } + s /= (nsc + nac) * 4; + rp = mp->regions; + for (i = 0; i < s; ++i, ip += nac+nsc) { + if (nac >= 2 && ip[nac-2] != 0) + continue; + rp->address = ip[nac-1]; + if (nsc >= 2 && ip[nac+nsc-2] != 0) + rp->size = ~0U; + else + rp->size = ip[nac+nsc-1]; + ++rp; + } + mp->n_regions = rp - mp->regions; + + /* Make sure the pieces are sorted. */ + mem_pieces_sort(mp); + mem_pieces_coalesce(mp); + return 1; +} + +static unsigned long __init chrp_find_end_of_memory(void) +{ + unsigned long a, total; + struct mem_pieces phys_mem; + + /* + * Find out where physical memory is, and check that it + * starts at 0 and is contiguous. It seems that RAM is + * always physically contiguous on Power Macintoshes. + * + * Supporting discontiguous physical memory isn't hard, + * it just makes the virtual <-> physical mapping functions + * more complicated (or else you end up wasting space + * in mem_map). + */ + memory_node = find_devices("memory"); + if (memory_node == NULL || !get_mem_prop("reg", &phys_mem) + || phys_mem.n_regions == 0) + panic("No RAM??"); + a = phys_mem.regions[0].address; + if (a != 0) + panic("RAM doesn't start at physical address 0"); + total = phys_mem.regions[0].size; + + if (phys_mem.n_regions > 1) { + printk("RAM starting at 0x%x is not contiguous\n", + phys_mem.regions[1].address); + printk("Using RAM from 0 to 0x%lx\n", total-1); + } + + return total; +} + void __init chrp_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) @@ -525,7 +594,7 @@ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5, ppc_md.get_rtc_time = chrp_get_rtc_time; ppc_md.calibrate_decr = chrp_calibrate_decr; - ppc_md.find_end_of_memory = pmac_find_end_of_memory; + ppc_md.find_end_of_memory = chrp_find_end_of_memory; if (rtas_data) { struct device_node *rtas; diff --git a/arch/ppc/platforms/chrp_time.c b/arch/ppc/platforms/chrp_time.c index 29d074c305f..57753a55b58 100644 --- a/arch/ppc/platforms/chrp_time.c +++ b/arch/ppc/platforms/chrp_time.c @@ -163,13 +163,75 @@ unsigned long chrp_get_rtc_time(void) return mktime(year, mon, day, hour, min, sec); } +/* + * Calibrate the decrementer frequency with the VIA timer 1. + */ +#define VIA_TIMER_FREQ_6 4700000 /* time 1 frequency * 6 */ + +/* VIA registers */ +#define RS 0x200 /* skip between registers */ +#define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */ +#define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */ +#define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */ +#define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */ +#define ACR (11*RS) /* Auxiliary control register */ +#define IFR (13*RS) /* Interrupt flag register */ + +/* Bits in ACR */ +#define T1MODE 0xc0 /* Timer 1 mode */ +#define T1MODE_CONT 0x40 /* continuous interrupts */ + +/* Bits in IFR and IER */ +#define T1_INT 0x40 /* Timer 1 interrupt */ + +static int __init chrp_via_calibrate_decr(void) +{ + struct device_node *vias; + volatile unsigned char __iomem *via; + int count = VIA_TIMER_FREQ_6 / 100; + unsigned int dstart, dend; + + vias = find_devices("via-cuda"); + if (vias == 0) + vias = find_devices("via"); + if (vias == 0 || vias->n_addrs == 0) + return 0; + via = ioremap(vias->addrs[0].address, vias->addrs[0].size); + + /* set timer 1 for continuous interrupts */ + out_8(&via[ACR], (via[ACR] & ~T1MODE) | T1MODE_CONT); + /* set the counter to a small value */ + out_8(&via[T1CH], 2); + /* set the latch to `count' */ + out_8(&via[T1LL], count); + out_8(&via[T1LH], count >> 8); + /* wait until it hits 0 */ + while ((in_8(&via[IFR]) & T1_INT) == 0) + ; + dstart = get_dec(); + /* clear the interrupt & wait until it hits 0 again */ + in_8(&via[T1CL]); + while ((in_8(&via[IFR]) & T1_INT) == 0) + ; + dend = get_dec(); + + tb_ticks_per_jiffy = (dstart - dend) / ((6 * HZ)/100); + tb_to_us = mulhwu_scale_factor(dstart - dend, 60000); + + printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n", + tb_ticks_per_jiffy, dstart - dend); + + iounmap(via); + + return 1; +} void __init chrp_calibrate_decr(void) { struct device_node *cpu; unsigned int freq, *fp; - if (via_calibrate_decr()) + if (chrp_via_calibrate_decr()) return; /* diff --git a/arch/ppc/platforms/pmac_backlight.c b/arch/ppc/platforms/pmac_backlight.c deleted file mode 100644 index 8be2f7d071f..00000000000 --- a/arch/ppc/platforms/pmac_backlight.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Miscellaneous procedures for dealing with the PowerMac hardware. - * Contains support for the backlight. - * - * Copyright (C) 2000 Benjamin Herrenschmidt - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -static struct backlight_controller *backlighter; -static void* backlighter_data; -static int backlight_autosave; -static int backlight_level = BACKLIGHT_MAX; -static int backlight_enabled = 1; -static int backlight_req_level = -1; -static int backlight_req_enable = -1; - -static void backlight_callback(void *); -static DECLARE_WORK(backlight_work, backlight_callback, NULL); - -void register_backlight_controller(struct backlight_controller *ctrler, - void *data, char *type) -{ - struct device_node* bk_node; - char *prop; - int valid = 0; - - /* There's already a matching controller, bail out */ - if (backlighter != NULL) - return; - - bk_node = find_devices("backlight"); - -#ifdef CONFIG_ADB_PMU - /* Special case for the old PowerBook since I can't test on it */ - backlight_autosave = machine_is_compatible("AAPL,3400/2400") - || machine_is_compatible("AAPL,3500"); - if ((backlight_autosave - || machine_is_compatible("AAPL,PowerBook1998") - || machine_is_compatible("PowerBook1,1")) - && !strcmp(type, "pmu")) - valid = 1; -#endif - if (bk_node) { - prop = get_property(bk_node, "backlight-control", NULL); - if (prop && !strncmp(prop, type, strlen(type))) - valid = 1; - } - if (!valid) - return; - backlighter = ctrler; - backlighter_data = data; - - if (bk_node && !backlight_autosave) - prop = get_property(bk_node, "bklt", NULL); - else - prop = NULL; - if (prop) { - backlight_level = ((*prop)+1) >> 1; - if (backlight_level > BACKLIGHT_MAX) - backlight_level = BACKLIGHT_MAX; - } - -#ifdef CONFIG_ADB_PMU - if (backlight_autosave) { - struct adb_request req; - pmu_request(&req, NULL, 2, 0xd9, 0); - while (!req.complete) - pmu_poll(); - backlight_level = req.reply[0] >> 4; - } -#endif - acquire_console_sem(); - if (!backlighter->set_enable(1, backlight_level, data)) - backlight_enabled = 1; - release_console_sem(); - - printk(KERN_INFO "Registered \"%s\" backlight controller," - "level: %d/15\n", type, backlight_level); -} -EXPORT_SYMBOL(register_backlight_controller); - -void unregister_backlight_controller(struct backlight_controller - *ctrler, void *data) -{ - /* We keep the current backlight level (for now) */ - if (ctrler == backlighter && data == backlighter_data) - backlighter = NULL; -} -EXPORT_SYMBOL(unregister_backlight_controller); - -static int __set_backlight_enable(int enable) -{ - int rc; - - if (!backlighter) - return -ENODEV; - acquire_console_sem(); - rc = backlighter->set_enable(enable, backlight_level, - backlighter_data); - if (!rc) - backlight_enabled = enable; - release_console_sem(); - return rc; -} -int set_backlight_enable(int enable) -{ - if (!backlighter) - return -ENODEV; - backlight_req_enable = enable; - schedule_work(&backlight_work); - return 0; -} - -EXPORT_SYMBOL(set_backlight_enable); - -int get_backlight_enable(void) -{ - if (!backlighter) - return -ENODEV; - return backlight_enabled; -} -EXPORT_SYMBOL(get_backlight_enable); - -static int __set_backlight_level(int level) -{ - int rc = 0; - - if (!backlighter) - return -ENODEV; - if (level < BACKLIGHT_MIN) - level = BACKLIGHT_OFF; - if (level > BACKLIGHT_MAX) - level = BACKLIGHT_MAX; - acquire_console_sem(); - if (backlight_enabled) - rc = backlighter->set_level(level, backlighter_data); - if (!rc) - backlight_level = level; - release_console_sem(); - if (!rc && !backlight_autosave) { - level <<=1; - if (level & 0x10) - level |= 0x01; - // -- todo: save to property "bklt" - } - return rc; -} -int set_backlight_level(int level) -{ - if (!backlighter) - return -ENODEV; - backlight_req_level = level; - schedule_work(&backlight_work); - return 0; -} - -EXPORT_SYMBOL(set_backlight_level); - -int get_backlight_level(void) -{ - if (!backlighter) - return -ENODEV; - return backlight_level; -} -EXPORT_SYMBOL(get_backlight_level); - -static void backlight_callback(void *dummy) -{ - int level, enable; - - do { - level = backlight_req_level; - enable = backlight_req_enable; - mb(); - - if (level >= 0) - __set_backlight_level(level); - if (enable >= 0) - __set_backlight_enable(enable); - } while(cmpxchg(&backlight_req_level, level, -1) != level || - cmpxchg(&backlight_req_enable, enable, -1) != enable); -} diff --git a/arch/ppc/platforms/pmac_cache.S b/arch/ppc/platforms/pmac_cache.S deleted file mode 100644 index fb977de6b70..00000000000 --- a/arch/ppc/platforms/pmac_cache.S +++ /dev/null @@ -1,359 +0,0 @@ -/* - * This file contains low-level cache management functions - * used for sleep and CPU speed changes on Apple machines. - * (In fact the only thing that is Apple-specific is that we assume - * that we can read from ROM at physical address 0xfff00000.) - * - * Copyright (C) 2004 Paul Mackerras (paulus@samba.org) and - * Benjamin Herrenschmidt (benh@kernel.crashing.org) - * - * 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 -#include -#include -#include - -/* - * Flush and disable all data caches (dL1, L2, L3). This is used - * when going to sleep, when doing a PMU based cpufreq transition, - * or when "offlining" a CPU on SMP machines. This code is over - * paranoid, but I've had enough issues with various CPU revs and - * bugs that I decided it was worth beeing over cautious - */ - -_GLOBAL(flush_disable_caches) -#ifndef CONFIG_6xx - blr -#else -BEGIN_FTR_SECTION - b flush_disable_745x -END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450) -BEGIN_FTR_SECTION - b flush_disable_75x -END_FTR_SECTION_IFSET(CPU_FTR_L2CR) - b __flush_disable_L1 - -/* This is the code for G3 and 74[01]0 */ -flush_disable_75x: - mflr r10 - - /* Turn off EE and DR in MSR */ - mfmsr r11 - rlwinm r0,r11,0,~MSR_EE - rlwinm r0,r0,0,~MSR_DR - sync - mtmsr r0 - isync - - /* Stop DST streams */ -BEGIN_FTR_SECTION - DSSALL - sync -END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) - - /* Stop DPM */ - mfspr r8,SPRN_HID0 /* Save SPRN_HID0 in r8 */ - rlwinm r4,r8,0,12,10 /* Turn off HID0[DPM] */ - sync - mtspr SPRN_HID0,r4 /* Disable DPM */ - sync - - /* Disp-flush L1. We have a weird problem here that I never - * totally figured out. On 750FX, using the ROM for the flush - * results in a non-working flush. We use that workaround for - * now until I finally understand what's going on. --BenH - */ - - /* ROM base by default */ - lis r4,0xfff0 - mfpvr r3 - srwi r3,r3,16 - cmplwi cr0,r3,0x7000 - bne+ 1f - /* RAM base on 750FX */ - li r4,0 -1: li r4,0x4000 - mtctr r4 -1: lwz r0,0(r4) - addi r4,r4,32 - bdnz 1b - sync - isync - - /* Disable / invalidate / enable L1 data */ - mfspr r3,SPRN_HID0 - rlwinm r3,r3,0,~(HID0_DCE | HID0_ICE) - mtspr SPRN_HID0,r3 - sync - isync - ori r3,r3,(HID0_DCE|HID0_DCI|HID0_ICE|HID0_ICFI) - sync - isync - mtspr SPRN_HID0,r3 - xori r3,r3,(HID0_DCI|HID0_ICFI) - mtspr SPRN_HID0,r3 - sync - - /* Get the current enable bit of the L2CR into r4 */ - mfspr r5,SPRN_L2CR - /* Set to data-only (pre-745x bit) */ - oris r3,r5,L2CR_L2DO@h - b 2f - /* When disabling L2, code must be in L1 */ - .balign 32 -1: mtspr SPRN_L2CR,r3 -3: sync - isync - b 1f -2: b 3f -3: sync - isync - b 1b -1: /* disp-flush L2. The interesting thing here is that the L2 can be - * up to 2Mb ... so using the ROM, we'll end up wrapping back to memory - * but that is probbaly fine. We disp-flush over 4Mb to be safe - */ - lis r4,2 - mtctr r4 - lis r4,0xfff0 -1: lwz r0,0(r4) - addi r4,r4,32 - bdnz 1b - sync - isync - lis r4,2 - mtctr r4 - lis r4,0xfff0 -1: dcbf 0,r4 - addi r4,r4,32 - bdnz 1b - sync - isync - - /* now disable L2 */ - rlwinm r5,r5,0,~L2CR_L2E - b 2f - /* When disabling L2, code must be in L1 */ - .balign 32 -1: mtspr SPRN_L2CR,r5 -3: sync - isync - b 1f -2: b 3f -3: sync - isync - b 1b -1: sync - isync - /* Invalidate L2. This is pre-745x, we clear the L2I bit ourselves */ - oris r4,r5,L2CR_L2I@h - mtspr SPRN_L2CR,r4 - sync - isync - - /* Wait for the invalidation to complete */ -1: mfspr r3,SPRN_L2CR - rlwinm. r0,r3,0,31,31 - bne 1b - - /* Clear L2I */ - xoris r4,r4,L2CR_L2I@h - sync - mtspr SPRN_L2CR,r4 - sync - - /* now disable the L1 data cache */ - mfspr r0,SPRN_HID0 - rlwinm r0,r0,0,~(HID0_DCE|HID0_ICE) - mtspr SPRN_HID0,r0 - sync - isync - - /* Restore HID0[DPM] to whatever it was before */ - sync - mfspr r0,SPRN_HID0 - rlwimi r0,r8,0,11,11 /* Turn back HID0[DPM] */ - mtspr SPRN_HID0,r0 - sync - - /* restore DR and EE */ - sync - mtmsr r11 - isync - - mtlr r10 - blr - -/* This code is for 745x processors */ -flush_disable_745x: - /* Turn off EE and DR in MSR */ - mfmsr r11 - rlwinm r0,r11,0,~MSR_EE - rlwinm r0,r0,0,~MSR_DR - sync - mtmsr r0 - isync - - /* Stop prefetch streams */ - DSSALL - sync - - /* Disable L2 prefetching */ - mfspr r0,SPRN_MSSCR0 - rlwinm r0,r0,0,0,29 - mtspr SPRN_MSSCR0,r0 - sync - isync - lis r4,0 - dcbf 0,r4 - dcbf 0,r4 - dcbf 0,r4 - dcbf 0,r4 - dcbf 0,r4 - dcbf 0,r4 - dcbf 0,r4 - dcbf 0,r4 - - /* Due to a bug with the HW flush on some CPU revs, we occasionally - * experience data corruption. I'm adding a displacement flush along - * with a dcbf loop over a few Mb to "help". The problem isn't totally - * fixed by this in theory, but at least, in practice, I couldn't reproduce - * it even with a big hammer... - */ - - lis r4,0x0002 - mtctr r4 - li r4,0 -1: - lwz r0,0(r4) - addi r4,r4,32 /* Go to start of next cache line */ - bdnz 1b - isync - - /* Now, flush the first 4MB of memory */ - lis r4,0x0002 - mtctr r4 - li r4,0 - sync -1: - dcbf 0,r4 - addi r4,r4,32 /* Go to start of next cache line */ - bdnz 1b - - /* Flush and disable the L1 data cache */ - mfspr r6,SPRN_LDSTCR - lis r3,0xfff0 /* read from ROM for displacement flush */ - li r4,0xfe /* start with only way 0 unlocked */ - li r5,128 /* 128 lines in each way */ -1: mtctr r5 - rlwimi r6,r4,0,24,31 - mtspr SPRN_LDSTCR,r6 - sync - isync -2: lwz r0,0(r3) /* touch each cache line */ - addi r3,r3,32 - bdnz 2b - rlwinm r4,r4,1,24,30 /* move on to the next way */ - ori r4,r4,1 - cmpwi r4,0xff /* all done? */ - bne 1b - /* now unlock the L1 data cache */ - li r4,0 - rlwimi r6,r4,0,24,31 - sync - mtspr SPRN_LDSTCR,r6 - sync - isync - - /* Flush the L2 cache using the hardware assist */ - mfspr r3,SPRN_L2CR - cmpwi r3,0 /* check if it is enabled first */ - bge 4f - oris r0,r3,(L2CR_L2IO_745x|L2CR_L2DO_745x)@h - b 2f - /* When disabling/locking L2, code must be in L1 */ - .balign 32 -1: mtspr SPRN_L2CR,r0 /* lock the L2 cache */ -3: sync - isync - b 1f -2: b 3f -3: sync - isync - b 1b -1: sync - isync - ori r0,r3,L2CR_L2HWF_745x - sync - mtspr SPRN_L2CR,r0 /* set the hardware flush bit */ -3: mfspr r0,SPRN_L2CR /* wait for it to go to 0 */ - andi. r0,r0,L2CR_L2HWF_745x - bne 3b - sync - rlwinm r3,r3,0,~L2CR_L2E - b 2f - /* When disabling L2, code must be in L1 */ - .balign 32 -1: mtspr SPRN_L2CR,r3 /* disable the L2 cache */ -3: sync - isync - b 1f -2: b 3f -3: sync - isync - b 1b -1: sync - isync - oris r4,r3,L2CR_L2I@h - mtspr SPRN_L2CR,r4 - sync - isync -1: mfspr r4,SPRN_L2CR - andis. r0,r4,L2CR_L2I@h - bne 1b - sync - -BEGIN_FTR_SECTION - /* Flush the L3 cache using the hardware assist */ -4: mfspr r3,SPRN_L3CR - cmpwi r3,0 /* check if it is enabled */ - bge 6f - oris r0,r3,L3CR_L3IO@h - ori r0,r0,L3CR_L3DO - sync - mtspr SPRN_L3CR,r0 /* lock the L3 cache */ - sync - isync - ori r0,r0,L3CR_L3HWF - sync - mtspr SPRN_L3CR,r0 /* set the hardware flush bit */ -5: mfspr r0,SPRN_L3CR /* wait for it to go to zero */ - andi. r0,r0,L3CR_L3HWF - bne 5b - rlwinm r3,r3,0,~L3CR_L3E - sync - mtspr SPRN_L3CR,r3 /* disable the L3 cache */ - sync - ori r4,r3,L3CR_L3I - mtspr SPRN_L3CR,r4 -1: mfspr r4,SPRN_L3CR - andi. r0,r4,L3CR_L3I - bne 1b - sync -END_FTR_SECTION_IFSET(CPU_FTR_L3CR) - -6: mfspr r0,SPRN_HID0 /* now disable the L1 data cache */ - rlwinm r0,r0,0,~HID0_DCE - mtspr SPRN_HID0,r0 - sync - isync - mtmsr r11 /* restore DR and EE */ - isync - blr -#endif /* CONFIG_6xx */ diff --git a/arch/ppc/platforms/pmac_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c deleted file mode 100644 index fba7e4d7c0b..00000000000 --- a/arch/ppc/platforms/pmac_cpufreq.c +++ /dev/null @@ -1,735 +0,0 @@ -/* - * arch/ppc/platforms/pmac_cpufreq.c - * - * Copyright (C) 2002 - 2005 Benjamin Herrenschmidt - * Copyright (C) 2004 John Steele Scott - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * TODO: Need a big cleanup here. Basically, we need to have different - * cpufreq_driver structures for the different type of HW instead of the - * current mess. We also need to better deal with the detection of the - * type of machine. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* WARNING !!! This will cause calibrate_delay() to be called, - * but this is an __init function ! So you MUST go edit - * init/main.c to make it non-init before enabling DEBUG_FREQ - */ -#undef DEBUG_FREQ - -/* - * There is a problem with the core cpufreq code on SMP kernels, - * it won't recalculate the Bogomips properly - */ -#ifdef CONFIG_SMP -#warning "WARNING, CPUFREQ not recommended on SMP kernels" -#endif - -extern void low_choose_7447a_dfs(int dfs); -extern void low_choose_750fx_pll(int pll); -extern void low_sleep_handler(void); - -/* - * Currently, PowerMac cpufreq supports only high & low frequencies - * that are set by the firmware - */ -static unsigned int low_freq; -static unsigned int hi_freq; -static unsigned int cur_freq; -static unsigned int sleep_freq; - -/* - * Different models uses different mecanisms to switch the frequency - */ -static int (*set_speed_proc)(int low_speed); -static unsigned int (*get_speed_proc)(void); - -/* - * Some definitions used by the various speedprocs - */ -static u32 voltage_gpio; -static u32 frequency_gpio; -static u32 slew_done_gpio; -static int no_schedule; -static int has_cpu_l2lve; -static int is_pmu_based; - -/* There are only two frequency states for each processor. Values - * are in kHz for the time being. - */ -#define CPUFREQ_HIGH 0 -#define CPUFREQ_LOW 1 - -static struct cpufreq_frequency_table pmac_cpu_freqs[] = { - {CPUFREQ_HIGH, 0}, - {CPUFREQ_LOW, 0}, - {0, CPUFREQ_TABLE_END}, -}; - -static struct freq_attr* pmac_cpu_freqs_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - -static inline void local_delay(unsigned long ms) -{ - if (no_schedule) - mdelay(ms); - else - msleep(ms); -} - -static inline void wakeup_decrementer(void) -{ - set_dec(tb_ticks_per_jiffy); - /* No currently-supported powerbook has a 601, - * so use get_tbl, not native - */ - last_jiffy_stamp(0) = tb_last_stamp = get_tbl(); -} - -#ifdef DEBUG_FREQ -static inline void debug_calc_bogomips(void) -{ - /* This will cause a recalc of bogomips and display the - * result. We backup/restore the value to avoid affecting the - * core cpufreq framework's own calculation. - */ - extern void calibrate_delay(void); - - unsigned long save_lpj = loops_per_jiffy; - calibrate_delay(); - loops_per_jiffy = save_lpj; -} -#endif /* DEBUG_FREQ */ - -/* Switch CPU speed under 750FX CPU control - */ -static int cpu_750fx_cpu_speed(int low_speed) -{ - u32 hid2; - - if (low_speed == 0) { - /* ramping up, set voltage first */ - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); - /* Make sure we sleep for at least 1ms */ - local_delay(10); - - /* tweak L2 for high voltage */ - if (has_cpu_l2lve) { - hid2 = mfspr(SPRN_HID2); - hid2 &= ~0x2000; - mtspr(SPRN_HID2, hid2); - } - } -#ifdef CONFIG_6xx - low_choose_750fx_pll(low_speed); -#endif - if (low_speed == 1) { - /* tweak L2 for low voltage */ - if (has_cpu_l2lve) { - hid2 = mfspr(SPRN_HID2); - hid2 |= 0x2000; - mtspr(SPRN_HID2, hid2); - } - - /* ramping down, set voltage last */ - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); - local_delay(10); - } - - return 0; -} - -static unsigned int cpu_750fx_get_cpu_speed(void) -{ - if (mfspr(SPRN_HID1) & HID1_PS) - return low_freq; - else - return hi_freq; -} - -/* Switch CPU speed using DFS */ -static int dfs_set_cpu_speed(int low_speed) -{ - if (low_speed == 0) { - /* ramping up, set voltage first */ - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); - /* Make sure we sleep for at least 1ms */ - local_delay(1); - } - - /* set frequency */ -#ifdef CONFIG_6xx - low_choose_7447a_dfs(low_speed); -#endif - udelay(100); - - if (low_speed == 1) { - /* ramping down, set voltage last */ - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); - local_delay(1); - } - - return 0; -} - -static unsigned int dfs_get_cpu_speed(void) -{ - if (mfspr(SPRN_HID1) & HID1_DFS) - return low_freq; - else - return hi_freq; -} - - -/* Switch CPU speed using slewing GPIOs - */ -static int gpios_set_cpu_speed(int low_speed) -{ - int gpio, timeout = 0; - - /* If ramping up, set voltage first */ - if (low_speed == 0) { - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); - /* Delay is way too big but it's ok, we schedule */ - local_delay(10); - } - - /* Set frequency */ - gpio = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0); - if (low_speed == ((gpio & 0x01) == 0)) - goto skip; - - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, frequency_gpio, - low_speed ? 0x04 : 0x05); - udelay(200); - do { - if (++timeout > 100) - break; - local_delay(1); - gpio = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, slew_done_gpio, 0); - } while((gpio & 0x02) == 0); - skip: - /* If ramping down, set voltage last */ - if (low_speed == 1) { - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); - /* Delay is way too big but it's ok, we schedule */ - local_delay(10); - } - -#ifdef DEBUG_FREQ - debug_calc_bogomips(); -#endif - - return 0; -} - -/* Switch CPU speed under PMU control - */ -static int pmu_set_cpu_speed(int low_speed) -{ - struct adb_request req; - unsigned long save_l2cr; - unsigned long save_l3cr; - unsigned int pic_prio; - unsigned long flags; - - preempt_disable(); - -#ifdef DEBUG_FREQ - printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1)); -#endif - pmu_suspend(); - - /* Disable all interrupt sources on openpic */ - pic_prio = openpic_get_priority(); - openpic_set_priority(0xf); - - /* Make sure the decrementer won't interrupt us */ - asm volatile("mtdec %0" : : "r" (0x7fffffff)); - /* Make sure any pending DEC interrupt occuring while we did - * the above didn't re-enable the DEC */ - mb(); - asm volatile("mtdec %0" : : "r" (0x7fffffff)); - - /* We can now disable MSR_EE */ - local_irq_save(flags); - - /* Giveup the FPU & vec */ - enable_kernel_fp(); - -#ifdef CONFIG_ALTIVEC - if (cpu_has_feature(CPU_FTR_ALTIVEC)) - enable_kernel_altivec(); -#endif /* CONFIG_ALTIVEC */ - - /* Save & disable L2 and L3 caches */ - save_l3cr = _get_L3CR(); /* (returns -1 if not available) */ - save_l2cr = _get_L2CR(); /* (returns -1 if not available) */ - - /* Send the new speed command. My assumption is that this command - * will cause PLL_CFG[0..3] to be changed next time CPU goes to sleep - */ - pmu_request(&req, NULL, 6, PMU_CPU_SPEED, 'W', 'O', 'O', 'F', low_speed); - while (!req.complete) - pmu_poll(); - - /* Prepare the northbridge for the speed transition */ - pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,1); - - /* Call low level code to backup CPU state and recover from - * hardware reset - */ - low_sleep_handler(); - - /* Restore the northbridge */ - pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,0); - - /* Restore L2 cache */ - if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0) - _set_L2CR(save_l2cr); - /* Restore L3 cache */ - if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0) - _set_L3CR(save_l3cr); - - /* Restore userland MMU context */ - set_context(current->active_mm->context, current->active_mm->pgd); - -#ifdef DEBUG_FREQ - printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1)); -#endif - - /* Restore low level PMU operations */ - pmu_unlock(); - - /* Restore decrementer */ - wakeup_decrementer(); - - /* Restore interrupts */ - openpic_set_priority(pic_prio); - - /* Let interrupts flow again ... */ - local_irq_restore(flags); - -#ifdef DEBUG_FREQ - debug_calc_bogomips(); -#endif - - pmu_resume(); - - preempt_enable(); - - return 0; -} - -static int do_set_cpu_speed(int speed_mode, int notify) -{ - struct cpufreq_freqs freqs; - unsigned long l3cr; - static unsigned long prev_l3cr; - - freqs.old = cur_freq; - freqs.new = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq; - freqs.cpu = smp_processor_id(); - - if (freqs.old == freqs.new) - return 0; - - if (notify) - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - if (speed_mode == CPUFREQ_LOW && - cpu_has_feature(CPU_FTR_L3CR)) { - l3cr = _get_L3CR(); - if (l3cr & L3CR_L3E) { - prev_l3cr = l3cr; - _set_L3CR(0); - } - } - set_speed_proc(speed_mode == CPUFREQ_LOW); - if (speed_mode == CPUFREQ_HIGH && - cpu_has_feature(CPU_FTR_L3CR)) { - l3cr = _get_L3CR(); - if ((prev_l3cr & L3CR_L3E) && l3cr != prev_l3cr) - _set_L3CR(prev_l3cr); - } - if (notify) - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - cur_freq = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq; - - return 0; -} - -static unsigned int pmac_cpufreq_get_speed(unsigned int cpu) -{ - return cur_freq; -} - -static int pmac_cpufreq_verify(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, pmac_cpu_freqs); -} - -static int pmac_cpufreq_target( struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) -{ - unsigned int newstate = 0; - - if (cpufreq_frequency_table_target(policy, pmac_cpu_freqs, - target_freq, relation, &newstate)) - return -EINVAL; - - return do_set_cpu_speed(newstate, 1); -} - -unsigned int pmac_get_one_cpufreq(int i) -{ - /* Supports only one CPU for now */ - return (i == 0) ? cur_freq : 0; -} - -static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy) -{ - if (policy->cpu != 0) - return -ENODEV; - - policy->governor = CPUFREQ_DEFAULT_GOVERNOR; - policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; - policy->cur = cur_freq; - - cpufreq_frequency_table_get_attr(pmac_cpu_freqs, policy->cpu); - return cpufreq_frequency_table_cpuinfo(policy, pmac_cpu_freqs); -} - -static u32 read_gpio(struct device_node *np) -{ - u32 *reg = (u32 *)get_property(np, "reg", NULL); - u32 offset; - - if (reg == NULL) - return 0; - /* That works for all keylargos but shall be fixed properly - * some day... The problem is that it seems we can't rely - * on the "reg" property of the GPIO nodes, they are either - * relative to the base of KeyLargo or to the base of the - * GPIO space, and the device-tree doesn't help. - */ - offset = *reg; - if (offset < KEYLARGO_GPIO_LEVELS0) - offset += KEYLARGO_GPIO_LEVELS0; - return offset; -} - -static int pmac_cpufreq_suspend(struct cpufreq_policy *policy, pm_message_t pmsg) -{ - /* Ok, this could be made a bit smarter, but let's be robust for now. We - * always force a speed change to high speed before sleep, to make sure - * we have appropriate voltage and/or bus speed for the wakeup process, - * and to make sure our loops_per_jiffies are "good enough", that is will - * not cause too short delays if we sleep in low speed and wake in high - * speed.. - */ - no_schedule = 1; - sleep_freq = cur_freq; - if (cur_freq == low_freq && !is_pmu_based) - do_set_cpu_speed(CPUFREQ_HIGH, 0); - return 0; -} - -static int pmac_cpufreq_resume(struct cpufreq_policy *policy) -{ - /* If we resume, first check if we have a get() function */ - if (get_speed_proc) - cur_freq = get_speed_proc(); - else - cur_freq = 0; - - /* We don't, hrm... we don't really know our speed here, best - * is that we force a switch to whatever it was, which is - * probably high speed due to our suspend() routine - */ - do_set_cpu_speed(sleep_freq == low_freq ? - CPUFREQ_LOW : CPUFREQ_HIGH, 0); - - no_schedule = 0; - return 0; -} - -static struct cpufreq_driver pmac_cpufreq_driver = { - .verify = pmac_cpufreq_verify, - .target = pmac_cpufreq_target, - .get = pmac_cpufreq_get_speed, - .init = pmac_cpufreq_cpu_init, - .suspend = pmac_cpufreq_suspend, - .resume = pmac_cpufreq_resume, - .flags = CPUFREQ_PM_NO_WARN, - .attr = pmac_cpu_freqs_attr, - .name = "powermac", - .owner = THIS_MODULE, -}; - - -static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode) -{ - struct device_node *volt_gpio_np = of_find_node_by_name(NULL, - "voltage-gpio"); - struct device_node *freq_gpio_np = of_find_node_by_name(NULL, - "frequency-gpio"); - struct device_node *slew_done_gpio_np = of_find_node_by_name(NULL, - "slewing-done"); - u32 *value; - - /* - * Check to see if it's GPIO driven or PMU only - * - * The way we extract the GPIO address is slightly hackish, but it - * works well enough for now. We need to abstract the whole GPIO - * stuff sooner or later anyway - */ - - if (volt_gpio_np) - voltage_gpio = read_gpio(volt_gpio_np); - if (freq_gpio_np) - frequency_gpio = read_gpio(freq_gpio_np); - if (slew_done_gpio_np) - slew_done_gpio = read_gpio(slew_done_gpio_np); - - /* If we use the frequency GPIOs, calculate the min/max speeds based - * on the bus frequencies - */ - if (frequency_gpio && slew_done_gpio) { - int lenp, rc; - u32 *freqs, *ratio; - - freqs = (u32 *)get_property(cpunode, "bus-frequencies", &lenp); - lenp /= sizeof(u32); - if (freqs == NULL || lenp != 2) { - printk(KERN_ERR "cpufreq: bus-frequencies incorrect or missing\n"); - return 1; - } - ratio = (u32 *)get_property(cpunode, "processor-to-bus-ratio*2", NULL); - if (ratio == NULL) { - printk(KERN_ERR "cpufreq: processor-to-bus-ratio*2 missing\n"); - return 1; - } - - /* Get the min/max bus frequencies */ - low_freq = min(freqs[0], freqs[1]); - hi_freq = max(freqs[0], freqs[1]); - - /* Grrrr.. It _seems_ that the device-tree is lying on the low bus - * frequency, it claims it to be around 84Mhz on some models while - * it appears to be approx. 101Mhz on all. Let's hack around here... - * fortunately, we don't need to be too precise - */ - if (low_freq < 98000000) - low_freq = 101000000; - - /* Convert those to CPU core clocks */ - low_freq = (low_freq * (*ratio)) / 2000; - hi_freq = (hi_freq * (*ratio)) / 2000; - - /* Now we get the frequencies, we read the GPIO to see what is out current - * speed - */ - rc = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0); - cur_freq = (rc & 0x01) ? hi_freq : low_freq; - - set_speed_proc = gpios_set_cpu_speed; - return 1; - } - - /* If we use the PMU, look for the min & max frequencies in the - * device-tree - */ - value = (u32 *)get_property(cpunode, "min-clock-frequency", NULL); - if (!value) - return 1; - low_freq = (*value) / 1000; - /* The PowerBook G4 12" (PowerBook6,1) has an error in the device-tree - * here */ - if (low_freq < 100000) - low_freq *= 10; - - value = (u32 *)get_property(cpunode, "max-clock-frequency", NULL); - if (!value) - return 1; - hi_freq = (*value) / 1000; - set_speed_proc = pmu_set_cpu_speed; - is_pmu_based = 1; - - return 0; -} - -static int pmac_cpufreq_init_7447A(struct device_node *cpunode) -{ - struct device_node *volt_gpio_np; - - if (get_property(cpunode, "dynamic-power-step", NULL) == NULL) - return 1; - - volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select"); - if (volt_gpio_np) - voltage_gpio = read_gpio(volt_gpio_np); - if (!voltage_gpio){ - printk(KERN_ERR "cpufreq: missing cpu-vcore-select gpio\n"); - return 1; - } - - /* OF only reports the high frequency */ - hi_freq = cur_freq; - low_freq = cur_freq/2; - - /* Read actual frequency from CPU */ - cur_freq = dfs_get_cpu_speed(); - set_speed_proc = dfs_set_cpu_speed; - get_speed_proc = dfs_get_cpu_speed; - - return 0; -} - -static int pmac_cpufreq_init_750FX(struct device_node *cpunode) -{ - struct device_node *volt_gpio_np; - u32 pvr, *value; - - if (get_property(cpunode, "dynamic-power-step", NULL) == NULL) - return 1; - - hi_freq = cur_freq; - value = (u32 *)get_property(cpunode, "reduced-clock-frequency", NULL); - if (!value) - return 1; - low_freq = (*value) / 1000; - - volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select"); - if (volt_gpio_np) - voltage_gpio = read_gpio(volt_gpio_np); - - pvr = mfspr(SPRN_PVR); - has_cpu_l2lve = !((pvr & 0xf00) == 0x100); - - set_speed_proc = cpu_750fx_cpu_speed; - get_speed_proc = cpu_750fx_get_cpu_speed; - cur_freq = cpu_750fx_get_cpu_speed(); - - return 0; -} - -/* Currently, we support the following machines: - * - * - Titanium PowerBook 1Ghz (PMU based, 667Mhz & 1Ghz) - * - Titanium PowerBook 800 (PMU based, 667Mhz & 800Mhz) - * - Titanium PowerBook 400 (PMU based, 300Mhz & 400Mhz) - * - Titanium PowerBook 500 (PMU based, 300Mhz & 500Mhz) - * - iBook2 500/600 (PMU based, 400Mhz & 500/600Mhz) - * - iBook2 700 (CPU based, 400Mhz & 700Mhz, support low voltage) - * - Recent MacRISC3 laptops - * - All new machines with 7447A CPUs - */ -static int __init pmac_cpufreq_setup(void) -{ - struct device_node *cpunode; - u32 *value; - - if (strstr(cmd_line, "nocpufreq")) - return 0; - - /* Assume only one CPU */ - cpunode = find_type_devices("cpu"); - if (!cpunode) - goto out; - - /* Get current cpu clock freq */ - value = (u32 *)get_property(cpunode, "clock-frequency", NULL); - if (!value) - goto out; - cur_freq = (*value) / 1000; - - /* Check for 7447A based MacRISC3 */ - if (machine_is_compatible("MacRISC3") && - get_property(cpunode, "dynamic-power-step", NULL) && - PVR_VER(mfspr(SPRN_PVR)) == 0x8003) { - pmac_cpufreq_init_7447A(cpunode); - /* Check for other MacRISC3 machines */ - } else if (machine_is_compatible("PowerBook3,4") || - machine_is_compatible("PowerBook3,5") || - machine_is_compatible("MacRISC3")) { - pmac_cpufreq_init_MacRISC3(cpunode); - /* Else check for iBook2 500/600 */ - } else if (machine_is_compatible("PowerBook4,1")) { - hi_freq = cur_freq; - low_freq = 400000; - set_speed_proc = pmu_set_cpu_speed; - is_pmu_based = 1; - } - /* Else check for TiPb 550 */ - else if (machine_is_compatible("PowerBook3,3") && cur_freq == 550000) { - hi_freq = cur_freq; - low_freq = 500000; - set_speed_proc = pmu_set_cpu_speed; - is_pmu_based = 1; - } - /* Else check for TiPb 400 & 500 */ - else if (machine_is_compatible("PowerBook3,2")) { - /* We only know about the 400 MHz and the 500Mhz model - * they both have 300 MHz as low frequency - */ - if (cur_freq < 350000 || cur_freq > 550000) - goto out; - hi_freq = cur_freq; - low_freq = 300000; - set_speed_proc = pmu_set_cpu_speed; - is_pmu_based = 1; - } - /* Else check for 750FX */ - else if (PVR_VER(mfspr(SPRN_PVR)) == 0x7000) - pmac_cpufreq_init_750FX(cpunode); -out: - if (set_speed_proc == NULL) - return -ENODEV; - - pmac_cpu_freqs[CPUFREQ_LOW].frequency = low_freq; - pmac_cpu_freqs[CPUFREQ_HIGH].frequency = hi_freq; - - printk(KERN_INFO "Registering PowerMac CPU frequency driver\n"); - printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Boot: %d Mhz\n", - low_freq/1000, hi_freq/1000, cur_freq/1000); - - return cpufreq_register_driver(&pmac_cpufreq_driver); -} - -module_init(pmac_cpufreq_setup); - diff --git a/arch/ppc/platforms/pmac_feature.c b/arch/ppc/platforms/pmac_feature.c deleted file mode 100644 index 6b7b3a15063..00000000000 --- a/arch/ppc/platforms/pmac_feature.c +++ /dev/null @@ -1,3023 +0,0 @@ -/* - * arch/ppc/platforms/pmac_feature.c - * - * Copyright (C) 1996-2001 Paul Mackerras (paulus@cs.anu.edu.au) - * Ben. Herrenschmidt (benh@kernel.crashing.org) - * - * 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. - * - * TODO: - * - * - Replace mdelay with some schedule loop if possible - * - Shorten some obfuscated delays on some routines (like modem - * power) - * - Refcount some clocks (see darwin) - * - Split split split... - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#undef DEBUG_FEATURE - -#ifdef DEBUG_FEATURE -#define DBG(fmt,...) printk(KERN_DEBUG fmt) -#else -#define DBG(fmt,...) -#endif - -#ifdef CONFIG_6xx -extern int powersave_lowspeed; -#endif - -extern int powersave_nap; -extern struct device_node *k2_skiplist[2]; - - -/* - * We use a single global lock to protect accesses. Each driver has - * to take care of its own locking - */ -static DEFINE_SPINLOCK(feature_lock); - -#define LOCK(flags) spin_lock_irqsave(&feature_lock, flags); -#define UNLOCK(flags) spin_unlock_irqrestore(&feature_lock, flags); - - -/* - * Instance of some macio stuffs - */ -struct macio_chip macio_chips[MAX_MACIO_CHIPS]; - -struct macio_chip* macio_find(struct device_node* child, int type) -{ - while(child) { - int i; - - for (i=0; i < MAX_MACIO_CHIPS && macio_chips[i].of_node; i++) - if (child == macio_chips[i].of_node && - (!type || macio_chips[i].type == type)) - return &macio_chips[i]; - child = child->parent; - } - return NULL; -} -EXPORT_SYMBOL_GPL(macio_find); - -static const char* macio_names[] = -{ - "Unknown", - "Grand Central", - "OHare", - "OHareII", - "Heathrow", - "Gatwick", - "Paddington", - "Keylargo", - "Pangea", - "Intrepid", - "K2" -}; - - - -/* - * Uninorth reg. access. Note that Uni-N regs are big endian - */ - -#define UN_REG(r) (uninorth_base + ((r) >> 2)) -#define UN_IN(r) (in_be32(UN_REG(r))) -#define UN_OUT(r,v) (out_be32(UN_REG(r), (v))) -#define UN_BIS(r,v) (UN_OUT((r), UN_IN(r) | (v))) -#define UN_BIC(r,v) (UN_OUT((r), UN_IN(r) & ~(v))) - -static struct device_node* uninorth_node; -static u32 __iomem * uninorth_base; -static u32 uninorth_rev; -static int uninorth_u3; -static void __iomem *u3_ht; - -/* - * For each motherboard family, we have a table of functions pointers - * that handle the various features. - */ - -typedef long (*feature_call)(struct device_node* node, long param, long value); - -struct feature_table_entry { - unsigned int selector; - feature_call function; -}; - -struct pmac_mb_def -{ - const char* model_string; - const char* model_name; - int model_id; - struct feature_table_entry* features; - unsigned long board_flags; -}; -static struct pmac_mb_def pmac_mb; - -/* - * Here are the chip specific feature functions - */ - -static inline int -simple_feature_tweak(struct device_node* node, int type, int reg, u32 mask, int value) -{ - struct macio_chip* macio; - unsigned long flags; - - macio = macio_find(node, type); - if (!macio) - return -ENODEV; - LOCK(flags); - if (value) - MACIO_BIS(reg, mask); - else - MACIO_BIC(reg, mask); - (void)MACIO_IN32(reg); - UNLOCK(flags); - - return 0; -} - -#ifndef CONFIG_POWER4 - -static long -ohare_htw_scc_enable(struct device_node* node, long param, long value) -{ - struct macio_chip* macio; - unsigned long chan_mask; - unsigned long fcr; - unsigned long flags; - int htw, trans; - unsigned long rmask; - - macio = macio_find(node, 0); - if (!macio) - return -ENODEV; - if (!strcmp(node->name, "ch-a")) - chan_mask = MACIO_FLAG_SCCA_ON; - else if (!strcmp(node->name, "ch-b")) - chan_mask = MACIO_FLAG_SCCB_ON; - else - return -ENODEV; - - htw = (macio->type == macio_heathrow || macio->type == macio_paddington - || macio->type == macio_gatwick); - /* On these machines, the HRW_SCC_TRANS_EN_N bit mustn't be touched */ - trans = (pmac_mb.model_id != PMAC_TYPE_YOSEMITE && - pmac_mb.model_id != PMAC_TYPE_YIKES); - if (value) { -#ifdef CONFIG_ADB_PMU - if ((param & 0xfff) == PMAC_SCC_IRDA) - pmu_enable_irled(1); -#endif /* CONFIG_ADB_PMU */ - LOCK(flags); - fcr = MACIO_IN32(OHARE_FCR); - /* Check if scc cell need enabling */ - if (!(fcr & OH_SCC_ENABLE)) { - fcr |= OH_SCC_ENABLE; - if (htw) { - /* Side effect: this will also power up the - * modem, but it's too messy to figure out on which - * ports this controls the tranceiver and on which - * it controls the modem - */ - if (trans) - fcr &= ~HRW_SCC_TRANS_EN_N; - MACIO_OUT32(OHARE_FCR, fcr); - fcr |= (rmask = HRW_RESET_SCC); - MACIO_OUT32(OHARE_FCR, fcr); - } else { - fcr |= (rmask = OH_SCC_RESET); - MACIO_OUT32(OHARE_FCR, fcr); - } - UNLOCK(flags); - (void)MACIO_IN32(OHARE_FCR); - mdelay(15); - LOCK(flags); - fcr &= ~rmask; - MACIO_OUT32(OHARE_FCR, fcr); - } - if (chan_mask & MACIO_FLAG_SCCA_ON) - fcr |= OH_SCCA_IO; - if (chan_mask & MACIO_FLAG_SCCB_ON) - fcr |= OH_SCCB_IO; - MACIO_OUT32(OHARE_FCR, fcr); - macio->flags |= chan_mask; - UNLOCK(flags); - if (param & PMAC_SCC_FLAG_XMON) - macio->flags |= MACIO_FLAG_SCC_LOCKED; - } else { - if (macio->flags & MACIO_FLAG_SCC_LOCKED) - return -EPERM; - LOCK(flags); - fcr = MACIO_IN32(OHARE_FCR); - if (chan_mask & MACIO_FLAG_SCCA_ON) - fcr &= ~OH_SCCA_IO; - if (chan_mask & MACIO_FLAG_SCCB_ON) - fcr &= ~OH_SCCB_IO; - MACIO_OUT32(OHARE_FCR, fcr); - if ((fcr & (OH_SCCA_IO | OH_SCCB_IO)) == 0) { - fcr &= ~OH_SCC_ENABLE; - if (htw && trans) - fcr |= HRW_SCC_TRANS_EN_N; - MACIO_OUT32(OHARE_FCR, fcr); - } - macio->flags &= ~(chan_mask); - UNLOCK(flags); - mdelay(10); -#ifdef CONFIG_ADB_PMU - if ((param & 0xfff) == PMAC_SCC_IRDA) - pmu_enable_irled(0); -#endif /* CONFIG_ADB_PMU */ - } - return 0; -} - -static long -ohare_floppy_enable(struct device_node* node, long param, long value) -{ - return simple_feature_tweak(node, macio_ohare, - OHARE_FCR, OH_FLOPPY_ENABLE, value); -} - -static long -ohare_mesh_enable(struct device_node* node, long param, long value) -{ - return simple_feature_tweak(node, macio_ohare, - OHARE_FCR, OH_MESH_ENABLE, value); -} - -static long -ohare_ide_enable(struct device_node* node, long param, long value) -{ - switch(param) { - case 0: - /* For some reason, setting the bit in set_initial_features() - * doesn't stick. I'm still investigating... --BenH. - */ - if (value) - simple_feature_tweak(node, macio_ohare, - OHARE_FCR, OH_IOBUS_ENABLE, 1); - return simple_feature_tweak(node, macio_ohare, - OHARE_FCR, OH_IDE0_ENABLE, value); - case 1: - return simple_feature_tweak(node, macio_ohare, - OHARE_FCR, OH_BAY_IDE_ENABLE, value); - default: - return -ENODEV; - } -} - -static long -ohare_ide_reset(struct device_node* node, long param, long value) -{ - switch(param) { - case 0: - return simple_feature_tweak(node, macio_ohare, - OHARE_FCR, OH_IDE0_RESET_N, !value); - case 1: - return simple_feature_tweak(node, macio_ohare, - OHARE_FCR, OH_IDE1_RESET_N, !value); - default: - return -ENODEV; - } -} - -static long -ohare_sleep_state(struct device_node* node, long param, long value) -{ - struct macio_chip* macio = &macio_chips[0]; - - if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0) - return -EPERM; - if (value == 1) { - MACIO_BIC(OHARE_FCR, OH_IOBUS_ENABLE); - } else if (value == 0) { - MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); - } - - return 0; -} - -static long -heathrow_modem_enable(struct device_node* node, long param, long value) -{ - struct macio_chip* macio; - u8 gpio; - unsigned long flags; - - macio = macio_find(node, macio_unknown); - if (!macio) - return -ENODEV; - gpio = MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1; - if (!value) { - LOCK(flags); - MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio); - UNLOCK(flags); - (void)MACIO_IN8(HRW_GPIO_MODEM_RESET); - mdelay(250); - } - if (pmac_mb.model_id != PMAC_TYPE_YOSEMITE && - pmac_mb.model_id != PMAC_TYPE_YIKES) { - LOCK(flags); - if (value) - MACIO_BIC(HEATHROW_FCR, HRW_SCC_TRANS_EN_N); - else - MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N); - UNLOCK(flags); - (void)MACIO_IN32(HEATHROW_FCR); - mdelay(250); - } - if (value) { - LOCK(flags); - MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1); - (void)MACIO_IN8(HRW_GPIO_MODEM_RESET); - UNLOCK(flags); mdelay(250); LOCK(flags); - MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio); - (void)MACIO_IN8(HRW_GPIO_MODEM_RESET); - UNLOCK(flags); mdelay(250); LOCK(flags); - MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1); - (void)MACIO_IN8(HRW_GPIO_MODEM_RESET); - UNLOCK(flags); mdelay(250); - } - return 0; -} - -static long -heathrow_floppy_enable(struct device_node* node, long param, long value) -{ - return simple_feature_tweak(node, macio_unknown, - HEATHROW_FCR, - HRW_SWIM_ENABLE|HRW_BAY_FLOPPY_ENABLE, - value); -} - -static long -heathrow_mesh_enable(struct device_node* node, long param, long value) -{ - struct macio_chip* macio; - unsigned long flags; - - macio = macio_find(node, macio_unknown); - if (!macio) - return -ENODEV; - LOCK(flags); - /* Set clear mesh cell enable */ - if (value) - MACIO_BIS(HEATHROW_FCR, HRW_MESH_ENABLE); - else - MACIO_BIC(HEATHROW_FCR, HRW_MESH_ENABLE); - (void)MACIO_IN32(HEATHROW_FCR); - udelay(10); - /* Set/Clear termination power */ - if (value) - MACIO_BIC(HEATHROW_MBCR, 0x04000000); - else - MACIO_BIS(HEATHROW_MBCR, 0x04000000); - (void)MACIO_IN32(HEATHROW_MBCR); - udelay(10); - UNLOCK(flags); - - return 0; -} - -static long -heathrow_ide_enable(struct device_node* node, long param, long value) -{ - switch(param) { - case 0: - return simple_feature_tweak(node, macio_unknown, - HEATHROW_FCR, HRW_IDE0_ENABLE, value); - case 1: - return simple_feature_tweak(node, macio_unknown, - HEATHROW_FCR, HRW_BAY_IDE_ENABLE, value); - default: - return -ENODEV; - } -} - -static long -heathrow_ide_reset(struct device_node* node, long param, long value) -{ - switch(param) { - case 0: - return simple_feature_tweak(node, macio_unknown, - HEATHROW_FCR, HRW_IDE0_RESET_N, !value); - case 1: - return simple_feature_tweak(node, macio_unknown, - HEATHROW_FCR, HRW_IDE1_RESET_N, !value); - default: - return -ENODEV; - } -} - -static long -heathrow_bmac_enable(struct device_node* node, long param, long value) -{ - struct macio_chip* macio; - unsigned long flags; - - macio = macio_find(node, 0); - if (!macio) - return -ENODEV; - if (value) { - LOCK(flags); - MACIO_BIS(HEATHROW_FCR, HRW_BMAC_IO_ENABLE); - MACIO_BIS(HEATHROW_FCR, HRW_BMAC_RESET); - UNLOCK(flags); - (void)MACIO_IN32(HEATHROW_FCR); - mdelay(10); - LOCK(flags); - MACIO_BIC(HEATHROW_FCR, HRW_BMAC_RESET); - UNLOCK(flags); - (void)MACIO_IN32(HEATHROW_FCR); - mdelay(10); - } else { - LOCK(flags); - MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE); - UNLOCK(flags); - } - return 0; -} - -static long -heathrow_sound_enable(struct device_node* node, long param, long value) -{ - struct macio_chip* macio; - unsigned long flags; - - /* B&W G3 and Yikes don't support that properly (the - * sound appear to never come back after beeing shut down). - */ - if (pmac_mb.model_id == PMAC_TYPE_YOSEMITE || - pmac_mb.model_id == PMAC_TYPE_YIKES) - return 0; - - macio = macio_find(node, 0); - if (!macio) - return -ENODEV; - if (value) { - LOCK(flags); - MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE); - MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N); - UNLOCK(flags); - (void)MACIO_IN32(HEATHROW_FCR); - } else { - LOCK(flags); - MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N); - MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE); - UNLOCK(flags); - } - return 0; -} - -static u32 save_fcr[6]; -static u32 save_mbcr; -static u32 save_gpio_levels[2]; -static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT]; -static u8 save_gpio_normal[KEYLARGO_GPIO_CNT]; -static u32 save_unin_clock_ctl; -static struct dbdma_regs save_dbdma[13]; -static struct dbdma_regs save_alt_dbdma[13]; - -static void -dbdma_save(struct macio_chip* macio, struct dbdma_regs* save) -{ - int i; - - /* Save state & config of DBDMA channels */ - for (i=0; i<13; i++) { - volatile struct dbdma_regs __iomem * chan = (void __iomem *) - (macio->base + ((0x8000+i*0x100)>>2)); - save[i].cmdptr_hi = in_le32(&chan->cmdptr_hi); - save[i].cmdptr = in_le32(&chan->cmdptr); - save[i].intr_sel = in_le32(&chan->intr_sel); - save[i].br_sel = in_le32(&chan->br_sel); - save[i].wait_sel = in_le32(&chan->wait_sel); - } -} - -static void -dbdma_restore(struct macio_chip* macio, struct dbdma_regs* save) -{ - int i; - - /* Save state & config of DBDMA channels */ - for (i=0; i<13; i++) { - volatile struct dbdma_regs __iomem * chan = (void __iomem *) - (macio->base + ((0x8000+i*0x100)>>2)); - out_le32(&chan->control, (ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN)<<16); - while (in_le32(&chan->status) & ACTIVE) - mb(); - out_le32(&chan->cmdptr_hi, save[i].cmdptr_hi); - out_le32(&chan->cmdptr, save[i].cmdptr); - out_le32(&chan->intr_sel, save[i].intr_sel); - out_le32(&chan->br_sel, save[i].br_sel); - out_le32(&chan->wait_sel, save[i].wait_sel); - } -} - -static void -heathrow_sleep(struct macio_chip* macio, int secondary) -{ - if (secondary) { - dbdma_save(macio, save_alt_dbdma); - save_fcr[2] = MACIO_IN32(0x38); - save_fcr[3] = MACIO_IN32(0x3c); - } else { - dbdma_save(macio, save_dbdma); - save_fcr[0] = MACIO_IN32(0x38); - save_fcr[1] = MACIO_IN32(0x3c); - save_mbcr = MACIO_IN32(0x34); - /* Make sure sound is shut down */ - MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N); - MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE); - /* This seems to be necessary as well or the fan - * keeps coming up and battery drains fast */ - MACIO_BIC(HEATHROW_FCR, HRW_IOBUS_ENABLE); - MACIO_BIC(HEATHROW_FCR, HRW_IDE0_RESET_N); - /* Make sure eth is down even if module or sleep - * won't work properly */ - MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE | HRW_BMAC_RESET); - } - /* Make sure modem is shut down */ - MACIO_OUT8(HRW_GPIO_MODEM_RESET, - MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1); - MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N); - MACIO_BIC(HEATHROW_FCR, OH_SCCA_IO|OH_SCCB_IO|HRW_SCC_ENABLE); - - /* Let things settle */ - (void)MACIO_IN32(HEATHROW_FCR); -} - -static void -heathrow_wakeup(struct macio_chip* macio, int secondary) -{ - if (secondary) { - MACIO_OUT32(0x38, save_fcr[2]); - (void)MACIO_IN32(0x38); - mdelay(1); - MACIO_OUT32(0x3c, save_fcr[3]); - (void)MACIO_IN32(0x38); - mdelay(10); - dbdma_restore(macio, save_alt_dbdma); - } else { - MACIO_OUT32(0x38, save_fcr[0] | HRW_IOBUS_ENABLE); - (void)MACIO_IN32(0x38); - mdelay(1); - MACIO_OUT32(0x3c, save_fcr[1]); - (void)MACIO_IN32(0x38); - mdelay(1); - MACIO_OUT32(0x34, save_mbcr); - (void)MACIO_IN32(0x38); - mdelay(10); - dbdma_restore(macio, save_dbdma); - } -} - -static long -heathrow_sleep_state(struct device_node* node, long param, long value) -{ - if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0) - return -EPERM; - if (value == 1) { - if (macio_chips[1].type == macio_gatwick) - heathrow_sleep(&macio_chips[0], 1); - heathrow_sleep(&macio_chips[0], 0); - } else if (value == 0) { - heathrow_wakeup(&macio_chips[0], 0); - if (macio_chips[1].type == macio_gatwick) - heathrow_wakeup(&macio_chips[0], 1); - } - return 0; -} - -static long -core99_scc_enable(struct device_node* node, long param, long value) -{ - struct macio_chip* macio; - unsigned long flags; - unsigned long chan_mask; - u32 fcr; - - macio = macio_find(node, 0); - if (!macio) - return -ENODEV; - if (!strcmp(node->name, "ch-a")) - chan_mask = MACIO_FLAG_SCCA_ON; - else if (!strcmp(node->name, "ch-b")) - chan_mask = MACIO_FLAG_SCCB_ON; - else - return -ENODEV; - - if (value) { - int need_reset_scc = 0; - int need_reset_irda = 0; - - LOCK(flags); - fcr = MACIO_IN32(KEYLARGO_FCR0); - /* Check if scc cell need enabling */ - if (!(fcr & KL0_SCC_CELL_ENABLE)) { - fcr |= KL0_SCC_CELL_ENABLE; - need_reset_scc = 1; - } - if (chan_mask & MACIO_FLAG_SCCA_ON) { - fcr |= KL0_SCCA_ENABLE; - /* Don't enable line drivers for I2S modem */ - if ((param & 0xfff) == PMAC_SCC_I2S1) - fcr &= ~KL0_SCC_A_INTF_ENABLE; - else - fcr |= KL0_SCC_A_INTF_ENABLE; - } - if (chan_mask & MACIO_FLAG_SCCB_ON) { - fcr |= KL0_SCCB_ENABLE; - /* Perform irda specific inits */ - if ((param & 0xfff) == PMAC_SCC_IRDA) { - fcr &= ~KL0_SCC_B_INTF_ENABLE; - fcr |= KL0_IRDA_ENABLE; - fcr |= KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE; - fcr |= KL0_IRDA_SOURCE1_SEL; - fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0); - fcr &= ~(KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND); - need_reset_irda = 1; - } else - fcr |= KL0_SCC_B_INTF_ENABLE; - } - MACIO_OUT32(KEYLARGO_FCR0, fcr); - macio->flags |= chan_mask; - if (need_reset_scc) { - MACIO_BIS(KEYLARGO_FCR0, KL0_SCC_RESET); - (void)MACIO_IN32(KEYLARGO_FCR0); - UNLOCK(flags); - mdelay(15); - LOCK(flags); - MACIO_BIC(KEYLARGO_FCR0, KL0_SCC_RESET); - } - if (need_reset_irda) { - MACIO_BIS(KEYLARGO_FCR0, KL0_IRDA_RESET); - (void)MACIO_IN32(KEYLARGO_FCR0); - UNLOCK(flags); - mdelay(15); - LOCK(flags); - MACIO_BIC(KEYLARGO_FCR0, KL0_IRDA_RESET); - } - UNLOCK(flags); - if (param & PMAC_SCC_FLAG_XMON) - macio->flags |= MACIO_FLAG_SCC_LOCKED; - } else { - if (macio->flags & MACIO_FLAG_SCC_LOCKED) - return -EPERM; - LOCK(flags); - fcr = MACIO_IN32(KEYLARGO_FCR0); - if (chan_mask & MACIO_FLAG_SCCA_ON) - fcr &= ~KL0_SCCA_ENABLE; - if (chan_mask & MACIO_FLAG_SCCB_ON) { - fcr &= ~KL0_SCCB_ENABLE; - /* Perform irda specific clears */ - if ((param & 0xfff) == PMAC_SCC_IRDA) { - fcr &= ~KL0_IRDA_ENABLE; - fcr &= ~(KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE); - fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0); - fcr &= ~(KL0_IRDA_SOURCE1_SEL|KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND); - } - } - MACIO_OUT32(KEYLARGO_FCR0, fcr); - if ((fcr & (KL0_SCCA_ENABLE | KL0_SCCB_ENABLE)) == 0) { - fcr &= ~KL0_SCC_CELL_ENABLE; - MACIO_OUT32(KEYLARGO_FCR0, fcr); - } - macio->flags &= ~(chan_mask); - UNLOCK(flags); - mdelay(10); - } - return 0; -} - -static long -core99_modem_enable(struct device_node* node, long param, long value) -{ - struct macio_chip* macio; - u8 gpio; - unsigned long flags; - - /* Hack for internal USB modem */ - if (node == NULL) { - if (macio_chips[0].type != macio_keylargo) - return -ENODEV; - node = macio_chips[0].of_node; - } - macio = macio_find(node, 0); - if (!macio) - return -ENODEV; - gpio = MACIO_IN8(KL_GPIO_MODEM_RESET); - gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE; - gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA; - - if (!value) { - LOCK(flags); - MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); - UNLOCK(flags); - (void)MACIO_IN8(KL_GPIO_MODEM_RESET); - mdelay(250); - } - LOCK(flags); - if (value) { - MACIO_BIC(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); - UNLOCK(flags); - (void)MACIO_IN32(KEYLARGO_FCR2); - mdelay(250); - } else { - MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); - UNLOCK(flags); - } - if (value) { - LOCK(flags); - MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); - (void)MACIO_IN8(KL_GPIO_MODEM_RESET); - UNLOCK(flags); mdelay(250); LOCK(flags); - MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); - (void)MACIO_IN8(KL_GPIO_MODEM_RESET); - UNLOCK(flags); mdelay(250); LOCK(flags); - MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); - (void)MACIO_IN8(KL_GPIO_MODEM_RESET); - UNLOCK(flags); mdelay(250); - } - return 0; -} - -static long -pangea_modem_enable(struct device_node* node, long param, long value) -{ - struct macio_chip* macio; - u8 gpio; - unsigned long flags; - - /* Hack for internal USB modem */ - if (node == NULL) { - if (macio_chips[0].type != macio_pangea && - macio_chips[0].type != macio_intrepid) - return -ENODEV; - node = macio_chips[0].of_node; - } - macio = macio_find(node, 0); - if (!macio) - return -ENODEV; - gpio = MACIO_IN8(KL_GPIO_MODEM_RESET); - gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE; - gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA; - - if (!value) { - LOCK(flags); - MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); - UNLOCK(flags); - (void)MACIO_IN8(KL_GPIO_MODEM_RESET); - mdelay(250); - } - LOCK(flags); - if (value) { - MACIO_OUT8(KL_GPIO_MODEM_POWER, - KEYLARGO_GPIO_OUTPUT_ENABLE); - UNLOCK(flags); - (void)MACIO_IN32(KEYLARGO_FCR2); - mdelay(250); - } else { - MACIO_OUT8(KL_GPIO_MODEM_POWER, - KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA); - UNLOCK(flags); - } - if (value) { - LOCK(flags); - MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); - (void)MACIO_IN8(KL_GPIO_MODEM_RESET); - UNLOCK(flags); mdelay(250); LOCK(flags); - MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); - (void)MACIO_IN8(KL_GPIO_MODEM_RESET); - UNLOCK(flags); mdelay(250); LOCK(flags); - MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); - (void)MACIO_IN8(KL_GPIO_MODEM_RESET); - UNLOCK(flags); mdelay(250); - } - return 0; -} - -static long -core99_ata100_enable(struct device_node* node, long value) -{ - unsigned long flags; - struct pci_dev *pdev = NULL; - u8 pbus, pid; - - if (uninorth_rev < 0x24) - return -ENODEV; - - LOCK(flags); - if (value) - UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100); - else - UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100); - (void)UN_IN(UNI_N_CLOCK_CNTL); - UNLOCK(flags); - udelay(20); - - if (value) { - if (pci_device_from_OF_node(node, &pbus, &pid) == 0) - pdev = pci_find_slot(pbus, pid); - if (pdev == NULL) - return 0; - pci_enable_device(pdev); - pci_set_master(pdev); - } - return 0; -} - -static long -core99_ide_enable(struct device_node* node, long param, long value) -{ - /* Bus ID 0 to 2 are KeyLargo based IDE, busID 3 is U2 - * based ata-100 - */ - switch(param) { - case 0: - return simple_feature_tweak(node, macio_unknown, - KEYLARGO_FCR1, KL1_EIDE0_ENABLE, value); - case 1: - return simple_feature_tweak(node, macio_unknown, - KEYLARGO_FCR1, KL1_EIDE1_ENABLE, value); - case 2: - return simple_feature_tweak(node, macio_unknown, - KEYLARGO_FCR1, KL1_UIDE_ENABLE, value); - case 3: - return core99_ata100_enable(node, value); - default: - return -ENODEV; - } -} - -static long -core99_ide_reset(struct device_node* node, long param, long value) -{ - switch(param) { - case 0: - return simple_feature_tweak(node, macio_unknown, - KEYLARGO_FCR1, KL1_EIDE0_RESET_N, !value); - case 1: - return simple_feature_tweak(node, macio_unknown, - KEYLARGO_FCR1, KL1_EIDE1_RESET_N, !value); - case 2: - return simple_feature_tweak(node, macio_unknown, - KEYLARGO_FCR1, KL1_UIDE_RESET_N, !value); - default: - return -ENODEV; - } -} - -static long -core99_gmac_enable(struct device_node* node, long param, long value) -{ - unsigned long flags; - - LOCK(flags); - if (value) - UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC); - else - UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC); - (void)UN_IN(UNI_N_CLOCK_CNTL); - UNLOCK(flags); - udelay(20); - - return 0; -} - -static long -core99_gmac_phy_reset(struct device_node* node, long param, long value) -{ - unsigned long flags; - struct macio_chip* macio; - - macio = &macio_chips[0]; - if (macio->type != macio_keylargo && macio->type != macio_pangea && - macio->type != macio_intrepid) - return -ENODEV; - - LOCK(flags); - MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE); - (void)MACIO_IN8(KL_GPIO_ETH_PHY_RESET); - UNLOCK(flags); - mdelay(10); - LOCK(flags); - MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, /*KEYLARGO_GPIO_OUTPUT_ENABLE | */ - KEYLARGO_GPIO_OUTOUT_DATA); - UNLOCK(flags); - mdelay(10); - - return 0; -} - -static long -core99_sound_chip_enable(struct device_node* node, long param, long value) -{ - struct macio_chip* macio; - unsigned long flags; - - macio = macio_find(node, 0); - if (!macio) - return -ENODEV; - - /* Do a better probe code, screamer G4 desktops & - * iMacs can do that too, add a recalibrate in - * the driver as well - */ - if (pmac_mb.model_id == PMAC_TYPE_PISMO || - pmac_mb.model_id == PMAC_TYPE_TITANIUM) { - LOCK(flags); - if (value) - MACIO_OUT8(KL_GPIO_SOUND_POWER, - KEYLARGO_GPIO_OUTPUT_ENABLE | - KEYLARGO_GPIO_OUTOUT_DATA); - else - MACIO_OUT8(KL_GPIO_SOUND_POWER, - KEYLARGO_GPIO_OUTPUT_ENABLE); - (void)MACIO_IN8(KL_GPIO_SOUND_POWER); - UNLOCK(flags); - } - return 0; -} - -static long -core99_airport_enable(struct device_node* node, long param, long value) -{ - struct macio_chip* macio; - unsigned long flags; - int state; - - macio = macio_find(node, 0); - if (!macio) - return -ENODEV; - - /* Hint: we allow passing of macio itself for the sake of the - * sleep code - */ - if (node != macio->of_node && - (!node->parent || node->parent != macio->of_node)) - return -ENODEV; - state = (macio->flags & MACIO_FLAG_AIRPORT_ON) != 0; - if (value == state) - return 0; - if (value) { - /* This code is a reproduction of OF enable-cardslot - * and init-wireless methods, slightly hacked until - * I got it working. - */ - LOCK(flags); - MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 5); - (void)MACIO_IN8(KEYLARGO_GPIO_0+0xf); - UNLOCK(flags); - mdelay(10); - LOCK(flags); - MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 4); - (void)MACIO_IN8(KEYLARGO_GPIO_0+0xf); - UNLOCK(flags); - - mdelay(10); - - LOCK(flags); - MACIO_BIC(KEYLARGO_FCR2, KL2_CARDSEL_16); - (void)MACIO_IN32(KEYLARGO_FCR2); - udelay(10); - MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xb, 0); - (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xb); - udelay(10); - MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xa, 0x28); - (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xa); - udelay(10); - MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xd, 0x28); - (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xd); - udelay(10); - MACIO_OUT8(KEYLARGO_GPIO_0+0xd, 0x28); - (void)MACIO_IN8(KEYLARGO_GPIO_0+0xd); - udelay(10); - MACIO_OUT8(KEYLARGO_GPIO_0+0xe, 0x28); - (void)MACIO_IN8(KEYLARGO_GPIO_0+0xe); - UNLOCK(flags); - udelay(10); - MACIO_OUT32(0x1c000, 0); - mdelay(1); - MACIO_OUT8(0x1a3e0, 0x41); - (void)MACIO_IN8(0x1a3e0); - udelay(10); - LOCK(flags); - MACIO_BIS(KEYLARGO_FCR2, KL2_CARDSEL_16); - (void)MACIO_IN32(KEYLARGO_FCR2); - UNLOCK(flags); - mdelay(100); - - macio->flags |= MACIO_FLAG_AIRPORT_ON; - } else { - LOCK(flags); - MACIO_BIC(KEYLARGO_FCR2, KL2_CARDSEL_16); - (void)MACIO_IN32(KEYLARGO_FCR2); - MACIO_OUT8(KL_GPIO_AIRPORT_0, 0); - MACIO_OUT8(KL_GPIO_AIRPORT_1, 0); - MACIO_OUT8(KL_GPIO_AIRPORT_2, 0); - MACIO_OUT8(KL_GPIO_AIRPORT_3, 0); - MACIO_OUT8(KL_GPIO_AIRPORT_4, 0); - (void)MACIO_IN8(KL_GPIO_AIRPORT_4); - UNLOCK(flags); - - macio->flags &= ~MACIO_FLAG_AIRPORT_ON; - } - return 0; -} - -#ifdef CONFIG_SMP -static long -core99_reset_cpu(struct device_node* node, long param, long value) -{ - unsigned int reset_io = 0; - unsigned long flags; - struct macio_chip* macio; - struct device_node* np; - const int dflt_reset_lines[] = { KL_GPIO_RESET_CPU0, - KL_GPIO_RESET_CPU1, - KL_GPIO_RESET_CPU2, - KL_GPIO_RESET_CPU3 }; - - macio = &macio_chips[0]; - if (macio->type != macio_keylargo) - return -ENODEV; - - np = find_path_device("/cpus"); - if (np == NULL) - return -ENODEV; - for (np = np->child; np != NULL; np = np->sibling) { - u32* num = (u32 *)get_property(np, "reg", NULL); - u32* rst = (u32 *)get_property(np, "soft-reset", NULL); - if (num == NULL || rst == NULL) - continue; - if (param == *num) { - reset_io = *rst; - break; - } - } - if (np == NULL || reset_io == 0) - reset_io = dflt_reset_lines[param]; - - LOCK(flags); - MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE); - (void)MACIO_IN8(reset_io); - udelay(1); - MACIO_OUT8(reset_io, 0); - (void)MACIO_IN8(reset_io); - UNLOCK(flags); - - return 0; -} -#endif /* CONFIG_SMP */ - -static long -core99_usb_enable(struct device_node* node, long param, long value) -{ - struct macio_chip* macio; - unsigned long flags; - char* prop; - int number; - u32 reg; - - macio = &macio_chips[0]; - if (macio->type != macio_keylargo && macio->type != macio_pangea && - macio->type != macio_intrepid) - return -ENODEV; - - prop = (char *)get_property(node, "AAPL,clock-id", NULL); - if (!prop) - return -ENODEV; - if (strncmp(prop, "usb0u048", 8) == 0) - number = 0; - else if (strncmp(prop, "usb1u148", 8) == 0) - number = 2; - else if (strncmp(prop, "usb2u248", 8) == 0) - number = 4; - else - return -ENODEV; - - /* Sorry for the brute-force locking, but this is only used during - * sleep and the timing seem to be critical - */ - LOCK(flags); - if (value) { - /* Turn ON */ - if (number == 0) { - MACIO_BIC(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1)); - (void)MACIO_IN32(KEYLARGO_FCR0); - UNLOCK(flags); - mdelay(1); - LOCK(flags); - MACIO_BIS(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE); - } else if (number == 2) { - MACIO_BIC(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1)); - UNLOCK(flags); - (void)MACIO_IN32(KEYLARGO_FCR0); - mdelay(1); - LOCK(flags); - MACIO_BIS(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE); - } else if (number == 4) { - MACIO_BIC(KEYLARGO_FCR1, (KL1_USB2_PAD_SUSPEND0 | KL1_USB2_PAD_SUSPEND1)); - UNLOCK(flags); - (void)MACIO_IN32(KEYLARGO_FCR1); - mdelay(1); - LOCK(flags); - MACIO_BIS(KEYLARGO_FCR1, KL1_USB2_CELL_ENABLE); - } - if (number < 4) { - reg = MACIO_IN32(KEYLARGO_FCR4); - reg &= ~(KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) | - KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number)); - reg &= ~(KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) | - KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1)); - MACIO_OUT32(KEYLARGO_FCR4, reg); - (void)MACIO_IN32(KEYLARGO_FCR4); - udelay(10); - } else { - reg = MACIO_IN32(KEYLARGO_FCR3); - reg &= ~(KL3_IT_PORT_WAKEUP_ENABLE(0) | KL3_IT_PORT_RESUME_WAKE_EN(0) | - KL3_IT_PORT_CONNECT_WAKE_EN(0) | KL3_IT_PORT_DISCONNECT_WAKE_EN(0)); - reg &= ~(KL3_IT_PORT_WAKEUP_ENABLE(1) | KL3_IT_PORT_RESUME_WAKE_EN(1) | - KL3_IT_PORT_CONNECT_WAKE_EN(1) | KL3_IT_PORT_DISCONNECT_WAKE_EN(1)); - MACIO_OUT32(KEYLARGO_FCR3, reg); - (void)MACIO_IN32(KEYLARGO_FCR3); - udelay(10); - } - if (macio->type == macio_intrepid) { - /* wait for clock stopped bits to clear */ - u32 test0 = 0, test1 = 0; - u32 status0, status1; - int timeout = 1000; - - UNLOCK(flags); - switch (number) { - case 0: - test0 = UNI_N_CLOCK_STOPPED_USB0; - test1 = UNI_N_CLOCK_STOPPED_USB0PCI; - break; - case 2: - test0 = UNI_N_CLOCK_STOPPED_USB1; - test1 = UNI_N_CLOCK_STOPPED_USB1PCI; - break; - case 4: - test0 = UNI_N_CLOCK_STOPPED_USB2; - test1 = UNI_N_CLOCK_STOPPED_USB2PCI; - break; - } - do { - if (--timeout <= 0) { - printk(KERN_ERR "core99_usb_enable: " - "Timeout waiting for clocks\n"); - break; - } - mdelay(1); - status0 = UN_IN(UNI_N_CLOCK_STOP_STATUS0); - status1 = UN_IN(UNI_N_CLOCK_STOP_STATUS1); - } while ((status0 & test0) | (status1 & test1)); - LOCK(flags); - } - } else { - /* Turn OFF */ - if (number < 4) { - reg = MACIO_IN32(KEYLARGO_FCR4); - reg |= KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) | - KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number); - reg |= KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) | - KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1); - MACIO_OUT32(KEYLARGO_FCR4, reg); - (void)MACIO_IN32(KEYLARGO_FCR4); - udelay(1); - } else { - reg = MACIO_IN32(KEYLARGO_FCR3); - reg |= KL3_IT_PORT_WAKEUP_ENABLE(0) | KL3_IT_PORT_RESUME_WAKE_EN(0) | - KL3_IT_PORT_CONNECT_WAKE_EN(0) | KL3_IT_PORT_DISCONNECT_WAKE_EN(0); - reg |= KL3_IT_PORT_WAKEUP_ENABLE(1) | KL3_IT_PORT_RESUME_WAKE_EN(1) | - KL3_IT_PORT_CONNECT_WAKE_EN(1) | KL3_IT_PORT_DISCONNECT_WAKE_EN(1); - MACIO_OUT32(KEYLARGO_FCR3, reg); - (void)MACIO_IN32(KEYLARGO_FCR3); - udelay(1); - } - if (number == 0) { - if (macio->type != macio_intrepid) - MACIO_BIC(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE); - (void)MACIO_IN32(KEYLARGO_FCR0); - udelay(1); - MACIO_BIS(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1)); - (void)MACIO_IN32(KEYLARGO_FCR0); - } else if (number == 2) { - if (macio->type != macio_intrepid) - MACIO_BIC(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE); - (void)MACIO_IN32(KEYLARGO_FCR0); - udelay(1); - MACIO_BIS(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1)); - (void)MACIO_IN32(KEYLARGO_FCR0); - } else if (number == 4) { - udelay(1); - MACIO_BIS(KEYLARGO_FCR1, (KL1_USB2_PAD_SUSPEND0 | KL1_USB2_PAD_SUSPEND1)); - (void)MACIO_IN32(KEYLARGO_FCR1); - } - udelay(1); - } - UNLOCK(flags); - - return 0; -} - -static long -core99_firewire_enable(struct device_node* node, long param, long value) -{ - unsigned long flags; - struct macio_chip* macio; - - macio = &macio_chips[0]; - if (macio->type != macio_keylargo && macio->type != macio_pangea && - macio->type != macio_intrepid) - return -ENODEV; - if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED)) - return -ENODEV; - - LOCK(flags); - if (value) { - UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW); - (void)UN_IN(UNI_N_CLOCK_CNTL); - } else { - UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW); - (void)UN_IN(UNI_N_CLOCK_CNTL); - } - UNLOCK(flags); - mdelay(1); - - return 0; -} - -static long -core99_firewire_cable_power(struct device_node* node, long param, long value) -{ - unsigned long flags; - struct macio_chip* macio; - - /* Trick: we allow NULL node */ - if ((pmac_mb.board_flags & PMAC_MB_HAS_FW_POWER) == 0) - return -ENODEV; - macio = &macio_chips[0]; - if (macio->type != macio_keylargo && macio->type != macio_pangea && - macio->type != macio_intrepid) - return -ENODEV; - if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED)) - return -ENODEV; - - LOCK(flags); - if (value) { - MACIO_OUT8(KL_GPIO_FW_CABLE_POWER , 0); - MACIO_IN8(KL_GPIO_FW_CABLE_POWER); - udelay(10); - } else { - MACIO_OUT8(KL_GPIO_FW_CABLE_POWER , 4); - MACIO_IN8(KL_GPIO_FW_CABLE_POWER); udelay(10); - } - UNLOCK(flags); - mdelay(1); - - return 0; -} - -static long -intrepid_aack_delay_enable(struct device_node* node, long param, long value) -{ - unsigned long flags; - - if (uninorth_rev < 0xd2) - return -ENODEV; - - LOCK(flags); - if (param) - UN_BIS(UNI_N_AACK_DELAY, UNI_N_AACK_DELAY_ENABLE); - else - UN_BIC(UNI_N_AACK_DELAY, UNI_N_AACK_DELAY_ENABLE); - UNLOCK(flags); - - return 0; -} - - -#endif /* CONFIG_POWER4 */ - -static long -core99_read_gpio(struct device_node* node, long param, long value) -{ - struct macio_chip* macio = &macio_chips[0]; - - return MACIO_IN8(param); -} - - -static long -core99_write_gpio(struct device_node* node, long param, long value) -{ - struct macio_chip* macio = &macio_chips[0]; - - MACIO_OUT8(param, (u8)(value & 0xff)); - return 0; -} - -#ifdef CONFIG_POWER4 - -static long -g5_gmac_enable(struct device_node* node, long param, long value) -{ - struct macio_chip* macio = &macio_chips[0]; - unsigned long flags; - u8 pbus, pid; - - LOCK(flags); - if (value) { - MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE); - mb(); - k2_skiplist[0] = NULL; - } else { - k2_skiplist[0] = node; - mb(); - MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE); - } - - UNLOCK(flags); - mdelay(1); - - return 0; -} - -static long -g5_fw_enable(struct device_node* node, long param, long value) -{ - struct macio_chip* macio = &macio_chips[0]; - unsigned long flags; - - LOCK(flags); - if (value) { - MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE); - mb(); - k2_skiplist[1] = NULL; - } else { - k2_skiplist[1] = node; - mb(); - MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE); - } - - UNLOCK(flags); - mdelay(1); - - return 0; -} - -static long -g5_mpic_enable(struct device_node* node, long param, long value) -{ - unsigned long flags; - - if (node->parent == NULL || strcmp(node->parent->name, "u3")) - return 0; - - LOCK(flags); - UN_BIS(U3_TOGGLE_REG, U3_MPIC_RESET | U3_MPIC_OUTPUT_ENABLE); - UNLOCK(flags); - - return 0; -} - -#ifdef CONFIG_SMP -static long -g5_reset_cpu(struct device_node* node, long param, long value) -{ - unsigned int reset_io = 0; - unsigned long flags; - struct macio_chip* macio; - struct device_node* np; - - macio = &macio_chips[0]; - if (macio->type != macio_keylargo2) - return -ENODEV; - - np = find_path_device("/cpus"); - if (np == NULL) - return -ENODEV; - for (np = np->child; np != NULL; np = np->sibling) { - u32* num = (u32 *)get_property(np, "reg", NULL); - u32* rst = (u32 *)get_property(np, "soft-reset", NULL); - if (num == NULL || rst == NULL) - continue; - if (param == *num) { - reset_io = *rst; - break; - } - } - if (np == NULL || reset_io == 0) - return -ENODEV; - - LOCK(flags); - MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE); - (void)MACIO_IN8(reset_io); - udelay(1); - MACIO_OUT8(reset_io, 0); - (void)MACIO_IN8(reset_io); - UNLOCK(flags); - - return 0; -} -#endif /* CONFIG_SMP */ - -/* - * This can be called from pmac_smp so isn't static - * - * This takes the second CPU off the bus on dual CPU machines - * running UP - */ -void g5_phy_disable_cpu1(void) -{ - UN_OUT(U3_API_PHY_CONFIG_1, 0); -} - -#endif /* CONFIG_POWER4 */ - -#ifndef CONFIG_POWER4 - -static void -keylargo_shutdown(struct macio_chip* macio, int sleep_mode) -{ - u32 temp; - - if (sleep_mode) { - mdelay(1); - MACIO_BIS(KEYLARGO_FCR0, KL0_USB_REF_SUSPEND); - (void)MACIO_IN32(KEYLARGO_FCR0); - mdelay(1); - } - - MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE | - KL0_SCC_CELL_ENABLE | - KL0_IRDA_ENABLE | KL0_IRDA_CLK32_ENABLE | - KL0_IRDA_CLK19_ENABLE); - - MACIO_BIC(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_MASK); - MACIO_BIS(KEYLARGO_MBCR, KL_MBCR_MB0_IDE_ENABLE); - - MACIO_BIC(KEYLARGO_FCR1, - KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT | - KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE | - KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT | - KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE | - KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE | - KL1_EIDE0_ENABLE | KL1_EIDE0_RESET_N | - KL1_EIDE1_ENABLE | KL1_EIDE1_RESET_N | - KL1_UIDE_ENABLE); - - MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); - MACIO_BIC(KEYLARGO_FCR2, KL2_IOBUS_ENABLE); - - temp = MACIO_IN32(KEYLARGO_FCR3); - if (macio->rev >= 2) { - temp |= KL3_SHUTDOWN_PLL2X; - if (sleep_mode) - temp |= KL3_SHUTDOWN_PLL_TOTAL; - } - - temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 | - KL3_SHUTDOWN_PLLKW35; - if (sleep_mode) - temp |= KL3_SHUTDOWN_PLLKW12; - temp &= ~(KL3_CLK66_ENABLE | KL3_CLK49_ENABLE | KL3_CLK45_ENABLE - | KL3_CLK31_ENABLE | KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE); - if (sleep_mode) - temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE); - MACIO_OUT32(KEYLARGO_FCR3, temp); - - /* Flush posted writes & wait a bit */ - (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1); -} - -static void -pangea_shutdown(struct macio_chip* macio, int sleep_mode) -{ - u32 temp; - - MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE | - KL0_SCC_CELL_ENABLE | - KL0_USB0_CELL_ENABLE | KL0_USB1_CELL_ENABLE); - - MACIO_BIC(KEYLARGO_FCR1, - KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT | - KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE | - KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT | - KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE | - KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE | - KL1_UIDE_ENABLE); - if (pmac_mb.board_flags & PMAC_MB_MOBILE) - MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N); - - MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); - - temp = MACIO_IN32(KEYLARGO_FCR3); - temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 | - KL3_SHUTDOWN_PLLKW35; - temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE | KL3_CLK31_ENABLE - | KL3_I2S0_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE); - if (sleep_mode) - temp &= ~(KL3_VIA_CLK16_ENABLE | KL3_TIMER_CLK18_ENABLE); - MACIO_OUT32(KEYLARGO_FCR3, temp); - - /* Flush posted writes & wait a bit */ - (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1); -} - -static void -intrepid_shutdown(struct macio_chip* macio, int sleep_mode) -{ - u32 temp; - - MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE | - KL0_SCC_CELL_ENABLE); - - MACIO_BIC(KEYLARGO_FCR1, - /*KL1_USB2_CELL_ENABLE |*/ - KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT | - KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE | - KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE); - if (pmac_mb.board_flags & PMAC_MB_MOBILE) - MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N); - - temp = MACIO_IN32(KEYLARGO_FCR3); - temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE | - KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE); - if (sleep_mode) - temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_IT_VIA_CLK32_ENABLE); - MACIO_OUT32(KEYLARGO_FCR3, temp); - - /* Flush posted writes & wait a bit */ - (void)MACIO_IN32(KEYLARGO_FCR0); - mdelay(10); -} - - -void pmac_tweak_clock_spreading(int enable) -{ - struct macio_chip* macio = &macio_chips[0]; - - /* Hack for doing clock spreading on some machines PowerBooks and - * iBooks. This implements the "platform-do-clockspreading" OF - * property as decoded manually on various models. For safety, we also - * check the product ID in the device-tree in cases we'll whack the i2c - * chip to make reasonably sure we won't set wrong values in there - * - * Of course, ultimately, we have to implement a real parser for - * the platform-do-* stuff... - */ - - if (macio->type == macio_intrepid) { - struct device_node *clock = - of_find_node_by_path("/uni-n@f8000000/hw-clock"); - if (clock && get_property(clock, "platform-do-clockspreading", - NULL)) { - printk(KERN_INFO "%sabling clock spreading on Intrepid" - " ASIC\n", enable ? "En" : "Dis"); - if (enable) - UN_OUT(UNI_N_CLOCK_SPREADING, 2); - else - UN_OUT(UNI_N_CLOCK_SPREADING, 0); - mdelay(40); - } - of_node_put(clock); - } - - while (machine_is_compatible("PowerBook5,2") || - machine_is_compatible("PowerBook5,3") || - machine_is_compatible("PowerBook6,2") || - machine_is_compatible("PowerBook6,3")) { - struct device_node *ui2c = of_find_node_by_type(NULL, "i2c"); - struct device_node *dt = of_find_node_by_name(NULL, "device-tree"); - u8 buffer[9]; - u32 *productID; - int i, rc, changed = 0; - - if (dt == NULL) - break; - productID = (u32 *)get_property(dt, "pid#", NULL); - if (productID == NULL) - break; - while(ui2c) { - struct device_node *p = of_get_parent(ui2c); - if (p && !strcmp(p->name, "uni-n")) - break; - ui2c = of_find_node_by_type(ui2c, "i2c"); - } - if (ui2c == NULL) - break; - DBG("Trying to bump clock speed for PID: %08x...\n", *productID); - rc = pmac_low_i2c_open(ui2c, 1); - if (rc != 0) - break; - pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined); - rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9); - DBG("read result: %d,", rc); - if (rc != 0) { - pmac_low_i2c_close(ui2c); - break; - } - for (i=0; i<9; i++) - DBG(" %02x", buffer[i]); - DBG("\n"); - - switch(*productID) { - case 0x1182: /* AlBook 12" rev 2 */ - case 0x1183: /* iBook G4 12" */ - buffer[0] = (buffer[0] & 0x8f) | 0x70; - buffer[2] = (buffer[2] & 0x7f) | 0x00; - buffer[5] = (buffer[5] & 0x80) | 0x31; - buffer[6] = (buffer[6] & 0x40) | 0xb0; - buffer[7] = (buffer[7] & 0x00) | (enable ? 0xc0 : 0xba); - buffer[8] = (buffer[8] & 0x00) | 0x30; - changed = 1; - break; - case 0x3142: /* AlBook 15" (ATI M10) */ - case 0x3143: /* AlBook 17" (ATI M10) */ - buffer[0] = (buffer[0] & 0xaf) | 0x50; - buffer[2] = (buffer[2] & 0x7f) | 0x00; - buffer[5] = (buffer[5] & 0x80) | 0x31; - buffer[6] = (buffer[6] & 0x40) | 0xb0; - buffer[7] = (buffer[7] & 0x00) | (enable ? 0xd0 : 0xc0); - buffer[8] = (buffer[8] & 0x00) | 0x30; - changed = 1; - break; - default: - DBG("i2c-hwclock: Machine model not handled\n"); - break; - } - if (!changed) { - pmac_low_i2c_close(ui2c); - break; - } - printk(KERN_INFO "%sabling clock spreading on i2c clock chip\n", - enable ? "En" : "Dis"); - pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_stdsub); - rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_write, 0x80, buffer, 9); - DBG("write result: %d,", rc); - pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined); - rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9); - DBG("read result: %d,", rc); - if (rc != 0) { - pmac_low_i2c_close(ui2c); - break; - } - for (i=0; i<9; i++) - DBG(" %02x", buffer[i]); - pmac_low_i2c_close(ui2c); - break; - } -} - - -static int -core99_sleep(void) -{ - struct macio_chip* macio; - int i; - - macio = &macio_chips[0]; - if (macio->type != macio_keylargo && macio->type != macio_pangea && - macio->type != macio_intrepid) - return -ENODEV; - - /* We power off the wireless slot in case it was not done - * by the driver. We don't power it on automatically however - */ - if (macio->flags & MACIO_FLAG_AIRPORT_ON) - core99_airport_enable(macio->of_node, 0, 0); - - /* We power off the FW cable. Should be done by the driver... */ - if (macio->flags & MACIO_FLAG_FW_SUPPORTED) { - core99_firewire_enable(NULL, 0, 0); - core99_firewire_cable_power(NULL, 0, 0); - } - - /* We make sure int. modem is off (in case driver lost it) */ - if (macio->type == macio_keylargo) - core99_modem_enable(macio->of_node, 0, 0); - else - pangea_modem_enable(macio->of_node, 0, 0); - - /* We make sure the sound is off as well */ - core99_sound_chip_enable(macio->of_node, 0, 0); - - /* - * Save various bits of KeyLargo - */ - - /* Save the state of the various GPIOs */ - save_gpio_levels[0] = MACIO_IN32(KEYLARGO_GPIO_LEVELS0); - save_gpio_levels[1] = MACIO_IN32(KEYLARGO_GPIO_LEVELS1); - for (i=0; itype == macio_keylargo) - save_mbcr = MACIO_IN32(KEYLARGO_MBCR); - save_fcr[0] = MACIO_IN32(KEYLARGO_FCR0); - save_fcr[1] = MACIO_IN32(KEYLARGO_FCR1); - save_fcr[2] = MACIO_IN32(KEYLARGO_FCR2); - save_fcr[3] = MACIO_IN32(KEYLARGO_FCR3); - save_fcr[4] = MACIO_IN32(KEYLARGO_FCR4); - if (macio->type == macio_pangea || macio->type == macio_intrepid) - save_fcr[5] = MACIO_IN32(KEYLARGO_FCR5); - - /* Save state & config of DBDMA channels */ - dbdma_save(macio, save_dbdma); - - /* - * Turn off as much as we can - */ - if (macio->type == macio_pangea) - pangea_shutdown(macio, 1); - else if (macio->type == macio_intrepid) - intrepid_shutdown(macio, 1); - else if (macio->type == macio_keylargo) - keylargo_shutdown(macio, 1); - - /* - * Put the host bridge to sleep - */ - - save_unin_clock_ctl = UN_IN(UNI_N_CLOCK_CNTL); - /* Note: do not switch GMAC off, driver does it when necessary, WOL must keep it - * enabled ! - */ - UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl & - ~(/*UNI_N_CLOCK_CNTL_GMAC|*/UNI_N_CLOCK_CNTL_FW/*|UNI_N_CLOCK_CNTL_PCI*/)); - udelay(100); - UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING); - UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_SLEEP); - mdelay(10); - - /* - * FIXME: A bit of black magic with OpenPIC (don't ask me why) - */ - if (pmac_mb.model_id == PMAC_TYPE_SAWTOOTH) { - MACIO_BIS(0x506e0, 0x00400000); - MACIO_BIS(0x506e0, 0x80000000); - } - return 0; -} - -static int -core99_wake_up(void) -{ - struct macio_chip* macio; - int i; - - macio = &macio_chips[0]; - if (macio->type != macio_keylargo && macio->type != macio_pangea && - macio->type != macio_intrepid) - return -ENODEV; - - /* - * Wakeup the host bridge - */ - UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL); - udelay(10); - UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING); - udelay(10); - - /* - * Restore KeyLargo - */ - - if (macio->type == macio_keylargo) { - MACIO_OUT32(KEYLARGO_MBCR, save_mbcr); - (void)MACIO_IN32(KEYLARGO_MBCR); udelay(10); - } - MACIO_OUT32(KEYLARGO_FCR0, save_fcr[0]); - (void)MACIO_IN32(KEYLARGO_FCR0); udelay(10); - MACIO_OUT32(KEYLARGO_FCR1, save_fcr[1]); - (void)MACIO_IN32(KEYLARGO_FCR1); udelay(10); - MACIO_OUT32(KEYLARGO_FCR2, save_fcr[2]); - (void)MACIO_IN32(KEYLARGO_FCR2); udelay(10); - MACIO_OUT32(KEYLARGO_FCR3, save_fcr[3]); - (void)MACIO_IN32(KEYLARGO_FCR3); udelay(10); - MACIO_OUT32(KEYLARGO_FCR4, save_fcr[4]); - (void)MACIO_IN32(KEYLARGO_FCR4); udelay(10); - if (macio->type == macio_pangea || macio->type == macio_intrepid) { - MACIO_OUT32(KEYLARGO_FCR5, save_fcr[5]); - (void)MACIO_IN32(KEYLARGO_FCR5); udelay(10); - } - - dbdma_restore(macio, save_dbdma); - - MACIO_OUT32(KEYLARGO_GPIO_LEVELS0, save_gpio_levels[0]); - MACIO_OUT32(KEYLARGO_GPIO_LEVELS1, save_gpio_levels[1]); - for (i=0; itype) { -#ifndef CONFIG_POWER4 - case macio_grand_central: - pmac_mb.model_id = PMAC_TYPE_PSURGE; - pmac_mb.model_name = "Unknown PowerSurge"; - break; - case macio_ohare: - pmac_mb.model_id = PMAC_TYPE_UNKNOWN_OHARE; - pmac_mb.model_name = "Unknown OHare-based"; - break; - case macio_heathrow: - pmac_mb.model_id = PMAC_TYPE_UNKNOWN_HEATHROW; - pmac_mb.model_name = "Unknown Heathrow-based"; - pmac_mb.features = heathrow_desktop_features; - break; - case macio_paddington: - pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PADDINGTON; - pmac_mb.model_name = "Unknown Paddington-based"; - pmac_mb.features = paddington_features; - break; - case macio_keylargo: - pmac_mb.model_id = PMAC_TYPE_UNKNOWN_CORE99; - pmac_mb.model_name = "Unknown Keylargo-based"; - pmac_mb.features = core99_features; - break; - case macio_pangea: - pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PANGEA; - pmac_mb.model_name = "Unknown Pangea-based"; - pmac_mb.features = pangea_features; - break; - case macio_intrepid: - pmac_mb.model_id = PMAC_TYPE_UNKNOWN_INTREPID; - pmac_mb.model_name = "Unknown Intrepid-based"; - pmac_mb.features = intrepid_features; - break; -#else /* CONFIG_POWER4 */ - case macio_keylargo2: - pmac_mb.model_id = PMAC_TYPE_UNKNOWN_K2; - pmac_mb.model_name = "Unknown G5"; - pmac_mb.features = g5_features; - break; -#endif /* CONFIG_POWER4 */ - default: - return -ENODEV; - } -found: -#ifndef CONFIG_POWER4 - /* Fixup Hooper vs. Comet */ - if (pmac_mb.model_id == PMAC_TYPE_HOOPER) { - u32 __iomem * mach_id_ptr = ioremap(0xf3000034, 4); - if (!mach_id_ptr) - return -ENODEV; - /* Here, I used to disable the media-bay on comet. It - * appears this is wrong, the floppy connector is actually - * a kind of media-bay and works with the current driver. - */ - if (__raw_readl(mach_id_ptr) & 0x20000000UL) - pmac_mb.model_id = PMAC_TYPE_COMET; - iounmap(mach_id_ptr); - } -#endif /* CONFIG_POWER4 */ - -#ifdef CONFIG_6xx - /* Set default value of powersave_nap on machines that support it. - * It appears that uninorth rev 3 has a problem with it, we don't - * enable it on those. In theory, the flush-on-lock property is - * supposed to be set when not supported, but I'm not very confident - * that all Apple OF revs did it properly, I do it the paranoid way. - */ - while (uninorth_base && uninorth_rev > 3) { - struct device_node* np = find_path_device("/cpus"); - if (!np || !np->child) { - printk(KERN_WARNING "Can't find CPU(s) in device tree !\n"); - break; - } - np = np->child; - /* Nap mode not supported on SMP */ - if (np->sibling) - break; - /* Nap mode not supported if flush-on-lock property is present */ - if (get_property(np, "flush-on-lock", NULL)) - break; - powersave_nap = 1; - printk(KERN_INFO "Processor NAP mode on idle enabled.\n"); - break; - } - - /* On CPUs that support it (750FX), lowspeed by default during - * NAP mode - */ - powersave_lowspeed = 1; -#endif /* CONFIG_6xx */ -#ifdef CONFIG_POWER4 - powersave_nap = 1; -#endif - /* Check for "mobile" machine */ - if (model && (strncmp(model, "PowerBook", 9) == 0 - || strncmp(model, "iBook", 5) == 0)) - pmac_mb.board_flags |= PMAC_MB_MOBILE; - - - printk(KERN_INFO "PowerMac motherboard: %s\n", pmac_mb.model_name); - return 0; -} - -/* Initialize the Core99 UniNorth host bridge and memory controller - */ -static void __init -probe_uninorth(void) -{ - unsigned long actrl; - - /* Locate core99 Uni-N */ - uninorth_node = of_find_node_by_name(NULL, "uni-n"); - /* Locate G5 u3 */ - if (uninorth_node == NULL) { - uninorth_node = of_find_node_by_name(NULL, "u3"); - uninorth_u3 = 1; - } - if (uninorth_node && uninorth_node->n_addrs > 0) { - unsigned long address = uninorth_node->addrs[0].address; - uninorth_base = ioremap(address, 0x40000); - uninorth_rev = in_be32(UN_REG(UNI_N_VERSION)); - if (uninorth_u3) - u3_ht = ioremap(address + U3_HT_CONFIG_BASE, 0x1000); - } else - uninorth_node = NULL; - - if (!uninorth_node) - return; - - printk(KERN_INFO "Found %s memory controller & host bridge, revision: %d\n", - uninorth_u3 ? "U3" : "UniNorth", uninorth_rev); - printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base); - - /* Set the arbitrer QAck delay according to what Apple does - */ - if (uninorth_rev < 0x11) { - actrl = UN_IN(UNI_N_ARB_CTRL) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK; - actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 : - UNI_N_ARB_CTRL_QACK_DELAY) << UNI_N_ARB_CTRL_QACK_DELAY_SHIFT; - UN_OUT(UNI_N_ARB_CTRL, actrl); - } - - /* Some more magic as done by them in recent MacOS X on UniNorth - * revs 1.5 to 2.O and Pangea. Seem to toggle the UniN Maxbus/PCI - * memory timeout - */ - if ((uninorth_rev >= 0x11 && uninorth_rev <= 0x24) || uninorth_rev == 0xc0) - UN_OUT(0x2160, UN_IN(0x2160) & 0x00ffffff); -} - -static void __init -probe_one_macio(const char* name, const char* compat, int type) -{ - struct device_node* node; - int i; - volatile u32 __iomem * base; - u32* revp; - - node = find_devices(name); - if (!node || !node->n_addrs) - return; - if (compat) - do { - if (device_is_compatible(node, compat)) - break; - node = node->next; - } while (node); - if (!node) - return; - for(i=0; i= MAX_MACIO_CHIPS) { - printk(KERN_ERR "pmac_feature: Please increase MAX_MACIO_CHIPS !\n"); - printk(KERN_ERR "pmac_feature: %s skipped\n", node->full_name); - return; - } - base = ioremap(node->addrs[0].address, node->addrs[0].size); - if (!base) { - printk(KERN_ERR "pmac_feature: Can't map mac-io chip !\n"); - return; - } - if (type == macio_keylargo) { - u32* did = (u32 *)get_property(node, "device-id", NULL); - if (*did == 0x00000025) - type = macio_pangea; - if (*did == 0x0000003e) - type = macio_intrepid; - } - macio_chips[i].of_node = node; - macio_chips[i].type = type; - macio_chips[i].base = base; - macio_chips[i].flags = MACIO_FLAG_SCCB_ON | MACIO_FLAG_SCCB_ON; - macio_chips[i].name = macio_names[type]; - revp = (u32 *)get_property(node, "revision-id", NULL); - if (revp) - macio_chips[i].rev = *revp; - printk(KERN_INFO "Found a %s mac-io controller, rev: %d, mapped at 0x%p\n", - macio_names[type], macio_chips[i].rev, macio_chips[i].base); -} - -static int __init -probe_macios(void) -{ - /* Warning, ordering is important */ - probe_one_macio("gc", NULL, macio_grand_central); - probe_one_macio("ohare", NULL, macio_ohare); - probe_one_macio("pci106b,7", NULL, macio_ohareII); - probe_one_macio("mac-io", "keylargo", macio_keylargo); - probe_one_macio("mac-io", "paddington", macio_paddington); - probe_one_macio("mac-io", "gatwick", macio_gatwick); - probe_one_macio("mac-io", "heathrow", macio_heathrow); - probe_one_macio("mac-io", "K2-Keylargo", macio_keylargo2); - - /* Make sure the "main" macio chip appear first */ - if (macio_chips[0].type == macio_gatwick - && macio_chips[1].type == macio_heathrow) { - struct macio_chip temp = macio_chips[0]; - macio_chips[0] = macio_chips[1]; - macio_chips[1] = temp; - } - if (macio_chips[0].type == macio_ohareII - && macio_chips[1].type == macio_ohare) { - struct macio_chip temp = macio_chips[0]; - macio_chips[0] = macio_chips[1]; - macio_chips[1] = temp; - } - macio_chips[0].lbus.index = 0; - macio_chips[1].lbus.index = 1; - - return (macio_chips[0].of_node == NULL) ? -ENODEV : 0; -} - -static void __init -initial_serial_shutdown(struct device_node* np) -{ - int len; - struct slot_names_prop { - int count; - char name[1]; - } *slots; - char *conn; - int port_type = PMAC_SCC_ASYNC; - int modem = 0; - - slots = (struct slot_names_prop *)get_property(np, "slot-names", &len); - conn = get_property(np, "AAPL,connector", &len); - if (conn && (strcmp(conn, "infrared") == 0)) - port_type = PMAC_SCC_IRDA; - else if (device_is_compatible(np, "cobalt")) - modem = 1; - else if (slots && slots->count > 0) { - if (strcmp(slots->name, "IrDA") == 0) - port_type = PMAC_SCC_IRDA; - else if (strcmp(slots->name, "Modem") == 0) - modem = 1; - } - if (modem) - pmac_call_feature(PMAC_FTR_MODEM_ENABLE, np, 0, 0); - pmac_call_feature(PMAC_FTR_SCC_ENABLE, np, port_type, 0); -} - -static void __init -set_initial_features(void) -{ - struct device_node* np; - - /* That hack appears to be necessary for some StarMax motherboards - * but I'm not too sure it was audited for side-effects on other - * ohare based machines... - * Since I still have difficulties figuring the right way to - * differenciate them all and since that hack was there for a long - * time, I'll keep it around - */ - if (macio_chips[0].type == macio_ohare && !find_devices("via-pmu")) { - struct macio_chip* macio = &macio_chips[0]; - MACIO_OUT32(OHARE_FCR, STARMAX_FEATURES); - } else if (macio_chips[0].type == macio_ohare) { - struct macio_chip* macio = &macio_chips[0]; - MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); - } else if (macio_chips[1].type == macio_ohare) { - struct macio_chip* macio = &macio_chips[1]; - MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); - } - -#ifdef CONFIG_POWER4 - if (macio_chips[0].type == macio_keylargo2) { -#ifndef CONFIG_SMP - /* On SMP machines running UP, we have the second CPU eating - * bus cycles. We need to take it off the bus. This is done - * from pmac_smp for SMP kernels running on one CPU - */ - np = of_find_node_by_type(NULL, "cpu"); - if (np != NULL) - np = of_find_node_by_type(np, "cpu"); - if (np != NULL) { - g5_phy_disable_cpu1(); - of_node_put(np); - } -#endif /* CONFIG_SMP */ - /* Enable GMAC for now for PCI probing. It will be disabled - * later on after PCI probe - */ - np = of_find_node_by_name(NULL, "ethernet"); - while(np) { - if (device_is_compatible(np, "K2-GMAC")) - g5_gmac_enable(np, 0, 1); - np = of_find_node_by_name(np, "ethernet"); - } - - /* Enable FW before PCI probe. Will be disabled later on - * Note: We should have a batter way to check that we are - * dealing with uninorth internal cell and not a PCI cell - * on the external PCI. The code below works though. - */ - np = of_find_node_by_name(NULL, "firewire"); - while(np) { - if (device_is_compatible(np, "pci106b,5811")) { - macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED; - g5_fw_enable(np, 0, 1); - } - np = of_find_node_by_name(np, "firewire"); - } - } -#else /* CONFIG_POWER4 */ - - if (macio_chips[0].type == macio_keylargo || - macio_chips[0].type == macio_pangea || - macio_chips[0].type == macio_intrepid) { - /* Enable GMAC for now for PCI probing. It will be disabled - * later on after PCI probe - */ - np = of_find_node_by_name(NULL, "ethernet"); - while(np) { - if (np->parent - && device_is_compatible(np->parent, "uni-north") - && device_is_compatible(np, "gmac")) - core99_gmac_enable(np, 0, 1); - np = of_find_node_by_name(np, "ethernet"); - } - - /* Enable FW before PCI probe. Will be disabled later on - * Note: We should have a batter way to check that we are - * dealing with uninorth internal cell and not a PCI cell - * on the external PCI. The code below works though. - */ - np = of_find_node_by_name(NULL, "firewire"); - while(np) { - if (np->parent - && device_is_compatible(np->parent, "uni-north") - && (device_is_compatible(np, "pci106b,18") || - device_is_compatible(np, "pci106b,30") || - device_is_compatible(np, "pci11c1,5811"))) { - macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED; - core99_firewire_enable(np, 0, 1); - } - np = of_find_node_by_name(np, "firewire"); - } - - /* Enable ATA-100 before PCI probe. */ - np = of_find_node_by_name(NULL, "ata-6"); - while(np) { - if (np->parent - && device_is_compatible(np->parent, "uni-north") - && device_is_compatible(np, "kauai-ata")) { - core99_ata100_enable(np, 1); - } - np = of_find_node_by_name(np, "ata-6"); - } - - /* Switch airport off */ - np = find_devices("radio"); - while(np) { - if (np && np->parent == macio_chips[0].of_node) { - macio_chips[0].flags |= MACIO_FLAG_AIRPORT_ON; - core99_airport_enable(np, 0, 0); - } - np = np->next; - } - } - - /* On all machines that support sound PM, switch sound off */ - if (macio_chips[0].of_node) - pmac_do_feature_call(PMAC_FTR_SOUND_CHIP_ENABLE, - macio_chips[0].of_node, 0, 0); - - /* While on some desktop G3s, we turn it back on */ - if (macio_chips[0].of_node && macio_chips[0].type == macio_heathrow - && (pmac_mb.model_id == PMAC_TYPE_GOSSAMER || - pmac_mb.model_id == PMAC_TYPE_SILK)) { - struct macio_chip* macio = &macio_chips[0]; - MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE); - MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N); - } - - /* Some machine models need the clock chip to be properly setup for - * clock spreading now. This should be a platform function but we - * don't do these at the moment - */ - pmac_tweak_clock_spreading(1); - -#endif /* CONFIG_POWER4 */ - - /* On all machines, switch modem & serial ports off */ - np = find_devices("ch-a"); - while(np) { - initial_serial_shutdown(np); - np = np->next; - } - np = find_devices("ch-b"); - while(np) { - initial_serial_shutdown(np); - np = np->next; - } -} - -void __init -pmac_feature_init(void) -{ - /* Detect the UniNorth memory controller */ - probe_uninorth(); - - /* Probe mac-io controllers */ - if (probe_macios()) { - printk(KERN_WARNING "No mac-io chip found\n"); - return; - } - - /* Setup low-level i2c stuffs */ - pmac_init_low_i2c(); - - /* Probe machine type */ - if (probe_motherboard()) - printk(KERN_WARNING "Unknown PowerMac !\n"); - - /* Set some initial features (turn off some chips that will - * be later turned on) - */ - set_initial_features(); -} - -int __init -pmac_feature_late_init(void) -{ - struct device_node* np; - - /* Request some resources late */ - if (uninorth_node) - request_OF_resource(uninorth_node, 0, NULL); - np = find_devices("hammerhead"); - if (np) - request_OF_resource(np, 0, NULL); - np = find_devices("interrupt-controller"); - if (np) - request_OF_resource(np, 0, NULL); - return 0; -} - -device_initcall(pmac_feature_late_init); - -#ifdef CONFIG_POWER4 - -static void dump_HT_speeds(char *name, u32 cfg, u32 frq) -{ - int freqs[16] = { 200,300,400,500,600,800,1000,0,0,0,0,0,0,0,0,0 }; - int bits[8] = { 8,16,0,32,2,4,0,0 }; - int freq = (frq >> 8) & 0xf; - - if (freqs[freq] == 0) - printk("%s: Unknown HT link frequency %x\n", name, freq); - else - printk("%s: %d MHz on main link, (%d in / %d out) bits width\n", - name, freqs[freq], - bits[(cfg >> 28) & 0x7], bits[(cfg >> 24) & 0x7]); -} - -void __init pmac_check_ht_link(void) -{ - u32 ufreq, freq, ucfg, cfg; - struct device_node *pcix_node; - u8 px_bus, px_devfn; - struct pci_controller *px_hose; - - (void)in_be32(u3_ht + U3_HT_LINK_COMMAND); - ucfg = cfg = in_be32(u3_ht + U3_HT_LINK_CONFIG); - ufreq = freq = in_be32(u3_ht + U3_HT_LINK_FREQ); - dump_HT_speeds("U3 HyperTransport", cfg, freq); - - pcix_node = of_find_compatible_node(NULL, "pci", "pci-x"); - if (pcix_node == NULL) { - printk("No PCI-X bridge found\n"); - return; - } - if (pci_device_from_OF_node(pcix_node, &px_bus, &px_devfn) != 0) { - printk("PCI-X bridge found but not matched to pci\n"); - return; - } - px_hose = pci_find_hose_for_OF_device(pcix_node); - if (px_hose == NULL) { - printk("PCI-X bridge found but not matched to host\n"); - return; - } - early_read_config_dword(px_hose, px_bus, px_devfn, 0xc4, &cfg); - early_read_config_dword(px_hose, px_bus, px_devfn, 0xcc, &freq); - dump_HT_speeds("PCI-X HT Uplink", cfg, freq); - early_read_config_dword(px_hose, px_bus, px_devfn, 0xc8, &cfg); - early_read_config_dword(px_hose, px_bus, px_devfn, 0xd0, &freq); - dump_HT_speeds("PCI-X HT Downlink", cfg, freq); -} - -#endif /* CONFIG_POWER4 */ - -/* - * Early video resume hook - */ - -static void (*pmac_early_vresume_proc)(void *data); -static void *pmac_early_vresume_data; - -void pmac_set_early_video_resume(void (*proc)(void *data), void *data) -{ - if (_machine != _MACH_Pmac) - return; - preempt_disable(); - pmac_early_vresume_proc = proc; - pmac_early_vresume_data = data; - preempt_enable(); -} -EXPORT_SYMBOL(pmac_set_early_video_resume); - -void pmac_call_early_video_resume(void) -{ - if (pmac_early_vresume_proc) - pmac_early_vresume_proc(pmac_early_vresume_data); -} - -/* - * AGP related suspend/resume code - */ - -static struct pci_dev *pmac_agp_bridge; -static int (*pmac_agp_suspend)(struct pci_dev *bridge); -static int (*pmac_agp_resume)(struct pci_dev *bridge); - -void pmac_register_agp_pm(struct pci_dev *bridge, - int (*suspend)(struct pci_dev *bridge), - int (*resume)(struct pci_dev *bridge)) -{ - if (suspend || resume) { - pmac_agp_bridge = bridge; - pmac_agp_suspend = suspend; - pmac_agp_resume = resume; - return; - } - if (bridge != pmac_agp_bridge) - return; - pmac_agp_suspend = pmac_agp_resume = NULL; - return; -} -EXPORT_SYMBOL(pmac_register_agp_pm); - -void pmac_suspend_agp_for_card(struct pci_dev *dev) -{ - if (pmac_agp_bridge == NULL || pmac_agp_suspend == NULL) - return; - if (pmac_agp_bridge->bus != dev->bus) - return; - pmac_agp_suspend(pmac_agp_bridge); -} -EXPORT_SYMBOL(pmac_suspend_agp_for_card); - -void pmac_resume_agp_for_card(struct pci_dev *dev) -{ - if (pmac_agp_bridge == NULL || pmac_agp_resume == NULL) - return; - if (pmac_agp_bridge->bus != dev->bus) - return; - pmac_agp_resume(pmac_agp_bridge); -} -EXPORT_SYMBOL(pmac_resume_agp_for_card); diff --git a/arch/ppc/platforms/pmac_low_i2c.c b/arch/ppc/platforms/pmac_low_i2c.c deleted file mode 100644 index 08583fce169..00000000000 --- a/arch/ppc/platforms/pmac_low_i2c.c +++ /dev/null @@ -1,511 +0,0 @@ -/* - * arch/ppc/platforms/pmac_low_i2c.c - * - * Copyright (C) 2003 Ben. Herrenschmidt (benh@kernel.crashing.org) - * - * 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. - * - * This file contains some low-level i2c access routines that - * need to be used by various bits of the PowerMac platform code - * at times where the real asynchronous & interrupt driven driver - * cannot be used. The API borrows some semantics from the darwin - * driver in order to ease the implementation of the platform - * properties parser - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MAX_LOW_I2C_HOST 4 - -#if 1 -#define DBG(x...) do {\ - printk(KERN_DEBUG "KW:" x); \ - } while(0) -#else -#define DBGG(x...) -#endif - -struct low_i2c_host; - -typedef int (*low_i2c_func_t)(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len); - -struct low_i2c_host -{ - struct device_node *np; /* OF device node */ - struct semaphore mutex; /* Access mutex for use by i2c-keywest */ - low_i2c_func_t func; /* Access function */ - int is_open : 1; /* Poor man's access control */ - int mode; /* Current mode */ - int channel; /* Current channel */ - int num_channels; /* Number of channels */ - void __iomem * base; /* For keywest-i2c, base address */ - int bsteps; /* And register stepping */ - int speed; /* And speed */ -}; - -static struct low_i2c_host low_i2c_hosts[MAX_LOW_I2C_HOST]; - -/* No locking is necessary on allocation, we are running way before - * anything can race with us - */ -static struct low_i2c_host *find_low_i2c_host(struct device_node *np) -{ - int i; - - for (i = 0; i < MAX_LOW_I2C_HOST; i++) - if (low_i2c_hosts[i].np == np) - return &low_i2c_hosts[i]; - return NULL; -} - -/* - * - * i2c-keywest implementation (UniNorth, U2, U3, Keylargo's) - * - */ - -/* - * Keywest i2c definitions borrowed from drivers/i2c/i2c-keywest.h, - * should be moved somewhere in include/asm-ppc/ - */ -/* Register indices */ -typedef enum { - reg_mode = 0, - reg_control, - reg_status, - reg_isr, - reg_ier, - reg_addr, - reg_subaddr, - reg_data -} reg_t; - - -/* Mode register */ -#define KW_I2C_MODE_100KHZ 0x00 -#define KW_I2C_MODE_50KHZ 0x01 -#define KW_I2C_MODE_25KHZ 0x02 -#define KW_I2C_MODE_DUMB 0x00 -#define KW_I2C_MODE_STANDARD 0x04 -#define KW_I2C_MODE_STANDARDSUB 0x08 -#define KW_I2C_MODE_COMBINED 0x0C -#define KW_I2C_MODE_MODE_MASK 0x0C -#define KW_I2C_MODE_CHAN_MASK 0xF0 - -/* Control register */ -#define KW_I2C_CTL_AAK 0x01 -#define KW_I2C_CTL_XADDR 0x02 -#define KW_I2C_CTL_STOP 0x04 -#define KW_I2C_CTL_START 0x08 - -/* Status register */ -#define KW_I2C_STAT_BUSY 0x01 -#define KW_I2C_STAT_LAST_AAK 0x02 -#define KW_I2C_STAT_LAST_RW 0x04 -#define KW_I2C_STAT_SDA 0x08 -#define KW_I2C_STAT_SCL 0x10 - -/* IER & ISR registers */ -#define KW_I2C_IRQ_DATA 0x01 -#define KW_I2C_IRQ_ADDR 0x02 -#define KW_I2C_IRQ_STOP 0x04 -#define KW_I2C_IRQ_START 0x08 -#define KW_I2C_IRQ_MASK 0x0F - -/* State machine states */ -enum { - state_idle, - state_addr, - state_read, - state_write, - state_stop, - state_dead -}; - -#define WRONG_STATE(name) do {\ - printk(KERN_DEBUG "KW: wrong state. Got %s, state: %s (isr: %02x)\n", \ - name, __kw_state_names[state], isr); \ - } while(0) - -static const char *__kw_state_names[] = { - "state_idle", - "state_addr", - "state_read", - "state_write", - "state_stop", - "state_dead" -}; - -static inline u8 __kw_read_reg(struct low_i2c_host *host, reg_t reg) -{ - return in_8(host->base + (((unsigned)reg) << host->bsteps)); -} - -static inline void __kw_write_reg(struct low_i2c_host *host, reg_t reg, u8 val) -{ - out_8(host->base + (((unsigned)reg) << host->bsteps), val); - (void)__kw_read_reg(host, reg_subaddr); -} - -#define kw_write_reg(reg, val) __kw_write_reg(host, reg, val) -#define kw_read_reg(reg) __kw_read_reg(host, reg) - - -/* Don't schedule, the g5 fan controller is too - * timing sensitive - */ -static u8 kw_wait_interrupt(struct low_i2c_host* host) -{ - int i; - u8 isr; - - for (i = 0; i < 200000; i++) { - isr = kw_read_reg(reg_isr) & KW_I2C_IRQ_MASK; - if (isr != 0) - return isr; - udelay(1); - } - return isr; -} - -static int kw_handle_interrupt(struct low_i2c_host *host, int state, int rw, int *rc, u8 **data, int *len, u8 isr) -{ - u8 ack; - - if (isr == 0) { - if (state != state_stop) { - DBG("KW: Timeout !\n"); - *rc = -EIO; - goto stop; - } - if (state == state_stop) { - ack = kw_read_reg(reg_status); - if (!(ack & KW_I2C_STAT_BUSY)) { - state = state_idle; - kw_write_reg(reg_ier, 0x00); - } - } - return state; - } - - if (isr & KW_I2C_IRQ_ADDR) { - ack = kw_read_reg(reg_status); - if (state != state_addr) { - kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR); - WRONG_STATE("KW_I2C_IRQ_ADDR"); - *rc = -EIO; - goto stop; - } - if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { - *rc = -ENODEV; - DBG("KW: NAK on address\n"); - return state_stop; - } else { - if (rw) { - state = state_read; - if (*len > 1) - kw_write_reg(reg_control, KW_I2C_CTL_AAK); - } else { - state = state_write; - kw_write_reg(reg_data, **data); - (*data)++; (*len)--; - } - } - kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR); - } - - if (isr & KW_I2C_IRQ_DATA) { - if (state == state_read) { - **data = kw_read_reg(reg_data); - (*data)++; (*len)--; - kw_write_reg(reg_isr, KW_I2C_IRQ_DATA); - if ((*len) == 0) - state = state_stop; - else if ((*len) == 1) - kw_write_reg(reg_control, 0); - } else if (state == state_write) { - ack = kw_read_reg(reg_status); - if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { - DBG("KW: nack on data write\n"); - *rc = -EIO; - goto stop; - } else if (*len) { - kw_write_reg(reg_data, **data); - (*data)++; (*len)--; - } else { - kw_write_reg(reg_control, KW_I2C_CTL_STOP); - state = state_stop; - *rc = 0; - } - kw_write_reg(reg_isr, KW_I2C_IRQ_DATA); - } else { - kw_write_reg(reg_isr, KW_I2C_IRQ_DATA); - WRONG_STATE("KW_I2C_IRQ_DATA"); - if (state != state_stop) { - *rc = -EIO; - goto stop; - } - } - } - - if (isr & KW_I2C_IRQ_STOP) { - kw_write_reg(reg_isr, KW_I2C_IRQ_STOP); - if (state != state_stop) { - WRONG_STATE("KW_I2C_IRQ_STOP"); - *rc = -EIO; - } - return state_idle; - } - - if (isr & KW_I2C_IRQ_START) - kw_write_reg(reg_isr, KW_I2C_IRQ_START); - - return state; - - stop: - kw_write_reg(reg_control, KW_I2C_CTL_STOP); - return state_stop; -} - -static int keywest_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 subaddr, u8 *data, int len) -{ - u8 mode_reg = host->speed; - int state = state_addr; - int rc = 0; - - /* Setup mode & subaddress if any */ - switch(host->mode) { - case pmac_low_i2c_mode_dumb: - printk(KERN_ERR "low_i2c: Dumb mode not supported !\n"); - return -EINVAL; - case pmac_low_i2c_mode_std: - mode_reg |= KW_I2C_MODE_STANDARD; - break; - case pmac_low_i2c_mode_stdsub: - mode_reg |= KW_I2C_MODE_STANDARDSUB; - kw_write_reg(reg_subaddr, subaddr); - break; - case pmac_low_i2c_mode_combined: - mode_reg |= KW_I2C_MODE_COMBINED; - kw_write_reg(reg_subaddr, subaddr); - break; - } - - /* Setup channel & clear pending irqs */ - kw_write_reg(reg_isr, kw_read_reg(reg_isr)); - kw_write_reg(reg_mode, mode_reg | (host->channel << 4)); - kw_write_reg(reg_status, 0); - - /* Set up address and r/w bit */ - kw_write_reg(reg_addr, addr); - - /* Start sending address & disable interrupt*/ - kw_write_reg(reg_ier, 0 /*KW_I2C_IRQ_MASK*/); - kw_write_reg(reg_control, KW_I2C_CTL_XADDR); - - /* State machine, to turn into an interrupt handler */ - while(state != state_idle) { - u8 isr = kw_wait_interrupt(host); - state = kw_handle_interrupt(host, state, addr & 1, &rc, &data, &len, isr); - } - - return rc; -} - -static void keywest_low_i2c_add(struct device_node *np) -{ - struct low_i2c_host *host = find_low_i2c_host(NULL); - unsigned long *psteps, *prate, steps, aoffset = 0; - struct device_node *parent; - - if (host == NULL) { - printk(KERN_ERR "low_i2c: Can't allocate host for %s\n", - np->full_name); - return; - } - memset(host, 0, sizeof(*host)); - - init_MUTEX(&host->mutex); - host->np = of_node_get(np); - psteps = (unsigned long *)get_property(np, "AAPL,address-step", NULL); - steps = psteps ? (*psteps) : 0x10; - for (host->bsteps = 0; (steps & 0x01) == 0; host->bsteps++) - steps >>= 1; - parent = of_get_parent(np); - host->num_channels = 1; - if (parent && parent->name[0] == 'u') { - host->num_channels = 2; - aoffset = 3; - } - /* Select interface rate */ - host->speed = KW_I2C_MODE_100KHZ; - prate = (unsigned long *)get_property(np, "AAPL,i2c-rate", NULL); - if (prate) switch(*prate) { - case 100: - host->speed = KW_I2C_MODE_100KHZ; - break; - case 50: - host->speed = KW_I2C_MODE_50KHZ; - break; - case 25: - host->speed = KW_I2C_MODE_25KHZ; - break; - } - host->mode = pmac_low_i2c_mode_std; - host->base = ioremap(np->addrs[0].address + aoffset, - np->addrs[0].size); - host->func = keywest_low_i2c_func; -} - -/* - * - * PMU implementation - * - */ - - -#ifdef CONFIG_ADB_PMU - -static int pmu_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len) -{ - // TODO - return -ENODEV; -} - -static void pmu_low_i2c_add(struct device_node *np) -{ - struct low_i2c_host *host = find_low_i2c_host(NULL); - - if (host == NULL) { - printk(KERN_ERR "low_i2c: Can't allocate host for %s\n", - np->full_name); - return; - } - memset(host, 0, sizeof(*host)); - - init_MUTEX(&host->mutex); - host->np = of_node_get(np); - host->num_channels = 3; - host->mode = pmac_low_i2c_mode_std; - host->func = pmu_low_i2c_func; -} - -#endif /* CONFIG_ADB_PMU */ - -void __init pmac_init_low_i2c(void) -{ - struct device_node *np; - - /* Probe keywest-i2c busses */ - np = of_find_compatible_node(NULL, "i2c", "keywest-i2c"); - while(np) { - keywest_low_i2c_add(np); - np = of_find_compatible_node(np, "i2c", "keywest-i2c"); - } - -#ifdef CONFIG_ADB_PMU - /* Probe PMU busses */ - np = of_find_node_by_name(NULL, "via-pmu"); - if (np) - pmu_low_i2c_add(np); -#endif /* CONFIG_ADB_PMU */ - - /* TODO: Add CUDA support as well */ -} - -int pmac_low_i2c_lock(struct device_node *np) -{ - struct low_i2c_host *host = find_low_i2c_host(np); - - if (!host) - return -ENODEV; - down(&host->mutex); - return 0; -} -EXPORT_SYMBOL(pmac_low_i2c_lock); - -int pmac_low_i2c_unlock(struct device_node *np) -{ - struct low_i2c_host *host = find_low_i2c_host(np); - - if (!host) - return -ENODEV; - up(&host->mutex); - return 0; -} -EXPORT_SYMBOL(pmac_low_i2c_unlock); - - -int pmac_low_i2c_open(struct device_node *np, int channel) -{ - struct low_i2c_host *host = find_low_i2c_host(np); - - if (!host) - return -ENODEV; - - if (channel >= host->num_channels) - return -EINVAL; - - down(&host->mutex); - host->is_open = 1; - host->channel = channel; - - return 0; -} -EXPORT_SYMBOL(pmac_low_i2c_open); - -int pmac_low_i2c_close(struct device_node *np) -{ - struct low_i2c_host *host = find_low_i2c_host(np); - - if (!host) - return -ENODEV; - - host->is_open = 0; - up(&host->mutex); - - return 0; -} -EXPORT_SYMBOL(pmac_low_i2c_close); - -int pmac_low_i2c_setmode(struct device_node *np, int mode) -{ - struct low_i2c_host *host = find_low_i2c_host(np); - - if (!host) - return -ENODEV; - WARN_ON(!host->is_open); - host->mode = mode; - - return 0; -} -EXPORT_SYMBOL(pmac_low_i2c_setmode); - -int pmac_low_i2c_xfer(struct device_node *np, u8 addrdir, u8 subaddr, u8 *data, int len) -{ - struct low_i2c_host *host = find_low_i2c_host(np); - - if (!host) - return -ENODEV; - WARN_ON(!host->is_open); - - return host->func(host, addrdir, subaddr, data, len); -} -EXPORT_SYMBOL(pmac_low_i2c_xfer); - diff --git a/arch/ppc/platforms/pmac_nvram.c b/arch/ppc/platforms/pmac_nvram.c deleted file mode 100644 index 8c9b008c722..00000000000 --- a/arch/ppc/platforms/pmac_nvram.c +++ /dev/null @@ -1,584 +0,0 @@ -/* - * arch/ppc/platforms/pmac_nvram.c - * - * Copyright (C) 2002 Benjamin Herrenschmidt (benh@kernel.crashing.org) - * - * 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. - * - * Todo: - add support for the OF persistent properties - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DEBUG - -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -#define NVRAM_SIZE 0x2000 /* 8kB of non-volatile RAM */ - -#define CORE99_SIGNATURE 0x5a -#define CORE99_ADLER_START 0x14 - -/* On Core99, nvram is either a sharp, a micron or an AMD flash */ -#define SM_FLASH_STATUS_DONE 0x80 -#define SM_FLASH_STATUS_ERR 0x38 -#define SM_FLASH_CMD_ERASE_CONFIRM 0xd0 -#define SM_FLASH_CMD_ERASE_SETUP 0x20 -#define SM_FLASH_CMD_RESET 0xff -#define SM_FLASH_CMD_WRITE_SETUP 0x40 -#define SM_FLASH_CMD_CLEAR_STATUS 0x50 -#define SM_FLASH_CMD_READ_STATUS 0x70 - -/* CHRP NVRAM header */ -struct chrp_header { - u8 signature; - u8 cksum; - u16 len; - char name[12]; - u8 data[0]; -}; - -struct core99_header { - struct chrp_header hdr; - u32 adler; - u32 generation; - u32 reserved[2]; -}; - -/* - * Read and write the non-volatile RAM on PowerMacs and CHRP machines. - */ -static int nvram_naddrs; -static volatile unsigned char *nvram_addr; -static volatile unsigned char *nvram_data; -static int nvram_mult, is_core_99; -static int core99_bank = 0; -static int nvram_partitions[3]; -static DEFINE_SPINLOCK(nv_lock); - -extern int pmac_newworld; -extern int system_running; - -static int (*core99_write_bank)(int bank, u8* datas); -static int (*core99_erase_bank)(int bank); - -static char *nvram_image; - - -static unsigned char core99_nvram_read_byte(int addr) -{ - if (nvram_image == NULL) - return 0xff; - return nvram_image[addr]; -} - -static void core99_nvram_write_byte(int addr, unsigned char val) -{ - if (nvram_image == NULL) - return; - nvram_image[addr] = val; -} - - -static unsigned char direct_nvram_read_byte(int addr) -{ - return in_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult]); -} - -static void direct_nvram_write_byte(int addr, unsigned char val) -{ - out_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult], val); -} - - -static unsigned char indirect_nvram_read_byte(int addr) -{ - unsigned char val; - unsigned long flags; - - spin_lock_irqsave(&nv_lock, flags); - out_8(nvram_addr, addr >> 5); - val = in_8(&nvram_data[(addr & 0x1f) << 4]); - spin_unlock_irqrestore(&nv_lock, flags); - - return val; -} - -static void indirect_nvram_write_byte(int addr, unsigned char val) -{ - unsigned long flags; - - spin_lock_irqsave(&nv_lock, flags); - out_8(nvram_addr, addr >> 5); - out_8(&nvram_data[(addr & 0x1f) << 4], val); - spin_unlock_irqrestore(&nv_lock, flags); -} - - -#ifdef CONFIG_ADB_PMU - -static void pmu_nvram_complete(struct adb_request *req) -{ - if (req->arg) - complete((struct completion *)req->arg); -} - -static unsigned char pmu_nvram_read_byte(int addr) -{ - struct adb_request req; - DECLARE_COMPLETION(req_complete); - - req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL; - if (pmu_request(&req, pmu_nvram_complete, 3, PMU_READ_NVRAM, - (addr >> 8) & 0xff, addr & 0xff)) - return 0xff; - if (system_state == SYSTEM_RUNNING) - wait_for_completion(&req_complete); - while (!req.complete) - pmu_poll(); - return req.reply[0]; -} - -static void pmu_nvram_write_byte(int addr, unsigned char val) -{ - struct adb_request req; - DECLARE_COMPLETION(req_complete); - - req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL; - if (pmu_request(&req, pmu_nvram_complete, 4, PMU_WRITE_NVRAM, - (addr >> 8) & 0xff, addr & 0xff, val)) - return; - if (system_state == SYSTEM_RUNNING) - wait_for_completion(&req_complete); - while (!req.complete) - pmu_poll(); -} - -#endif /* CONFIG_ADB_PMU */ - - -static u8 chrp_checksum(struct chrp_header* hdr) -{ - u8 *ptr; - u16 sum = hdr->signature; - for (ptr = (u8 *)&hdr->len; ptr < hdr->data; ptr++) - sum += *ptr; - while (sum > 0xFF) - sum = (sum & 0xFF) + (sum>>8); - return sum; -} - -static u32 core99_calc_adler(u8 *buffer) -{ - int cnt; - u32 low, high; - - buffer += CORE99_ADLER_START; - low = 1; - high = 0; - for (cnt=0; cnt<(NVRAM_SIZE-CORE99_ADLER_START); cnt++) { - if ((cnt % 5000) == 0) { - high %= 65521UL; - high %= 65521UL; - } - low += buffer[cnt]; - high += low; - } - low %= 65521UL; - high %= 65521UL; - - return (high << 16) | low; -} - -static u32 core99_check(u8* datas) -{ - struct core99_header* hdr99 = (struct core99_header*)datas; - - if (hdr99->hdr.signature != CORE99_SIGNATURE) { - DBG("Invalid signature\n"); - return 0; - } - if (hdr99->hdr.cksum != chrp_checksum(&hdr99->hdr)) { - DBG("Invalid checksum\n"); - return 0; - } - if (hdr99->adler != core99_calc_adler(datas)) { - DBG("Invalid adler\n"); - return 0; - } - return hdr99->generation; -} - -static int sm_erase_bank(int bank) -{ - int stat, i; - unsigned long timeout; - - u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE; - - DBG("nvram: Sharp/Micron Erasing bank %d...\n", bank); - - out_8(base, SM_FLASH_CMD_ERASE_SETUP); - out_8(base, SM_FLASH_CMD_ERASE_CONFIRM); - timeout = 0; - do { - if (++timeout > 1000000) { - printk(KERN_ERR "nvram: Sharp/Miron flash erase timeout !\n"); - break; - } - out_8(base, SM_FLASH_CMD_READ_STATUS); - stat = in_8(base); - } while (!(stat & SM_FLASH_STATUS_DONE)); - - out_8(base, SM_FLASH_CMD_CLEAR_STATUS); - out_8(base, SM_FLASH_CMD_RESET); - - for (i=0; i 1000000) { - printk(KERN_ERR "nvram: Sharp/Micron flash write timeout !\n"); - break; - } - out_8(base, SM_FLASH_CMD_READ_STATUS); - stat = in_8(base); - } while (!(stat & SM_FLASH_STATUS_DONE)); - if (!(stat & SM_FLASH_STATUS_DONE)) - break; - } - out_8(base, SM_FLASH_CMD_CLEAR_STATUS); - out_8(base, SM_FLASH_CMD_RESET); - for (i=0; i 1000000) { - printk(KERN_ERR "nvram: AMD flash erase timeout !\n"); - break; - } - stat = in_8(base) ^ in_8(base); - } while (stat != 0); - - /* Reset */ - out_8(base, 0xf0); - udelay(1); - - for (i=0; i 1000000) { - printk(KERN_ERR "nvram: AMD flash write timeout !\n"); - break; - } - stat = in_8(base) ^ in_8(base); - } while (stat != 0); - if (stat != 0) - break; - } - - /* Reset */ - out_8(base, 0xf0); - udelay(1); - - for (i=0; iname, "common")) - nvram_partitions[pmac_nvram_OF] = offset + 0x10; - if (!strcmp(hdr->name, "APL,MacOS75")) { - nvram_partitions[pmac_nvram_XPRAM] = offset + 0x10; - nvram_partitions[pmac_nvram_NR] = offset + 0x110; - } - offset += (hdr->len * 0x10); - } while(offset < NVRAM_SIZE); - } else { - nvram_partitions[pmac_nvram_OF] = 0x1800; - nvram_partitions[pmac_nvram_XPRAM] = 0x1300; - nvram_partitions[pmac_nvram_NR] = 0x1400; - } - DBG("nvram: OF partition at 0x%x\n", nvram_partitions[pmac_nvram_OF]); - DBG("nvram: XP partition at 0x%x\n", nvram_partitions[pmac_nvram_XPRAM]); - DBG("nvram: NR partition at 0x%x\n", nvram_partitions[pmac_nvram_NR]); -} - -static void core99_nvram_sync(void) -{ - struct core99_header* hdr99; - unsigned long flags; - - if (!is_core_99 || !nvram_data || !nvram_image) - return; - - spin_lock_irqsave(&nv_lock, flags); - if (!memcmp(nvram_image, (u8*)nvram_data + core99_bank*NVRAM_SIZE, - NVRAM_SIZE)) - goto bail; - - DBG("Updating nvram...\n"); - - hdr99 = (struct core99_header*)nvram_image; - hdr99->generation++; - hdr99->hdr.signature = CORE99_SIGNATURE; - hdr99->hdr.cksum = chrp_checksum(&hdr99->hdr); - hdr99->adler = core99_calc_adler(nvram_image); - core99_bank = core99_bank ? 0 : 1; - if (core99_erase_bank) - if (core99_erase_bank(core99_bank)) { - printk("nvram: Error erasing bank %d\n", core99_bank); - goto bail; - } - if (core99_write_bank) - if (core99_write_bank(core99_bank, nvram_image)) - printk("nvram: Error writing bank %d\n", core99_bank); - bail: - spin_unlock_irqrestore(&nv_lock, flags); - -#ifdef DEBUG - mdelay(2000); -#endif -} - -void __init pmac_nvram_init(void) -{ - struct device_node *dp; - - nvram_naddrs = 0; - - dp = find_devices("nvram"); - if (dp == NULL) { - printk(KERN_ERR "Can't find NVRAM device\n"); - return; - } - nvram_naddrs = dp->n_addrs; - is_core_99 = device_is_compatible(dp, "nvram,flash"); - if (is_core_99) { - int i; - u32 gen_bank0, gen_bank1; - - if (nvram_naddrs < 1) { - printk(KERN_ERR "nvram: no address\n"); - return; - } - nvram_image = alloc_bootmem(NVRAM_SIZE); - if (nvram_image == NULL) { - printk(KERN_ERR "nvram: can't allocate ram image\n"); - return; - } - nvram_data = ioremap(dp->addrs[0].address, NVRAM_SIZE*2); - nvram_naddrs = 1; /* Make sure we get the correct case */ - - DBG("nvram: Checking bank 0...\n"); - - gen_bank0 = core99_check((u8 *)nvram_data); - gen_bank1 = core99_check((u8 *)nvram_data + NVRAM_SIZE); - core99_bank = (gen_bank0 < gen_bank1) ? 1 : 0; - - DBG("nvram: gen0=%d, gen1=%d\n", gen_bank0, gen_bank1); - DBG("nvram: Active bank is: %d\n", core99_bank); - - for (i=0; iaddrs[0].address + isa_mem_base, - dp->addrs[0].size); - nvram_mult = 1; - ppc_md.nvram_read_val = direct_nvram_read_byte; - ppc_md.nvram_write_val = direct_nvram_write_byte; - } else if (nvram_naddrs == 1) { - nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size); - nvram_mult = (dp->addrs[0].size + NVRAM_SIZE - 1) / NVRAM_SIZE; - ppc_md.nvram_read_val = direct_nvram_read_byte; - ppc_md.nvram_write_val = direct_nvram_write_byte; - } else if (nvram_naddrs == 2) { - nvram_addr = ioremap(dp->addrs[0].address, dp->addrs[0].size); - nvram_data = ioremap(dp->addrs[1].address, dp->addrs[1].size); - ppc_md.nvram_read_val = indirect_nvram_read_byte; - ppc_md.nvram_write_val = indirect_nvram_write_byte; - } else if (nvram_naddrs == 0 && sys_ctrler == SYS_CTRLER_PMU) { -#ifdef CONFIG_ADB_PMU - nvram_naddrs = -1; - ppc_md.nvram_read_val = pmu_nvram_read_byte; - ppc_md.nvram_write_val = pmu_nvram_write_byte; -#endif /* CONFIG_ADB_PMU */ - } else { - printk(KERN_ERR "Don't know how to access NVRAM with %d addresses\n", - nvram_naddrs); - } - lookup_partitions(); -} - -int pmac_get_partition(int partition) -{ - return nvram_partitions[partition]; -} - -u8 pmac_xpram_read(int xpaddr) -{ - int offset = nvram_partitions[pmac_nvram_XPRAM]; - - if (offset < 0) - return 0xff; - - return ppc_md.nvram_read_val(xpaddr + offset); -} - -void pmac_xpram_write(int xpaddr, u8 data) -{ - int offset = nvram_partitions[pmac_nvram_XPRAM]; - - if (offset < 0) - return; - - ppc_md.nvram_write_val(xpaddr + offset, data); -} - -EXPORT_SYMBOL(pmac_get_partition); -EXPORT_SYMBOL(pmac_xpram_read); -EXPORT_SYMBOL(pmac_xpram_write); diff --git a/arch/ppc/platforms/pmac_pci.c b/arch/ppc/platforms/pmac_pci.c deleted file mode 100644 index 786295b6ddd..00000000000 --- a/arch/ppc/platforms/pmac_pci.c +++ /dev/null @@ -1,1124 +0,0 @@ -/* - * Support for PCI bridges found on Power Macintoshes. - * At present the "bandit" and "chaos" bridges are supported. - * Fortunately you access configuration space in the same - * way with either bridge. - * - * Copyright (C) 1997 Paul Mackerras (paulus@cs.anu.edu.au) - * - * 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 -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#undef DEBUG - -#ifdef DEBUG -#ifdef CONFIG_XMON -extern void xmon_printf(const char *fmt, ...); -#define DBG(x...) xmon_printf(x) -#else -#define DBG(x...) printk(x) -#endif -#else -#define DBG(x...) -#endif - -static int add_bridge(struct device_node *dev); -extern void pmac_check_ht_link(void); - -/* XXX Could be per-controller, but I don't think we risk anything by - * assuming we won't have both UniNorth and Bandit */ -static int has_uninorth; -#ifdef CONFIG_POWER4 -static struct pci_controller *u3_agp; -#endif /* CONFIG_POWER4 */ - -extern u8 pci_cache_line_size; -extern int pcibios_assign_bus_offset; - -struct device_node *k2_skiplist[2]; - -/* - * Magic constants for enabling cache coherency in the bandit/PSX bridge. - */ -#define BANDIT_DEVID_2 8 -#define BANDIT_REVID 3 - -#define BANDIT_DEVNUM 11 -#define BANDIT_MAGIC 0x50 -#define BANDIT_COHERENT 0x40 - -static int __init -fixup_one_level_bus_range(struct device_node *node, int higher) -{ - for (; node != 0;node = node->sibling) { - int * bus_range; - unsigned int *class_code; - int len; - - /* For PCI<->PCI bridges or CardBus bridges, we go down */ - class_code = (unsigned int *) get_property(node, "class-code", NULL); - if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI && - (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) - continue; - bus_range = (int *) get_property(node, "bus-range", &len); - if (bus_range != NULL && len > 2 * sizeof(int)) { - if (bus_range[1] > higher) - higher = bus_range[1]; - } - higher = fixup_one_level_bus_range(node->child, higher); - } - return higher; -} - -/* This routine fixes the "bus-range" property of all bridges in the - * system since they tend to have their "last" member wrong on macs - * - * Note that the bus numbers manipulated here are OF bus numbers, they - * are not Linux bus numbers. - */ -static void __init -fixup_bus_range(struct device_node *bridge) -{ - int * bus_range; - int len; - - /* Lookup the "bus-range" property for the hose */ - bus_range = (int *) get_property(bridge, "bus-range", &len); - if (bus_range == NULL || len < 2 * sizeof(int)) { - printk(KERN_WARNING "Can't get bus-range for %s\n", - bridge->full_name); - return; - } - bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]); -} - -/* - * Apple MacRISC (U3, UniNorth, Bandit, Chaos) PCI controllers. - * - * The "Bandit" version is present in all early PCI PowerMacs, - * and up to the first ones using Grackle. Some machines may - * have 2 bandit controllers (2 PCI busses). - * - * "Chaos" is used in some "Bandit"-type machines as a bridge - * for the separate display bus. It is accessed the same - * way as bandit, but cannot be probed for devices. It therefore - * has its own config access functions. - * - * The "UniNorth" version is present in all Core99 machines - * (iBook, G4, new IMacs, and all the recent Apple machines). - * It contains 3 controllers in one ASIC. - * - * The U3 is the bridge used on G5 machines. It contains an - * AGP bus which is dealt with the old UniNorth access routines - * and a HyperTransport bus which uses its own set of access - * functions. - */ - -#define MACRISC_CFA0(devfn, off) \ - ((1 << (unsigned long)PCI_SLOT(dev_fn)) \ - | (((unsigned long)PCI_FUNC(dev_fn)) << 8) \ - | (((unsigned long)(off)) & 0xFCUL)) - -#define MACRISC_CFA1(bus, devfn, off) \ - ((((unsigned long)(bus)) << 16) \ - |(((unsigned long)(devfn)) << 8) \ - |(((unsigned long)(off)) & 0xFCUL) \ - |1UL) - -static void volatile __iomem * -macrisc_cfg_access(struct pci_controller* hose, u8 bus, u8 dev_fn, u8 offset) -{ - unsigned int caddr; - - if (bus == hose->first_busno) { - if (dev_fn < (11 << 3)) - return NULL; - caddr = MACRISC_CFA0(dev_fn, offset); - } else - caddr = MACRISC_CFA1(bus, dev_fn, offset); - - /* Uninorth will return garbage if we don't read back the value ! */ - do { - out_le32(hose->cfg_addr, caddr); - } while (in_le32(hose->cfg_addr) != caddr); - - offset &= has_uninorth ? 0x07 : 0x03; - return hose->cfg_data + offset; -} - -static int -macrisc_read_config(struct pci_bus *bus, unsigned int devfn, int offset, - int len, u32 *val) -{ - struct pci_controller *hose = bus->sysdata; - void volatile __iomem *addr; - - addr = macrisc_cfg_access(hose, bus->number, devfn, offset); - if (!addr) - return PCIBIOS_DEVICE_NOT_FOUND; - /* - * Note: the caller has already checked that offset is - * suitably aligned and that len is 1, 2 or 4. - */ - switch (len) { - case 1: - *val = in_8(addr); - break; - case 2: - *val = in_le16(addr); - break; - default: - *val = in_le32(addr); - break; - } - return PCIBIOS_SUCCESSFUL; -} - -static int -macrisc_write_config(struct pci_bus *bus, unsigned int devfn, int offset, - int len, u32 val) -{ - struct pci_controller *hose = bus->sysdata; - void volatile __iomem *addr; - - addr = macrisc_cfg_access(hose, bus->number, devfn, offset); - if (!addr) - return PCIBIOS_DEVICE_NOT_FOUND; - /* - * Note: the caller has already checked that offset is - * suitably aligned and that len is 1, 2 or 4. - */ - switch (len) { - case 1: - out_8(addr, val); - (void) in_8(addr); - break; - case 2: - out_le16(addr, val); - (void) in_le16(addr); - break; - default: - out_le32(addr, val); - (void) in_le32(addr); - break; - } - return PCIBIOS_SUCCESSFUL; -} - -static struct pci_ops macrisc_pci_ops = -{ - macrisc_read_config, - macrisc_write_config -}; - -/* - * Verifiy that a specific (bus, dev_fn) exists on chaos - */ -static int -chaos_validate_dev(struct pci_bus *bus, int devfn, int offset) -{ - struct device_node *np; - u32 *vendor, *device; - - np = pci_busdev_to_OF_node(bus, devfn); - if (np == NULL) - return PCIBIOS_DEVICE_NOT_FOUND; - - vendor = (u32 *)get_property(np, "vendor-id", NULL); - device = (u32 *)get_property(np, "device-id", NULL); - if (vendor == NULL || device == NULL) - return PCIBIOS_DEVICE_NOT_FOUND; - - if ((*vendor == 0x106b) && (*device == 3) && (offset >= 0x10) - && (offset != 0x14) && (offset != 0x18) && (offset <= 0x24)) - return PCIBIOS_BAD_REGISTER_NUMBER; - - return PCIBIOS_SUCCESSFUL; -} - -static int -chaos_read_config(struct pci_bus *bus, unsigned int devfn, int offset, - int len, u32 *val) -{ - int result = chaos_validate_dev(bus, devfn, offset); - if (result == PCIBIOS_BAD_REGISTER_NUMBER) - *val = ~0U; - if (result != PCIBIOS_SUCCESSFUL) - return result; - return macrisc_read_config(bus, devfn, offset, len, val); -} - -static int -chaos_write_config(struct pci_bus *bus, unsigned int devfn, int offset, - int len, u32 val) -{ - int result = chaos_validate_dev(bus, devfn, offset); - if (result != PCIBIOS_SUCCESSFUL) - return result; - return macrisc_write_config(bus, devfn, offset, len, val); -} - -static struct pci_ops chaos_pci_ops = -{ - chaos_read_config, - chaos_write_config -}; - -#ifdef CONFIG_POWER4 - -/* - * These versions of U3 HyperTransport config space access ops do not - * implement self-view of the HT host yet - */ - -#define U3_HT_CFA0(devfn, off) \ - ((((unsigned long)devfn) << 8) | offset) -#define U3_HT_CFA1(bus, devfn, off) \ - (U3_HT_CFA0(devfn, off) \ - + (((unsigned long)bus) << 16) \ - + 0x01000000UL) - -static void volatile __iomem * -u3_ht_cfg_access(struct pci_controller* hose, u8 bus, u8 devfn, u8 offset) -{ - if (bus == hose->first_busno) { - /* For now, we don't self probe U3 HT bridge */ - if (PCI_FUNC(devfn) != 0 || PCI_SLOT(devfn) > 7 || - PCI_SLOT(devfn) < 1) - return 0; - return hose->cfg_data + U3_HT_CFA0(devfn, offset); - } else - return hose->cfg_data + U3_HT_CFA1(bus, devfn, offset); -} - -static int -u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, int offset, - int len, u32 *val) -{ - struct pci_controller *hose = bus->sysdata; - void volatile __iomem *addr; - int i; - - struct device_node *np = pci_busdev_to_OF_node(bus, devfn); - if (np == NULL) - return PCIBIOS_DEVICE_NOT_FOUND; - - /* - * When a device in K2 is powered down, we die on config - * cycle accesses. Fix that here. - */ - for (i=0; i<2; i++) - if (k2_skiplist[i] == np) { - switch (len) { - case 1: - *val = 0xff; break; - case 2: - *val = 0xffff; break; - default: - *val = 0xfffffffful; break; - } - return PCIBIOS_SUCCESSFUL; - } - - addr = u3_ht_cfg_access(hose, bus->number, devfn, offset); - if (!addr) - return PCIBIOS_DEVICE_NOT_FOUND; - /* - * Note: the caller has already checked that offset is - * suitably aligned and that len is 1, 2 or 4. - */ - switch (len) { - case 1: - *val = in_8(addr); - break; - case 2: - *val = in_le16(addr); - break; - default: - *val = in_le32(addr); - break; - } - return PCIBIOS_SUCCESSFUL; -} - -static int -u3_ht_write_config(struct pci_bus *bus, unsigned int devfn, int offset, - int len, u32 val) -{ - struct pci_controller *hose = bus->sysdata; - void volatile __iomem *addr; - int i; - - struct device_node *np = pci_busdev_to_OF_node(bus, devfn); - if (np == NULL) - return PCIBIOS_DEVICE_NOT_FOUND; - /* - * When a device in K2 is powered down, we die on config - * cycle accesses. Fix that here. - */ - for (i=0; i<2; i++) - if (k2_skiplist[i] == np) - return PCIBIOS_SUCCESSFUL; - - addr = u3_ht_cfg_access(hose, bus->number, devfn, offset); - if (!addr) - return PCIBIOS_DEVICE_NOT_FOUND; - /* - * Note: the caller has already checked that offset is - * suitably aligned and that len is 1, 2 or 4. - */ - switch (len) { - case 1: - out_8(addr, val); - (void) in_8(addr); - break; - case 2: - out_le16(addr, val); - (void) in_le16(addr); - break; - default: - out_le32(addr, val); - (void) in_le32(addr); - break; - } - return PCIBIOS_SUCCESSFUL; -} - -static struct pci_ops u3_ht_pci_ops = -{ - u3_ht_read_config, - u3_ht_write_config -}; - -#endif /* CONFIG_POWER4 */ - -/* - * For a bandit bridge, turn on cache coherency if necessary. - * N.B. we could clean this up using the hose ops directly. - */ -static void __init -init_bandit(struct pci_controller *bp) -{ - unsigned int vendev, magic; - int rev; - - /* read the word at offset 0 in config space for device 11 */ - out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_VENDOR_ID); - udelay(2); - vendev = in_le32(bp->cfg_data); - if (vendev == (PCI_DEVICE_ID_APPLE_BANDIT << 16) + - PCI_VENDOR_ID_APPLE) { - /* read the revision id */ - out_le32(bp->cfg_addr, - (1UL << BANDIT_DEVNUM) + PCI_REVISION_ID); - udelay(2); - rev = in_8(bp->cfg_data); - if (rev != BANDIT_REVID) - printk(KERN_WARNING - "Unknown revision %d for bandit\n", rev); - } else if (vendev != (BANDIT_DEVID_2 << 16) + PCI_VENDOR_ID_APPLE) { - printk(KERN_WARNING "bandit isn't? (%x)\n", vendev); - return; - } - - /* read the word at offset 0x50 */ - out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + BANDIT_MAGIC); - udelay(2); - magic = in_le32(bp->cfg_data); - if ((magic & BANDIT_COHERENT) != 0) - return; - magic |= BANDIT_COHERENT; - udelay(2); - out_le32(bp->cfg_data, magic); - printk(KERN_INFO "Cache coherency enabled for bandit/PSX\n"); -} - - -/* - * Tweak the PCI-PCI bridge chip on the blue & white G3s. - */ -static void __init -init_p2pbridge(void) -{ - struct device_node *p2pbridge; - struct pci_controller* hose; - u8 bus, devfn; - u16 val; - - /* XXX it would be better here to identify the specific - PCI-PCI bridge chip we have. */ - if ((p2pbridge = find_devices("pci-bridge")) == 0 - || p2pbridge->parent == NULL - || strcmp(p2pbridge->parent->name, "pci") != 0) - return; - if (pci_device_from_OF_node(p2pbridge, &bus, &devfn) < 0) { - DBG("Can't find PCI infos for PCI<->PCI bridge\n"); - return; - } - /* Warning: At this point, we have not yet renumbered all busses. - * So we must use OF walking to find out hose - */ - hose = pci_find_hose_for_OF_device(p2pbridge); - if (!hose) { - DBG("Can't find hose for PCI<->PCI bridge\n"); - return; - } - if (early_read_config_word(hose, bus, devfn, - PCI_BRIDGE_CONTROL, &val) < 0) { - printk(KERN_ERR "init_p2pbridge: couldn't read bridge control\n"); - return; - } - val &= ~PCI_BRIDGE_CTL_MASTER_ABORT; - early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, val); -} - -/* - * Some Apple desktop machines have a NEC PD720100A USB2 controller - * on the motherboard. Open Firmware, on these, will disable the - * EHCI part of it so it behaves like a pair of OHCI's. This fixup - * code re-enables it ;) - */ -static void __init -fixup_nec_usb2(void) -{ - struct device_node *nec; - - for (nec = NULL; (nec = of_find_node_by_name(nec, "usb")) != NULL;) { - struct pci_controller *hose; - u32 data, *prop; - u8 bus, devfn; - - prop = (u32 *)get_property(nec, "vendor-id", NULL); - if (prop == NULL) - continue; - if (0x1033 != *prop) - continue; - prop = (u32 *)get_property(nec, "device-id", NULL); - if (prop == NULL) - continue; - if (0x0035 != *prop) - continue; - prop = (u32 *)get_property(nec, "reg", NULL); - if (prop == NULL) - continue; - devfn = (prop[0] >> 8) & 0xff; - bus = (prop[0] >> 16) & 0xff; - if (PCI_FUNC(devfn) != 0) - continue; - hose = pci_find_hose_for_OF_device(nec); - if (!hose) - continue; - early_read_config_dword(hose, bus, devfn, 0xe4, &data); - if (data & 1UL) { - printk("Found NEC PD720100A USB2 chip with disabled EHCI, fixing up...\n"); - data &= ~1UL; - early_write_config_dword(hose, bus, devfn, 0xe4, data); - early_write_config_byte(hose, bus, devfn | 2, PCI_INTERRUPT_LINE, - nec->intrs[0].line); - } - } -} - -void __init -pmac_find_bridges(void) -{ - struct device_node *np, *root; - struct device_node *ht = NULL; - - root = of_find_node_by_path("/"); - if (root == NULL) { - printk(KERN_CRIT "pmac_find_bridges: can't find root of device tree\n"); - return; - } - for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) { - if (np->name == NULL) - continue; - if (strcmp(np->name, "bandit") == 0 - || strcmp(np->name, "chaos") == 0 - || strcmp(np->name, "pci") == 0) { - if (add_bridge(np) == 0) - of_node_get(np); - } - if (strcmp(np->name, "ht") == 0) { - of_node_get(np); - ht = np; - } - } - of_node_put(root); - - /* Probe HT last as it relies on the agp resources to be already - * setup - */ - if (ht && add_bridge(ht) != 0) - of_node_put(ht); - - init_p2pbridge(); - fixup_nec_usb2(); - - /* We are still having some issues with the Xserve G4, enabling - * some offset between bus number and domains for now when we - * assign all busses should help for now - */ - if (pci_assign_all_buses) - pcibios_assign_bus_offset = 0x10; - -#ifdef CONFIG_POWER4 - /* There is something wrong with DMA on U3/HT. I haven't figured out - * the details yet, but if I set the cache line size to 128 bytes like - * it should, I'm getting memory corruption caused by devices like - * sungem (even without the MWI bit set, but maybe sungem doesn't - * care). Right now, it appears that setting up a 64 bytes line size - * works properly, 64 bytes beeing the max transfer size of HT, I - * suppose this is related the way HT/PCI are hooked together. I still - * need to dive into more specs though to be really sure of what's - * going on. --BenH. - * - * Ok, apparently, it's just that HT can't do more than 64 bytes - * transactions. MWI seem to be meaningless there as well, it may - * be worth nop'ing out pci_set_mwi too though I haven't done that - * yet. - * - * Note that it's a bit different for whatever is in the AGP slot. - * For now, I don't care, but this can become a real issue, we - * should probably hook pci_set_mwi anyway to make sure it sets - * the real cache line size in there. - */ - if (machine_is_compatible("MacRISC4")) - pci_cache_line_size = 16; /* 64 bytes */ - - pmac_check_ht_link(); -#endif /* CONFIG_POWER4 */ -} - -#define GRACKLE_CFA(b, d, o) (0x80 | ((b) << 8) | ((d) << 16) \ - | (((o) & ~3) << 24)) - -#define GRACKLE_PICR1_STG 0x00000040 -#define GRACKLE_PICR1_LOOPSNOOP 0x00000010 - -/* N.B. this is called before bridges is initialized, so we can't - use grackle_pcibios_{read,write}_config_dword. */ -static inline void grackle_set_stg(struct pci_controller* bp, int enable) -{ - unsigned int val; - - out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8)); - val = in_le32(bp->cfg_data); - val = enable? (val | GRACKLE_PICR1_STG) : - (val & ~GRACKLE_PICR1_STG); - out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8)); - out_le32(bp->cfg_data, val); - (void)in_le32(bp->cfg_data); -} - -static inline void grackle_set_loop_snoop(struct pci_controller *bp, int enable) -{ - unsigned int val; - - out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8)); - val = in_le32(bp->cfg_data); - val = enable? (val | GRACKLE_PICR1_LOOPSNOOP) : - (val & ~GRACKLE_PICR1_LOOPSNOOP); - out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8)); - out_le32(bp->cfg_data, val); - (void)in_le32(bp->cfg_data); -} - -static int __init -setup_uninorth(struct pci_controller* hose, struct reg_property* addr) -{ - pci_assign_all_buses = 1; - has_uninorth = 1; - hose->ops = ¯isc_pci_ops; - hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000); - hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000); - /* We "know" that the bridge at f2000000 has the PCI slots. */ - return addr->address == 0xf2000000; -} - -static void __init -setup_bandit(struct pci_controller* hose, struct reg_property* addr) -{ - hose->ops = ¯isc_pci_ops; - hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000); - hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000); - init_bandit(hose); -} - -static void __init -setup_chaos(struct pci_controller* hose, struct reg_property* addr) -{ - /* assume a `chaos' bridge */ - hose->ops = &chaos_pci_ops; - hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000); - hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000); -} - -#ifdef CONFIG_POWER4 - -static void __init -setup_u3_agp(struct pci_controller* hose, struct reg_property* addr) -{ - /* On G5, we move AGP up to high bus number so we don't need - * to reassign bus numbers for HT. If we ever have P2P bridges - * on AGP, we'll have to move pci_assign_all_buses to the - * pci_controller structure so we enable it for AGP and not for - * HT childs. - * We hard code the address because of the different size of - * the reg address cell, we shall fix that by killing struct - * reg_property and using some accessor functions instead - */ - hose->first_busno = 0xf0; - hose->last_busno = 0xff; - has_uninorth = 1; - hose->ops = ¯isc_pci_ops; - hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000); - hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000); - - u3_agp = hose; -} - -static void __init -setup_u3_ht(struct pci_controller* hose, struct reg_property *addr) -{ - struct device_node *np = (struct device_node *)hose->arch_data; - int i, cur; - - hose->ops = &u3_ht_pci_ops; - - /* We hard code the address because of the different size of - * the reg address cell, we shall fix that by killing struct - * reg_property and using some accessor functions instead - */ - hose->cfg_data = ioremap(0xf2000000, 0x02000000); - - /* - * /ht node doesn't expose a "ranges" property, so we "remove" regions that - * have been allocated to AGP. So far, this version of the code doesn't assign - * any of the 0xfxxxxxxx "fine" memory regions to /ht. - * We need to fix that sooner or later by either parsing all child "ranges" - * properties or figuring out the U3 address space decoding logic and - * then read its configuration register (if any). - */ - hose->io_base_phys = 0xf4000000; - hose->io_base_virt = ioremap(hose->io_base_phys, 0x00400000); - isa_io_base = (unsigned long) hose->io_base_virt; - hose->io_resource.name = np->full_name; - hose->io_resource.start = 0; - hose->io_resource.end = 0x003fffff; - hose->io_resource.flags = IORESOURCE_IO; - hose->pci_mem_offset = 0; - hose->first_busno = 0; - hose->last_busno = 0xef; - hose->mem_resources[0].name = np->full_name; - hose->mem_resources[0].start = 0x80000000; - hose->mem_resources[0].end = 0xefffffff; - hose->mem_resources[0].flags = IORESOURCE_MEM; - - if (u3_agp == NULL) { - DBG("U3 has no AGP, using full resource range\n"); - return; - } - - /* We "remove" the AGP resources from the resources allocated to HT, that - * is we create "holes". However, that code does assumptions that so far - * happen to be true (cross fingers...), typically that resources in the - * AGP node are properly ordered - */ - cur = 0; - for (i=0; i<3; i++) { - struct resource *res = &u3_agp->mem_resources[i]; - if (res->flags != IORESOURCE_MEM) - continue; - /* We don't care about "fine" resources */ - if (res->start >= 0xf0000000) - continue; - /* Check if it's just a matter of "shrinking" us in one direction */ - if (hose->mem_resources[cur].start == res->start) { - DBG("U3/HT: shrink start of %d, %08lx -> %08lx\n", - cur, hose->mem_resources[cur].start, res->end + 1); - hose->mem_resources[cur].start = res->end + 1; - continue; - } - if (hose->mem_resources[cur].end == res->end) { - DBG("U3/HT: shrink end of %d, %08lx -> %08lx\n", - cur, hose->mem_resources[cur].end, res->start - 1); - hose->mem_resources[cur].end = res->start - 1; - continue; - } - /* No, it's not the case, we need a hole */ - if (cur == 2) { - /* not enough resources to make a hole, we drop part of the range */ - printk(KERN_WARNING "Running out of resources for /ht host !\n"); - hose->mem_resources[cur].end = res->start - 1; - continue; - } - cur++; - DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n", - cur-1, res->start - 1, cur, res->end + 1); - hose->mem_resources[cur].name = np->full_name; - hose->mem_resources[cur].flags = IORESOURCE_MEM; - hose->mem_resources[cur].start = res->end + 1; - hose->mem_resources[cur].end = hose->mem_resources[cur-1].end; - hose->mem_resources[cur-1].end = res->start - 1; - } -} - -#endif /* CONFIG_POWER4 */ - -void __init -setup_grackle(struct pci_controller *hose) -{ - setup_indirect_pci(hose, 0xfec00000, 0xfee00000); - if (machine_is_compatible("AAPL,PowerBook1998")) - grackle_set_loop_snoop(hose, 1); -#if 0 /* Disabled for now, HW problems ??? */ - grackle_set_stg(hose, 1); -#endif -} - -/* - * We assume that if we have a G3 powermac, we have one bridge called - * "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise, - * if we have one or more bandit or chaos bridges, we don't have a MPC106. - */ -static int __init -add_bridge(struct device_node *dev) -{ - int len; - struct pci_controller *hose; - struct reg_property *addr; - char* disp_name; - int *bus_range; - int primary = 1; - - DBG("Adding PCI host bridge %s\n", dev->full_name); - - addr = (struct reg_property *) get_property(dev, "reg", &len); - if (addr == NULL || len < sizeof(*addr)) { - printk(KERN_WARNING "Can't use %s: no address\n", - dev->full_name); - return -ENODEV; - } - bus_range = (int *) get_property(dev, "bus-range", &len); - if (bus_range == NULL || len < 2 * sizeof(int)) { - printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n", - dev->full_name); - } - - hose = pcibios_alloc_controller(); - if (!hose) - return -ENOMEM; - hose->arch_data = dev; - hose->first_busno = bus_range ? bus_range[0] : 0; - hose->last_busno = bus_range ? bus_range[1] : 0xff; - - disp_name = NULL; -#ifdef CONFIG_POWER4 - if (device_is_compatible(dev, "u3-agp")) { - setup_u3_agp(hose, addr); - disp_name = "U3-AGP"; - primary = 0; - } else if (device_is_compatible(dev, "u3-ht")) { - setup_u3_ht(hose, addr); - disp_name = "U3-HT"; - primary = 1; - } else -#endif /* CONFIG_POWER4 */ - if (device_is_compatible(dev, "uni-north")) { - primary = setup_uninorth(hose, addr); - disp_name = "UniNorth"; - } else if (strcmp(dev->name, "pci") == 0) { - /* XXX assume this is a mpc106 (grackle) */ - setup_grackle(hose); - disp_name = "Grackle (MPC106)"; - } else if (strcmp(dev->name, "bandit") == 0) { - setup_bandit(hose, addr); - disp_name = "Bandit"; - } else if (strcmp(dev->name, "chaos") == 0) { - setup_chaos(hose, addr); - disp_name = "Chaos"; - primary = 0; - } - printk(KERN_INFO "Found %s PCI host bridge at 0x%08x. Firmware bus number: %d->%d\n", - disp_name, addr->address, hose->first_busno, hose->last_busno); - DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", - hose, hose->cfg_addr, hose->cfg_data); - - /* Interpret the "ranges" property */ - /* This also maps the I/O region and sets isa_io/mem_base */ - pci_process_bridge_OF_ranges(hose, dev, primary); - - /* Fixup "bus-range" OF property */ - fixup_bus_range(dev); - - return 0; -} - -static void __init -pcibios_fixup_OF_interrupts(void) -{ - struct pci_dev* dev = NULL; - - /* - * Open Firmware often doesn't initialize the - * PCI_INTERRUPT_LINE config register properly, so we - * should find the device node and apply the interrupt - * obtained from the OF device-tree - */ - for_each_pci_dev(dev) { - struct device_node *node; - node = pci_device_to_OF_node(dev); - /* this is the node, see if it has interrupts */ - if (node && node->n_intrs > 0) - dev->irq = node->intrs[0].line; - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); - } -} - -void __init -pmac_pcibios_fixup(void) -{ - /* Fixup interrupts according to OF tree */ - pcibios_fixup_OF_interrupts(); -} - -int -pmac_pci_enable_device_hook(struct pci_dev *dev, int initial) -{ - struct device_node* node; - int updatecfg = 0; - int uninorth_child; - - node = pci_device_to_OF_node(dev); - - /* We don't want to enable USB controllers absent from the OF tree - * (iBook second controller) - */ - if (dev->vendor == PCI_VENDOR_ID_APPLE - && (dev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x10)) - && !node) { - printk(KERN_INFO "Apple USB OHCI %s disabled by firmware\n", - pci_name(dev)); - return -EINVAL; - } - - if (!node) - return 0; - - uninorth_child = node->parent && - device_is_compatible(node->parent, "uni-north"); - - /* Firewire & GMAC were disabled after PCI probe, the driver is - * claiming them, we must re-enable them now. - */ - if (uninorth_child && !strcmp(node->name, "firewire") && - (device_is_compatible(node, "pci106b,18") || - device_is_compatible(node, "pci106b,30") || - device_is_compatible(node, "pci11c1,5811"))) { - pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, node, 0, 1); - pmac_call_feature(PMAC_FTR_1394_ENABLE, node, 0, 1); - updatecfg = 1; - } - if (uninorth_child && !strcmp(node->name, "ethernet") && - device_is_compatible(node, "gmac")) { - pmac_call_feature(PMAC_FTR_GMAC_ENABLE, node, 0, 1); - updatecfg = 1; - } - - if (updatecfg) { - u16 cmd; - - /* - * Make sure PCI is correctly configured - * - * We use old pci_bios versions of the function since, by - * default, gmac is not powered up, and so will be absent - * from the kernel initial PCI lookup. - * - * Should be replaced by 2.4 new PCI mechanisms and really - * register the device. - */ - pci_read_config_word(dev, PCI_COMMAND, &cmd); - cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE; - pci_write_config_word(dev, PCI_COMMAND, cmd); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 16); - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, pci_cache_line_size); - } - - return 0; -} - -/* We power down some devices after they have been probed. They'll - * be powered back on later on - */ -void __init -pmac_pcibios_after_init(void) -{ - struct device_node* nd; - -#ifdef CONFIG_BLK_DEV_IDE - struct pci_dev *dev = NULL; - - /* OF fails to initialize IDE controllers on macs - * (and maybe other machines) - * - * Ideally, this should be moved to the IDE layer, but we need - * to check specifically with Andre Hedrick how to do it cleanly - * since the common IDE code seem to care about the fact that the - * BIOS may have disabled a controller. - * - * -- BenH - */ - for_each_pci_dev(dev) { - if ((dev->class >> 16) == PCI_BASE_CLASS_STORAGE) - pci_enable_device(dev); - } -#endif /* CONFIG_BLK_DEV_IDE */ - - nd = find_devices("firewire"); - while (nd) { - if (nd->parent && (device_is_compatible(nd, "pci106b,18") || - device_is_compatible(nd, "pci106b,30") || - device_is_compatible(nd, "pci11c1,5811")) - && device_is_compatible(nd->parent, "uni-north")) { - pmac_call_feature(PMAC_FTR_1394_ENABLE, nd, 0, 0); - pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, nd, 0, 0); - } - nd = nd->next; - } - nd = find_devices("ethernet"); - while (nd) { - if (nd->parent && device_is_compatible(nd, "gmac") - && device_is_compatible(nd->parent, "uni-north")) - pmac_call_feature(PMAC_FTR_GMAC_ENABLE, nd, 0, 0); - nd = nd->next; - } -} - -void pmac_pci_fixup_cardbus(struct pci_dev* dev) -{ - if (_machine != _MACH_Pmac) - return; - /* - * Fix the interrupt routing on the various cardbus bridges - * used on powerbooks - */ - if (dev->vendor != PCI_VENDOR_ID_TI) - return; - if (dev->device == PCI_DEVICE_ID_TI_1130 || - dev->device == PCI_DEVICE_ID_TI_1131) { - u8 val; - /* Enable PCI interrupt */ - if (pci_read_config_byte(dev, 0x91, &val) == 0) - pci_write_config_byte(dev, 0x91, val | 0x30); - /* Disable ISA interrupt mode */ - if (pci_read_config_byte(dev, 0x92, &val) == 0) - pci_write_config_byte(dev, 0x92, val & ~0x06); - } - if (dev->device == PCI_DEVICE_ID_TI_1210 || - dev->device == PCI_DEVICE_ID_TI_1211 || - dev->device == PCI_DEVICE_ID_TI_1410 || - dev->device == PCI_DEVICE_ID_TI_1510) { - u8 val; - /* 0x8c == TI122X_IRQMUX, 2 says to route the INTA - signal out the MFUNC0 pin */ - if (pci_read_config_byte(dev, 0x8c, &val) == 0) - pci_write_config_byte(dev, 0x8c, (val & ~0x0f) | 2); - /* Disable ISA interrupt mode */ - if (pci_read_config_byte(dev, 0x92, &val) == 0) - pci_write_config_byte(dev, 0x92, val & ~0x06); - } -} - -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TI, PCI_ANY_ID, pmac_pci_fixup_cardbus); - -void pmac_pci_fixup_pciata(struct pci_dev* dev) -{ - u8 progif = 0; - - /* - * On PowerMacs, we try to switch any PCI ATA controller to - * fully native mode - */ - if (_machine != _MACH_Pmac) - return; - /* Some controllers don't have the class IDE */ - if (dev->vendor == PCI_VENDOR_ID_PROMISE) - switch(dev->device) { - case PCI_DEVICE_ID_PROMISE_20246: - case PCI_DEVICE_ID_PROMISE_20262: - case PCI_DEVICE_ID_PROMISE_20263: - case PCI_DEVICE_ID_PROMISE_20265: - case PCI_DEVICE_ID_PROMISE_20267: - case PCI_DEVICE_ID_PROMISE_20268: - case PCI_DEVICE_ID_PROMISE_20269: - case PCI_DEVICE_ID_PROMISE_20270: - case PCI_DEVICE_ID_PROMISE_20271: - case PCI_DEVICE_ID_PROMISE_20275: - case PCI_DEVICE_ID_PROMISE_20276: - case PCI_DEVICE_ID_PROMISE_20277: - goto good; - } - /* Others, check PCI class */ - if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) - return; - good: - pci_read_config_byte(dev, PCI_CLASS_PROG, &progif); - if ((progif & 5) != 5) { - printk(KERN_INFO "Forcing PCI IDE into native mode: %s\n", pci_name(dev)); - (void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5); - if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || - (progif & 5) != 5) - printk(KERN_ERR "Rewrite of PROGIF failed !\n"); - } -} -DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pmac_pci_fixup_pciata); - - -/* - * Disable second function on K2-SATA, it's broken - * and disable IO BARs on first one - */ -void pmac_pci_fixup_k2_sata(struct pci_dev* dev) -{ - int i; - u16 cmd; - - if (PCI_FUNC(dev->devfn) > 0) { - pci_read_config_word(dev, PCI_COMMAND, &cmd); - cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY); - pci_write_config_word(dev, PCI_COMMAND, cmd); - for (i = 0; i < 6; i++) { - dev->resource[i].start = dev->resource[i].end = 0; - dev->resource[i].flags = 0; - pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, 0); - } - } else { - pci_read_config_word(dev, PCI_COMMAND, &cmd); - cmd &= ~PCI_COMMAND_IO; - pci_write_config_word(dev, PCI_COMMAND, cmd); - for (i = 0; i < 5; i++) { - dev->resource[i].start = dev->resource[i].end = 0; - dev->resource[i].flags = 0; - pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, 0); - } - } -} -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, 0x0240, pmac_pci_fixup_k2_sata); diff --git a/arch/ppc/platforms/pmac_pic.c b/arch/ppc/platforms/pmac_pic.c deleted file mode 100644 index 4742bf60935..00000000000 --- a/arch/ppc/platforms/pmac_pic.c +++ /dev/null @@ -1,693 +0,0 @@ -/* - * Support for the interrupt controllers found on Power Macintosh, - * currently Apple's "Grand Central" interrupt controller in all - * it's incarnations. OpenPIC support used on newer machines is - * in a separate file - * - * Copyright (C) 1997 Paul Mackerras (paulus@cs.anu.edu.au) - * - * Maintained by Benjamin Herrenschmidt (benh@kernel.crashing.org) - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pmac_pic.h" - -/* - * XXX this should be in xmon.h, but putting it there means xmon.h - * has to include (to get irqreturn_t), which - * causes all sorts of problems. -- paulus - */ -extern irqreturn_t xmon_irq(int, void *, struct pt_regs *); - -struct pmac_irq_hw { - unsigned int event; - unsigned int enable; - unsigned int ack; - unsigned int level; -}; - -/* Default addresses */ -static volatile struct pmac_irq_hw *pmac_irq_hw[4] = { - (struct pmac_irq_hw *) 0xf3000020, - (struct pmac_irq_hw *) 0xf3000010, - (struct pmac_irq_hw *) 0xf4000020, - (struct pmac_irq_hw *) 0xf4000010, -}; - -#define GC_LEVEL_MASK 0x3ff00000 -#define OHARE_LEVEL_MASK 0x1ff00000 -#define HEATHROW_LEVEL_MASK 0x1ff00000 - -static int max_irqs; -static int max_real_irqs; -static u32 level_mask[4]; - -static DEFINE_SPINLOCK(pmac_pic_lock); - - -#define GATWICK_IRQ_POOL_SIZE 10 -static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE]; - -#define NR_MASK_WORDS ((NR_IRQS + 31) / 32) -static unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; - -/* - * Mark an irq as "lost". This is only used on the pmac - * since it can lose interrupts (see pmac_set_irq_mask). - * -- Cort - */ -void -__set_lost(unsigned long irq_nr, int nokick) -{ - if (!test_and_set_bit(irq_nr, ppc_lost_interrupts)) { - atomic_inc(&ppc_n_lost_interrupts); - if (!nokick) - set_dec(1); - } -} - -static void -pmac_mask_and_ack_irq(unsigned int irq_nr) -{ - unsigned long bit = 1UL << (irq_nr & 0x1f); - int i = irq_nr >> 5; - unsigned long flags; - - if ((unsigned)irq_nr >= max_irqs) - return; - - clear_bit(irq_nr, ppc_cached_irq_mask); - if (test_and_clear_bit(irq_nr, ppc_lost_interrupts)) - atomic_dec(&ppc_n_lost_interrupts); - spin_lock_irqsave(&pmac_pic_lock, flags); - out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]); - out_le32(&pmac_irq_hw[i]->ack, bit); - do { - /* make sure ack gets to controller before we enable - interrupts */ - mb(); - } while((in_le32(&pmac_irq_hw[i]->enable) & bit) - != (ppc_cached_irq_mask[i] & bit)); - spin_unlock_irqrestore(&pmac_pic_lock, flags); -} - -static void pmac_set_irq_mask(unsigned int irq_nr, int nokicklost) -{ - unsigned long bit = 1UL << (irq_nr & 0x1f); - int i = irq_nr >> 5; - unsigned long flags; - - if ((unsigned)irq_nr >= max_irqs) - return; - - spin_lock_irqsave(&pmac_pic_lock, flags); - /* enable unmasked interrupts */ - out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]); - - do { - /* make sure mask gets to controller before we - return to user */ - mb(); - } while((in_le32(&pmac_irq_hw[i]->enable) & bit) - != (ppc_cached_irq_mask[i] & bit)); - - /* - * Unfortunately, setting the bit in the enable register - * when the device interrupt is already on *doesn't* set - * the bit in the flag register or request another interrupt. - */ - if (bit & ppc_cached_irq_mask[i] & in_le32(&pmac_irq_hw[i]->level)) - __set_lost((ulong)irq_nr, nokicklost); - spin_unlock_irqrestore(&pmac_pic_lock, flags); -} - -/* When an irq gets requested for the first client, if it's an - * edge interrupt, we clear any previous one on the controller - */ -static unsigned int pmac_startup_irq(unsigned int irq_nr) -{ - unsigned long bit = 1UL << (irq_nr & 0x1f); - int i = irq_nr >> 5; - - if ((irq_desc[irq_nr].status & IRQ_LEVEL) == 0) - out_le32(&pmac_irq_hw[i]->ack, bit); - set_bit(irq_nr, ppc_cached_irq_mask); - pmac_set_irq_mask(irq_nr, 0); - - return 0; -} - -static void pmac_mask_irq(unsigned int irq_nr) -{ - clear_bit(irq_nr, ppc_cached_irq_mask); - pmac_set_irq_mask(irq_nr, 0); - mb(); -} - -static void pmac_unmask_irq(unsigned int irq_nr) -{ - set_bit(irq_nr, ppc_cached_irq_mask); - pmac_set_irq_mask(irq_nr, 0); -} - -static void pmac_end_irq(unsigned int irq_nr) -{ - if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS)) - && irq_desc[irq_nr].action) { - set_bit(irq_nr, ppc_cached_irq_mask); - pmac_set_irq_mask(irq_nr, 1); - } -} - - -struct hw_interrupt_type pmac_pic = { - .typename = " PMAC-PIC ", - .startup = pmac_startup_irq, - .enable = pmac_unmask_irq, - .disable = pmac_mask_irq, - .ack = pmac_mask_and_ack_irq, - .end = pmac_end_irq, -}; - -struct hw_interrupt_type gatwick_pic = { - .typename = " GATWICK ", - .startup = pmac_startup_irq, - .enable = pmac_unmask_irq, - .disable = pmac_mask_irq, - .ack = pmac_mask_and_ack_irq, - .end = pmac_end_irq, -}; - -static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs) -{ - int irq, bits; - - for (irq = max_irqs; (irq -= 32) >= max_real_irqs; ) { - int i = irq >> 5; - bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i]; - /* We must read level interrupts from the level register */ - bits |= (in_le32(&pmac_irq_hw[i]->level) & level_mask[i]); - bits &= ppc_cached_irq_mask[i]; - if (bits == 0) - continue; - irq += __ilog2(bits); - __do_IRQ(irq, regs); - return IRQ_HANDLED; - } - printk("gatwick irq not from gatwick pic\n"); - return IRQ_NONE; -} - -int -pmac_get_irq(struct pt_regs *regs) -{ - int irq; - unsigned long bits = 0; - -#ifdef CONFIG_SMP - void psurge_smp_message_recv(struct pt_regs *); - - /* IPI's are a hack on the powersurge -- Cort */ - if ( smp_processor_id() != 0 ) { - psurge_smp_message_recv(regs); - return -2; /* ignore, already handled */ - } -#endif /* CONFIG_SMP */ - for (irq = max_real_irqs; (irq -= 32) >= 0; ) { - int i = irq >> 5; - bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i]; - /* We must read level interrupts from the level register */ - bits |= (in_le32(&pmac_irq_hw[i]->level) & level_mask[i]); - bits &= ppc_cached_irq_mask[i]; - if (bits == 0) - continue; - irq += __ilog2(bits); - break; - } - - return irq; -} - -/* This routine will fix some missing interrupt values in the device tree - * on the gatwick mac-io controller used by some PowerBooks - */ -static void __init -pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base) -{ - struct device_node *node; - int count; - - memset(gatwick_int_pool, 0, sizeof(gatwick_int_pool)); - node = gw->child; - count = 0; - while(node) - { - /* Fix SCC */ - if (strcasecmp(node->name, "escc") == 0) - if (node->child) { - if (node->child->n_intrs < 3) { - node->child->intrs = &gatwick_int_pool[count]; - count += 3; - } - node->child->n_intrs = 3; - node->child->intrs[0].line = 15+irq_base; - node->child->intrs[1].line = 4+irq_base; - node->child->intrs[2].line = 5+irq_base; - printk(KERN_INFO "irq: fixed SCC on second controller (%d,%d,%d)\n", - node->child->intrs[0].line, - node->child->intrs[1].line, - node->child->intrs[2].line); - } - /* Fix media-bay & left SWIM */ - if (strcasecmp(node->name, "media-bay") == 0) { - struct device_node* ya_node; - - if (node->n_intrs == 0) - node->intrs = &gatwick_int_pool[count++]; - node->n_intrs = 1; - node->intrs[0].line = 29+irq_base; - printk(KERN_INFO "irq: fixed media-bay on second controller (%d)\n", - node->intrs[0].line); - - ya_node = node->child; - while(ya_node) - { - if (strcasecmp(ya_node->name, "floppy") == 0) { - if (ya_node->n_intrs < 2) { - ya_node->intrs = &gatwick_int_pool[count]; - count += 2; - } - ya_node->n_intrs = 2; - ya_node->intrs[0].line = 19+irq_base; - ya_node->intrs[1].line = 1+irq_base; - printk(KERN_INFO "irq: fixed floppy on second controller (%d,%d)\n", - ya_node->intrs[0].line, ya_node->intrs[1].line); - } - if (strcasecmp(ya_node->name, "ata4") == 0) { - if (ya_node->n_intrs < 2) { - ya_node->intrs = &gatwick_int_pool[count]; - count += 2; - } - ya_node->n_intrs = 2; - ya_node->intrs[0].line = 14+irq_base; - ya_node->intrs[1].line = 3+irq_base; - printk(KERN_INFO "irq: fixed ide on second controller (%d,%d)\n", - ya_node->intrs[0].line, ya_node->intrs[1].line); - } - ya_node = ya_node->sibling; - } - } - node = node->sibling; - } - if (count > 10) { - printk("WARNING !! Gatwick interrupt pool overflow\n"); - printk(" GATWICK_IRQ_POOL_SIZE = %d\n", GATWICK_IRQ_POOL_SIZE); - printk(" requested = %d\n", count); - } -} - -/* - * The PowerBook 3400/2400/3500 can have a combo ethernet/modem - * card which includes an ohare chip that acts as a second interrupt - * controller. If we find this second ohare, set it up and fix the - * interrupt value in the device tree for the ethernet chip. - */ -static int __init enable_second_ohare(void) -{ - unsigned char bus, devfn; - unsigned short cmd; - unsigned long addr; - struct device_node *irqctrler = find_devices("pci106b,7"); - struct device_node *ether; - - if (irqctrler == NULL || irqctrler->n_addrs <= 0) - return -1; - addr = (unsigned long) ioremap(irqctrler->addrs[0].address, 0x40); - pmac_irq_hw[1] = (volatile struct pmac_irq_hw *)(addr + 0x20); - max_irqs = 64; - if (pci_device_from_OF_node(irqctrler, &bus, &devfn) == 0) { - struct pci_controller* hose = pci_find_hose_for_OF_device(irqctrler); - if (!hose) - printk(KERN_ERR "Can't find PCI hose for OHare2 !\n"); - else { - early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd); - cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; - cmd &= ~PCI_COMMAND_IO; - early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd); - } - } - - /* Fix interrupt for the modem/ethernet combo controller. The number - in the device tree (27) is bogus (correct for the ethernet-only - board but not the combo ethernet/modem board). - The real interrupt is 28 on the second controller -> 28+32 = 60. - */ - ether = find_devices("pci1011,14"); - if (ether && ether->n_intrs > 0) { - ether->intrs[0].line = 60; - printk(KERN_INFO "irq: Fixed ethernet IRQ to %d\n", - ether->intrs[0].line); - } - - /* Return the interrupt number of the cascade */ - return irqctrler->intrs[0].line; -} - -#ifdef CONFIG_POWER4 -static irqreturn_t k2u3_action(int cpl, void *dev_id, struct pt_regs *regs) -{ - int irq; - - irq = openpic2_get_irq(regs); - if (irq != -1) - __do_IRQ(irq, regs); - return IRQ_HANDLED; -} - -static struct irqaction k2u3_cascade_action = { - .handler = k2u3_action, - .flags = 0, - .mask = CPU_MASK_NONE, - .name = "U3->K2 Cascade", -}; -#endif /* CONFIG_POWER4 */ - -#ifdef CONFIG_XMON -static struct irqaction xmon_action = { - .handler = xmon_irq, - .flags = 0, - .mask = CPU_MASK_NONE, - .name = "NMI - XMON" -}; -#endif - -static struct irqaction gatwick_cascade_action = { - .handler = gatwick_action, - .flags = SA_INTERRUPT, - .mask = CPU_MASK_NONE, - .name = "cascade", -}; - -void __init pmac_pic_init(void) -{ - int i; - struct device_node *irqctrler = NULL; - struct device_node *irqctrler2 = NULL; - struct device_node *np; - unsigned long addr; - int irq_cascade = -1; - - /* We first try to detect Apple's new Core99 chipset, since mac-io - * is quite different on those machines and contains an IBM MPIC2. - */ - np = find_type_devices("open-pic"); - while(np) { - if (np->parent && !strcmp(np->parent->name, "u3")) - irqctrler2 = np; - else - irqctrler = np; - np = np->next; - } - if (irqctrler != NULL) - { - if (irqctrler->n_addrs > 0) - { - unsigned char senses[128]; - - printk(KERN_INFO "PowerMac using OpenPIC irq controller at 0x%08x\n", - irqctrler->addrs[0].address); - - prom_get_irq_senses(senses, 0, 128); - OpenPIC_InitSenses = senses; - OpenPIC_NumInitSenses = 128; - ppc_md.get_irq = openpic_get_irq; - pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler, 0, 0); - OpenPIC_Addr = ioremap(irqctrler->addrs[0].address, - irqctrler->addrs[0].size); - openpic_init(0); - -#ifdef CONFIG_POWER4 - if (irqctrler2 != NULL && irqctrler2->n_intrs > 0 && - irqctrler2->n_addrs > 0) { - printk(KERN_INFO "Slave OpenPIC at 0x%08x hooked on IRQ %d\n", - irqctrler2->addrs[0].address, - irqctrler2->intrs[0].line); - pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler2, 0, 0); - OpenPIC2_Addr = ioremap(irqctrler2->addrs[0].address, - irqctrler2->addrs[0].size); - prom_get_irq_senses(senses, PMAC_OPENPIC2_OFFSET, - PMAC_OPENPIC2_OFFSET+128); - OpenPIC_InitSenses = senses; - OpenPIC_NumInitSenses = 128; - openpic2_init(PMAC_OPENPIC2_OFFSET); - - if (setup_irq(irqctrler2->intrs[0].line, - &k2u3_cascade_action)) - printk("Unable to get OpenPIC IRQ for cascade\n"); - } -#endif /* CONFIG_POWER4 */ - -#ifdef CONFIG_XMON - { - struct device_node* pswitch; - int nmi_irq; - - pswitch = find_devices("programmer-switch"); - if (pswitch && pswitch->n_intrs) { - nmi_irq = pswitch->intrs[0].line; - openpic_init_nmi_irq(nmi_irq); - setup_irq(nmi_irq, &xmon_action); - } - } -#endif /* CONFIG_XMON */ - return; - } - irqctrler = NULL; - } - - /* Get the level/edge settings, assume if it's not - * a Grand Central nor an OHare, then it's an Heathrow - * (or Paddington). - */ - if (find_devices("gc")) - level_mask[0] = GC_LEVEL_MASK; - else if (find_devices("ohare")) { - level_mask[0] = OHARE_LEVEL_MASK; - /* We might have a second cascaded ohare */ - level_mask[1] = OHARE_LEVEL_MASK; - } else { - level_mask[0] = HEATHROW_LEVEL_MASK; - level_mask[1] = 0; - /* We might have a second cascaded heathrow */ - level_mask[2] = HEATHROW_LEVEL_MASK; - level_mask[3] = 0; - } - - /* - * G3 powermacs and 1999 G3 PowerBooks have 64 interrupts, - * 1998 G3 Series PowerBooks have 128, - * other powermacs have 32. - * The combo ethernet/modem card for the Powerstar powerbooks - * (2400/3400/3500, ohare based) has a second ohare chip - * effectively making a total of 64. - */ - max_irqs = max_real_irqs = 32; - irqctrler = find_devices("mac-io"); - if (irqctrler) - { - max_real_irqs = 64; - if (irqctrler->next) - max_irqs = 128; - else - max_irqs = 64; - } - for ( i = 0; i < max_real_irqs ; i++ ) - irq_desc[i].handler = &pmac_pic; - - /* get addresses of first controller */ - if (irqctrler) { - if (irqctrler->n_addrs > 0) { - addr = (unsigned long) - ioremap(irqctrler->addrs[0].address, 0x40); - for (i = 0; i < 2; ++i) - pmac_irq_hw[i] = (volatile struct pmac_irq_hw*) - (addr + (2 - i) * 0x10); - } - - /* get addresses of second controller */ - irqctrler = irqctrler->next; - if (irqctrler && irqctrler->n_addrs > 0) { - addr = (unsigned long) - ioremap(irqctrler->addrs[0].address, 0x40); - for (i = 2; i < 4; ++i) - pmac_irq_hw[i] = (volatile struct pmac_irq_hw*) - (addr + (4 - i) * 0x10); - irq_cascade = irqctrler->intrs[0].line; - if (device_is_compatible(irqctrler, "gatwick")) - pmac_fix_gatwick_interrupts(irqctrler, max_real_irqs); - } - } else { - /* older powermacs have a GC (grand central) or ohare at - f3000000, with interrupt control registers at f3000020. */ - addr = (unsigned long) ioremap(0xf3000000, 0x40); - pmac_irq_hw[0] = (volatile struct pmac_irq_hw *) (addr + 0x20); - } - - /* PowerBooks 3400 and 3500 can have a second controller in a second - ohare chip, on the combo ethernet/modem card */ - if (machine_is_compatible("AAPL,3400/2400") - || machine_is_compatible("AAPL,3500")) - irq_cascade = enable_second_ohare(); - - /* disable all interrupts in all controllers */ - for (i = 0; i * 32 < max_irqs; ++i) - out_le32(&pmac_irq_hw[i]->enable, 0); - /* mark level interrupts */ - for (i = 0; i < max_irqs; i++) - if (level_mask[i >> 5] & (1UL << (i & 0x1f))) - irq_desc[i].status = IRQ_LEVEL; - - /* get interrupt line of secondary interrupt controller */ - if (irq_cascade >= 0) { - printk(KERN_INFO "irq: secondary controller on irq %d\n", - (int)irq_cascade); - for ( i = max_real_irqs ; i < max_irqs ; i++ ) - irq_desc[i].handler = &gatwick_pic; - setup_irq(irq_cascade, &gatwick_cascade_action); - } - printk("System has %d possible interrupts\n", max_irqs); - if (max_irqs != max_real_irqs) - printk(KERN_DEBUG "%d interrupts on main controller\n", - max_real_irqs); - -#ifdef CONFIG_XMON - setup_irq(20, &xmon_action); -#endif /* CONFIG_XMON */ -} - -#ifdef CONFIG_PM -/* - * These procedures are used in implementing sleep on the powerbooks. - * sleep_save_intrs() saves the states of all interrupt enables - * and disables all interrupts except for the nominated one. - * sleep_restore_intrs() restores the states of all interrupt enables. - */ -unsigned long sleep_save_mask[2]; - -/* This used to be passed by the PMU driver but that link got - * broken with the new driver model. We use this tweak for now... - */ -static int pmacpic_find_viaint(void) -{ - int viaint = -1; - -#ifdef CONFIG_ADB_PMU - struct device_node *np; - - if (pmu_get_model() != PMU_OHARE_BASED) - goto not_found; - np = of_find_node_by_name(NULL, "via-pmu"); - if (np == NULL) - goto not_found; - viaint = np->intrs[0].line; -#endif /* CONFIG_ADB_PMU */ - -not_found: - return viaint; -} - -static int pmacpic_suspend(struct sys_device *sysdev, pm_message_t state) -{ - int viaint = pmacpic_find_viaint(); - - sleep_save_mask[0] = ppc_cached_irq_mask[0]; - sleep_save_mask[1] = ppc_cached_irq_mask[1]; - ppc_cached_irq_mask[0] = 0; - ppc_cached_irq_mask[1] = 0; - if (viaint > 0) - set_bit(viaint, ppc_cached_irq_mask); - out_le32(&pmac_irq_hw[0]->enable, ppc_cached_irq_mask[0]); - if (max_real_irqs > 32) - out_le32(&pmac_irq_hw[1]->enable, ppc_cached_irq_mask[1]); - (void)in_le32(&pmac_irq_hw[0]->event); - /* make sure mask gets to controller before we return to caller */ - mb(); - (void)in_le32(&pmac_irq_hw[0]->enable); - - return 0; -} - -static int pmacpic_resume(struct sys_device *sysdev) -{ - int i; - - out_le32(&pmac_irq_hw[0]->enable, 0); - if (max_real_irqs > 32) - out_le32(&pmac_irq_hw[1]->enable, 0); - mb(); - for (i = 0; i < max_real_irqs; ++i) - if (test_bit(i, sleep_save_mask)) - pmac_unmask_irq(i); - - return 0; -} - -#endif /* CONFIG_PM */ - -static struct sysdev_class pmacpic_sysclass = { - set_kset_name("pmac_pic"), -}; - -static struct sys_device device_pmacpic = { - .id = 0, - .cls = &pmacpic_sysclass, -}; - -static struct sysdev_driver driver_pmacpic = { -#ifdef CONFIG_PM - .suspend = &pmacpic_suspend, - .resume = &pmacpic_resume, -#endif /* CONFIG_PM */ -}; - -static int __init init_pmacpic_sysfs(void) -{ - if (max_irqs == 0) - return -ENODEV; - - printk(KERN_DEBUG "Registering pmac pic with sysfs...\n"); - sysdev_class_register(&pmacpic_sysclass); - sysdev_register(&device_pmacpic); - sysdev_driver_register(&pmacpic_sysclass, &driver_pmacpic); - return 0; -} - -subsys_initcall(init_pmacpic_sysfs); - diff --git a/arch/ppc/platforms/pmac_pic.h b/arch/ppc/platforms/pmac_pic.h deleted file mode 100644 index 664103dfeef..00000000000 --- a/arch/ppc/platforms/pmac_pic.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __PPC_PLATFORMS_PMAC_PIC_H -#define __PPC_PLATFORMS_PMAC_PIC_H - -#include - -extern struct hw_interrupt_type pmac_pic; - -void pmac_pic_init(void); -int pmac_get_irq(struct pt_regs *regs); - -#endif /* __PPC_PLATFORMS_PMAC_PIC_H */ diff --git a/arch/ppc/platforms/pmac_setup.c b/arch/ppc/platforms/pmac_setup.c deleted file mode 100644 index 55d2beffe56..00000000000 --- a/arch/ppc/platforms/pmac_setup.c +++ /dev/null @@ -1,745 +0,0 @@ -/* - * arch/ppc/platforms/setup.c - * - * PowerPC version - * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) - * - * Adapted for Power Macintosh by Paul Mackerras - * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) - * - * Derived from "arch/alpha/kernel/setup.c" - * Copyright (C) 1995 Linus Torvalds - * - * Maintained by Benjamin Herrenschmidt (benh@kernel.crashing.org) - * - * 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. - * - */ - -/* - * bootup setup stuff.. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pmac_pic.h" -#include "mem_pieces.h" - -#undef SHOW_GATWICK_IRQS - -extern long pmac_time_init(void); -extern unsigned long pmac_get_rtc_time(void); -extern int pmac_set_rtc_time(unsigned long nowtime); -extern void pmac_read_rtc_time(void); -extern void pmac_calibrate_decr(void); -extern void pmac_pcibios_fixup(void); -extern void pmac_find_bridges(void); -extern unsigned long pmac_ide_get_base(int index); -extern void pmac_ide_init_hwif_ports(hw_regs_t *hw, - unsigned long data_port, unsigned long ctrl_port, int *irq); - -extern void pmac_nvram_update(void); -extern unsigned char pmac_nvram_read_byte(int addr); -extern void pmac_nvram_write_byte(int addr, unsigned char val); -extern int pmac_pci_enable_device_hook(struct pci_dev *dev, int initial); -extern void pmac_pcibios_after_init(void); -extern int of_show_percpuinfo(struct seq_file *m, int i); - -struct device_node *memory_node; - -unsigned char drive_info; - -int ppc_override_l2cr = 0; -int ppc_override_l2cr_value; -int has_l2cache = 0; - -static int current_root_goodness = -1; - -extern int pmac_newworld; - -#define DEFAULT_ROOT_DEVICE Root_SDA1 /* sda1 - slightly silly choice */ - -extern void zs_kgdb_hook(int tty_num); -static void ohare_init(void); -#ifdef CONFIG_BOOTX_TEXT -static void pmac_progress(char *s, unsigned short hex); -#endif - -sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN; - -#ifdef CONFIG_SMP -extern struct smp_ops_t psurge_smp_ops; -extern struct smp_ops_t core99_smp_ops; -#endif /* CONFIG_SMP */ - -static int -pmac_show_cpuinfo(struct seq_file *m) -{ - struct device_node *np; - char *pp; - int plen; - int mbmodel = pmac_call_feature(PMAC_FTR_GET_MB_INFO, - NULL, PMAC_MB_INFO_MODEL, 0); - unsigned int mbflags = (unsigned int)pmac_call_feature(PMAC_FTR_GET_MB_INFO, - NULL, PMAC_MB_INFO_FLAGS, 0); - char* mbname; - - if (pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_NAME, (int)&mbname) != 0) - mbname = "Unknown"; - - /* find motherboard type */ - seq_printf(m, "machine\t\t: "); - np = find_devices("device-tree"); - if (np != NULL) { - pp = (char *) get_property(np, "model", NULL); - if (pp != NULL) - seq_printf(m, "%s\n", pp); - else - seq_printf(m, "PowerMac\n"); - pp = (char *) get_property(np, "compatible", &plen); - if (pp != NULL) { - seq_printf(m, "motherboard\t:"); - while (plen > 0) { - int l = strlen(pp) + 1; - seq_printf(m, " %s", pp); - plen -= l; - pp += l; - } - seq_printf(m, "\n"); - } - } else - seq_printf(m, "PowerMac\n"); - - /* print parsed model */ - seq_printf(m, "detected as\t: %d (%s)\n", mbmodel, mbname); - seq_printf(m, "pmac flags\t: %08x\n", mbflags); - - /* find l2 cache info */ - np = find_devices("l2-cache"); - if (np == 0) - np = find_type_devices("cache"); - if (np != 0) { - unsigned int *ic = (unsigned int *) - get_property(np, "i-cache-size", NULL); - unsigned int *dc = (unsigned int *) - get_property(np, "d-cache-size", NULL); - seq_printf(m, "L2 cache\t:"); - has_l2cache = 1; - if (get_property(np, "cache-unified", NULL) != 0 && dc) { - seq_printf(m, " %dK unified", *dc / 1024); - } else { - if (ic) - seq_printf(m, " %dK instruction", *ic / 1024); - if (dc) - seq_printf(m, "%s %dK data", - (ic? " +": ""), *dc / 1024); - } - pp = get_property(np, "ram-type", NULL); - if (pp) - seq_printf(m, " %s", pp); - seq_printf(m, "\n"); - } - - /* find ram info */ - np = find_devices("memory"); - if (np != 0) { - int n; - struct reg_property *reg = (struct reg_property *) - get_property(np, "reg", &n); - - if (reg != 0) { - unsigned long total = 0; - - for (n /= sizeof(struct reg_property); n > 0; --n) - total += (reg++)->size; - seq_printf(m, "memory\t\t: %luMB\n", total >> 20); - } - } - - /* Checks "l2cr-value" property in the registry */ - np = find_devices("cpus"); - if (np == 0) - np = find_type_devices("cpu"); - if (np != 0) { - unsigned int *l2cr = (unsigned int *) - get_property(np, "l2cr-value", NULL); - if (l2cr != 0) { - seq_printf(m, "l2cr override\t: 0x%x\n", *l2cr); - } - } - - /* Indicate newworld/oldworld */ - seq_printf(m, "pmac-generation\t: %s\n", - pmac_newworld ? "NewWorld" : "OldWorld"); - - - return 0; -} - -static int -pmac_show_percpuinfo(struct seq_file *m, int i) -{ -#ifdef CONFIG_CPU_FREQ_PMAC - extern unsigned int pmac_get_one_cpufreq(int i); - unsigned int freq = pmac_get_one_cpufreq(i); - if (freq != 0) { - seq_printf(m, "clock\t\t: %dMHz\n", freq/1000); - return 0; - } -#endif /* CONFIG_CPU_FREQ_PMAC */ - return of_show_percpuinfo(m, i); -} - -static volatile u32 *sysctrl_regs; - -void __init -pmac_setup_arch(void) -{ - struct device_node *cpu; - int *fp; - unsigned long pvr; - - pvr = PVR_VER(mfspr(SPRN_PVR)); - - /* Set loops_per_jiffy to a half-way reasonable value, - for use until calibrate_delay gets called. */ - cpu = find_type_devices("cpu"); - if (cpu != 0) { - fp = (int *) get_property(cpu, "clock-frequency", NULL); - if (fp != 0) { - if (pvr == 4 || pvr >= 8) - /* 604, G3, G4 etc. */ - loops_per_jiffy = *fp / HZ; - else - /* 601, 603, etc. */ - loops_per_jiffy = *fp / (2*HZ); - } else - loops_per_jiffy = 50000000 / HZ; - } - - /* this area has the CPU identification register - and some registers used by smp boards */ - sysctrl_regs = (volatile u32 *) ioremap(0xf8000000, 0x1000); - ohare_init(); - - /* Lookup PCI hosts */ - pmac_find_bridges(); - - /* Checks "l2cr-value" property in the registry */ - if (cpu_has_feature(CPU_FTR_L2CR)) { - struct device_node *np = find_devices("cpus"); - if (np == 0) - np = find_type_devices("cpu"); - if (np != 0) { - unsigned int *l2cr = (unsigned int *) - get_property(np, "l2cr-value", NULL); - if (l2cr != 0) { - ppc_override_l2cr = 1; - ppc_override_l2cr_value = *l2cr; - _set_L2CR(0); - _set_L2CR(ppc_override_l2cr_value); - } - } - } - - if (ppc_override_l2cr) - printk(KERN_INFO "L2CR overriden (0x%x), backside cache is %s\n", - ppc_override_l2cr_value, (ppc_override_l2cr_value & 0x80000000) - ? "enabled" : "disabled"); - -#ifdef CONFIG_KGDB - zs_kgdb_hook(0); -#endif - -#ifdef CONFIG_ADB_CUDA - find_via_cuda(); -#else - if (find_devices("via-cuda")) { - printk("WARNING ! Your machine is Cuda based but your kernel\n"); - printk(" wasn't compiled with CONFIG_ADB_CUDA option !\n"); - } -#endif -#ifdef CONFIG_ADB_PMU - find_via_pmu(); -#else - if (find_devices("via-pmu")) { - printk("WARNING ! Your machine is PMU based but your kernel\n"); - printk(" wasn't compiled with CONFIG_ADB_PMU option !\n"); - } -#endif -#ifdef CONFIG_NVRAM - pmac_nvram_init(); -#endif -#ifdef CONFIG_BLK_DEV_INITRD - if (initrd_start) - ROOT_DEV = Root_RAM0; - else -#endif - ROOT_DEV = DEFAULT_ROOT_DEVICE; - -#ifdef CONFIG_SMP - /* Check for Core99 */ - if (find_devices("uni-n") || find_devices("u3")) - smp_ops = &core99_smp_ops; - else - smp_ops = &psurge_smp_ops; -#endif /* CONFIG_SMP */ - - pci_create_OF_bus_map(); -} - -static void __init ohare_init(void) -{ - /* - * Turn on the L2 cache. - * We assume that we have a PSX memory controller iff - * we have an ohare I/O controller. - */ - if (find_devices("ohare") != NULL) { - if (((sysctrl_regs[2] >> 24) & 0xf) >= 3) { - if (sysctrl_regs[4] & 0x10) - sysctrl_regs[4] |= 0x04000020; - else - sysctrl_regs[4] |= 0x04000000; - if(has_l2cache) - printk(KERN_INFO "Level 2 cache enabled\n"); - } - } -} - -extern char *bootpath; -extern char *bootdevice; -void *boot_host; -int boot_target; -int boot_part; -extern dev_t boot_dev; - -#ifdef CONFIG_SCSI -void __init -note_scsi_host(struct device_node *node, void *host) -{ - int l; - char *p; - - l = strlen(node->full_name); - if (bootpath != NULL && bootdevice != NULL - && strncmp(node->full_name, bootdevice, l) == 0 - && (bootdevice[l] == '/' || bootdevice[l] == 0)) { - boot_host = host; - /* - * There's a bug in OF 1.0.5. (Why am I not surprised.) - * If you pass a path like scsi/sd@1:0 to canon, it returns - * something like /bandit@F2000000/gc@10/53c94@10000/sd@0,0 - * That is, the scsi target number doesn't get preserved. - * So we pick the target number out of bootpath and use that. - */ - p = strstr(bootpath, "/sd@"); - if (p != NULL) { - p += 4; - boot_target = simple_strtoul(p, NULL, 10); - p = strchr(p, ':'); - if (p != NULL) - boot_part = simple_strtoul(p + 1, NULL, 10); - } - } -} -#endif - -#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) -static dev_t __init -find_ide_boot(void) -{ - char *p; - int n; - dev_t __init pmac_find_ide_boot(char *bootdevice, int n); - - if (bootdevice == NULL) - return 0; - p = strrchr(bootdevice, '/'); - if (p == NULL) - return 0; - n = p - bootdevice; - - return pmac_find_ide_boot(bootdevice, n); -} -#endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */ - -static void __init -find_boot_device(void) -{ -#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) - boot_dev = find_ide_boot(); -#endif -} - -static int initializing = 1; -/* TODO: Merge the suspend-to-ram with the common code !!! - * currently, this is a stub implementation for suspend-to-disk - * only - */ - -#ifdef CONFIG_SOFTWARE_SUSPEND - -static int pmac_pm_prepare(suspend_state_t state) -{ - printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state); - - return 0; -} - -static int pmac_pm_enter(suspend_state_t state) -{ - printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state); - - /* Giveup the lazy FPU & vec so we don't have to back them - * up from the low level code - */ - enable_kernel_fp(); - -#ifdef CONFIG_ALTIVEC - if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC) - enable_kernel_altivec(); -#endif /* CONFIG_ALTIVEC */ - - return 0; -} - -static int pmac_pm_finish(suspend_state_t state) -{ - printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state); - - /* Restore userland MMU context */ - set_context(current->active_mm->context, current->active_mm->pgd); - - return 0; -} - -static struct pm_ops pmac_pm_ops = { - .pm_disk_mode = PM_DISK_SHUTDOWN, - .prepare = pmac_pm_prepare, - .enter = pmac_pm_enter, - .finish = pmac_pm_finish, -}; - -#endif /* CONFIG_SOFTWARE_SUSPEND */ - -static int pmac_late_init(void) -{ - initializing = 0; -#ifdef CONFIG_SOFTWARE_SUSPEND - pm_set_ops(&pmac_pm_ops); -#endif /* CONFIG_SOFTWARE_SUSPEND */ - return 0; -} - -late_initcall(pmac_late_init); - -/* can't be __init - can be called whenever a disk is first accessed */ -void -note_bootable_part(dev_t dev, int part, int goodness) -{ - static int found_boot = 0; - char *p; - - if (!initializing) - return; - if ((goodness <= current_root_goodness) && - ROOT_DEV != DEFAULT_ROOT_DEVICE) - return; - p = strstr(saved_command_line, "root="); - if (p != NULL && (p == saved_command_line || p[-1] == ' ')) - return; - - if (!found_boot) { - find_boot_device(); - found_boot = 1; - } - if (!boot_dev || dev == boot_dev) { - ROOT_DEV = dev + part; - boot_dev = 0; - current_root_goodness = goodness; - } -} - -static void -pmac_restart(char *cmd) -{ -#ifdef CONFIG_ADB_CUDA - struct adb_request req; -#endif /* CONFIG_ADB_CUDA */ - - switch (sys_ctrler) { -#ifdef CONFIG_ADB_CUDA - case SYS_CTRLER_CUDA: - cuda_request(&req, NULL, 2, CUDA_PACKET, - CUDA_RESET_SYSTEM); - for (;;) - cuda_poll(); - break; -#endif /* CONFIG_ADB_CUDA */ -#ifdef CONFIG_ADB_PMU - case SYS_CTRLER_PMU: - pmu_restart(); - break; -#endif /* CONFIG_ADB_PMU */ - default: ; - } -} - -static void -pmac_power_off(void) -{ -#ifdef CONFIG_ADB_CUDA - struct adb_request req; -#endif /* CONFIG_ADB_CUDA */ - - switch (sys_ctrler) { -#ifdef CONFIG_ADB_CUDA - case SYS_CTRLER_CUDA: - cuda_request(&req, NULL, 2, CUDA_PACKET, - CUDA_POWERDOWN); - for (;;) - cuda_poll(); - break; -#endif /* CONFIG_ADB_CUDA */ -#ifdef CONFIG_ADB_PMU - case SYS_CTRLER_PMU: - pmu_shutdown(); - break; -#endif /* CONFIG_ADB_PMU */ - default: ; - } -} - -static void -pmac_halt(void) -{ - pmac_power_off(); -} - -/* - * Read in a property describing some pieces of memory. - */ - -static int __init -get_mem_prop(char *name, struct mem_pieces *mp) -{ - struct reg_property *rp; - int i, s; - unsigned int *ip; - int nac = prom_n_addr_cells(memory_node); - int nsc = prom_n_size_cells(memory_node); - - ip = (unsigned int *) get_property(memory_node, name, &s); - if (ip == NULL) { - printk(KERN_ERR "error: couldn't get %s property on /memory\n", - name); - return 0; - } - s /= (nsc + nac) * 4; - rp = mp->regions; - for (i = 0; i < s; ++i, ip += nac+nsc) { - if (nac >= 2 && ip[nac-2] != 0) - continue; - rp->address = ip[nac-1]; - if (nsc >= 2 && ip[nac+nsc-2] != 0) - rp->size = ~0U; - else - rp->size = ip[nac+nsc-1]; - ++rp; - } - mp->n_regions = rp - mp->regions; - - /* Make sure the pieces are sorted. */ - mem_pieces_sort(mp); - mem_pieces_coalesce(mp); - return 1; -} - -/* - * On systems with Open Firmware, collect information about - * physical RAM and which pieces are already in use. - * At this point, we have (at least) the first 8MB mapped with a BAT. - * Our text, data, bss use something over 1MB, starting at 0. - * Open Firmware may be using 1MB at the 4MB point. - */ -unsigned long __init -pmac_find_end_of_memory(void) -{ - unsigned long a, total; - struct mem_pieces phys_mem; - - /* - * Find out where physical memory is, and check that it - * starts at 0 and is contiguous. It seems that RAM is - * always physically contiguous on Power Macintoshes. - * - * Supporting discontiguous physical memory isn't hard, - * it just makes the virtual <-> physical mapping functions - * more complicated (or else you end up wasting space - * in mem_map). - */ - memory_node = find_devices("memory"); - if (memory_node == NULL || !get_mem_prop("reg", &phys_mem) - || phys_mem.n_regions == 0) - panic("No RAM??"); - a = phys_mem.regions[0].address; - if (a != 0) - panic("RAM doesn't start at physical address 0"); - total = phys_mem.regions[0].size; - - if (phys_mem.n_regions > 1) { - printk("RAM starting at 0x%x is not contiguous\n", - phys_mem.regions[1].address); - printk("Using RAM from 0 to 0x%lx\n", total-1); - } - - return total; -} - -void __init -pmac_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) -{ - /* isa_io_base gets set in pmac_find_bridges */ - isa_mem_base = PMAC_ISA_MEM_BASE; - pci_dram_offset = PMAC_PCI_DRAM_OFFSET; - ISA_DMA_THRESHOLD = ~0L; - DMA_MODE_READ = 1; - DMA_MODE_WRITE = 2; - - ppc_md.setup_arch = pmac_setup_arch; - ppc_md.show_cpuinfo = pmac_show_cpuinfo; - ppc_md.show_percpuinfo = pmac_show_percpuinfo; - ppc_md.init_IRQ = pmac_pic_init; - ppc_md.get_irq = pmac_get_irq; /* Changed later on ... */ - - ppc_md.pcibios_fixup = pmac_pcibios_fixup; - ppc_md.pcibios_enable_device_hook = pmac_pci_enable_device_hook; - ppc_md.pcibios_after_init = pmac_pcibios_after_init; - ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot; - - ppc_md.restart = pmac_restart; - ppc_md.power_off = pmac_power_off; - ppc_md.halt = pmac_halt; - - ppc_md.time_init = pmac_time_init; - ppc_md.set_rtc_time = pmac_set_rtc_time; - ppc_md.get_rtc_time = pmac_get_rtc_time; - ppc_md.calibrate_decr = pmac_calibrate_decr; - - ppc_md.find_end_of_memory = pmac_find_end_of_memory; - - ppc_md.feature_call = pmac_do_feature_call; - -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) -#ifdef CONFIG_BLK_DEV_IDE_PMAC - ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports; - ppc_ide_md.default_io_base = pmac_ide_get_base; -#endif /* CONFIG_BLK_DEV_IDE_PMAC */ -#endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */ - -#ifdef CONFIG_BOOTX_TEXT - ppc_md.progress = pmac_progress; -#endif /* CONFIG_BOOTX_TEXT */ - - if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0); - -} - -#ifdef CONFIG_BOOTX_TEXT -static void __init -pmac_progress(char *s, unsigned short hex) -{ - if (boot_text_mapped) { - btext_drawstring(s); - btext_drawchar('\n'); - } -} -#endif /* CONFIG_BOOTX_TEXT */ - -static int __init -pmac_declare_of_platform_devices(void) -{ - struct device_node *np; - - np = find_devices("uni-n"); - if (np) { - for (np = np->child; np != NULL; np = np->sibling) - if (strncmp(np->name, "i2c", 3) == 0) { - of_platform_device_create(np, "uni-n-i2c", - NULL); - break; - } - } - np = find_devices("u3"); - if (np) { - for (np = np->child; np != NULL; np = np->sibling) - if (strncmp(np->name, "i2c", 3) == 0) { - of_platform_device_create(np, "u3-i2c", - NULL); - break; - } - } - - np = find_devices("valkyrie"); - if (np) - of_platform_device_create(np, "valkyrie", NULL); - np = find_devices("platinum"); - if (np) - of_platform_device_create(np, "platinum", NULL); - - return 0; -} - -device_initcall(pmac_declare_of_platform_devices); diff --git a/arch/ppc/platforms/pmac_sleep.S b/arch/ppc/platforms/pmac_sleep.S deleted file mode 100644 index 22b113d19b2..00000000000 --- a/arch/ppc/platforms/pmac_sleep.S +++ /dev/null @@ -1,396 +0,0 @@ -/* - * This file contains sleep low-level functions for PowerBook G3. - * Copyright (C) 1999 Benjamin Herrenschmidt (benh@kernel.crashing.org) - * and Paul Mackerras (paulus@samba.org). - * - * 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 -#include -#include -#include -#include -#include -#include -#include - -#define MAGIC 0x4c617273 /* 'Lars' */ - -/* - * Structure for storing CPU registers on the stack. - */ -#define SL_SP 0 -#define SL_PC 4 -#define SL_MSR 8 -#define SL_SDR1 0xc -#define SL_SPRG0 0x10 /* 4 sprg's */ -#define SL_DBAT0 0x20 -#define SL_IBAT0 0x28 -#define SL_DBAT1 0x30 -#define SL_IBAT1 0x38 -#define SL_DBAT2 0x40 -#define SL_IBAT2 0x48 -#define SL_DBAT3 0x50 -#define SL_IBAT3 0x58 -#define SL_TB 0x60 -#define SL_R2 0x68 -#define SL_CR 0x6c -#define SL_R12 0x70 /* r12 to r31 */ -#define SL_SIZE (SL_R12 + 80) - - .section .text - .align 5 - -#if defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ_PMAC) - -/* This gets called by via-pmu.c late during the sleep process. - * The PMU was already send the sleep command and will shut us down - * soon. We need to save all that is needed and setup the wakeup - * vector that will be called by the ROM on wakeup - */ -_GLOBAL(low_sleep_handler) -#ifndef CONFIG_6xx - blr -#else - mflr r0 - stw r0,4(r1) - stwu r1,-SL_SIZE(r1) - mfcr r0 - stw r0,SL_CR(r1) - stw r2,SL_R2(r1) - stmw r12,SL_R12(r1) - - /* Save MSR & SDR1 */ - mfmsr r4 - stw r4,SL_MSR(r1) - mfsdr1 r4 - stw r4,SL_SDR1(r1) - - /* Get a stable timebase and save it */ -1: mftbu r4 - stw r4,SL_TB(r1) - mftb r5 - stw r5,SL_TB+4(r1) - mftbu r3 - cmpw r3,r4 - bne 1b - - /* Save SPRGs */ - mfsprg r4,0 - stw r4,SL_SPRG0(r1) - mfsprg r4,1 - stw r4,SL_SPRG0+4(r1) - mfsprg r4,2 - stw r4,SL_SPRG0+8(r1) - mfsprg r4,3 - stw r4,SL_SPRG0+12(r1) - - /* Save BATs */ - mfdbatu r4,0 - stw r4,SL_DBAT0(r1) - mfdbatl r4,0 - stw r4,SL_DBAT0+4(r1) - mfdbatu r4,1 - stw r4,SL_DBAT1(r1) - mfdbatl r4,1 - stw r4,SL_DBAT1+4(r1) - mfdbatu r4,2 - stw r4,SL_DBAT2(r1) - mfdbatl r4,2 - stw r4,SL_DBAT2+4(r1) - mfdbatu r4,3 - stw r4,SL_DBAT3(r1) - mfdbatl r4,3 - stw r4,SL_DBAT3+4(r1) - mfibatu r4,0 - stw r4,SL_IBAT0(r1) - mfibatl r4,0 - stw r4,SL_IBAT0+4(r1) - mfibatu r4,1 - stw r4,SL_IBAT1(r1) - mfibatl r4,1 - stw r4,SL_IBAT1+4(r1) - mfibatu r4,2 - stw r4,SL_IBAT2(r1) - mfibatl r4,2 - stw r4,SL_IBAT2+4(r1) - mfibatu r4,3 - stw r4,SL_IBAT3(r1) - mfibatl r4,3 - stw r4,SL_IBAT3+4(r1) - - /* Backup various CPU config stuffs */ - bl __save_cpu_setup - - /* The ROM can wake us up via 2 different vectors: - * - On wallstreet & lombard, we must write a magic - * value 'Lars' at address 4 and a pointer to a - * memory location containing the PC to resume from - * at address 0. - * - On Core99, we must store the wakeup vector at - * address 0x80 and eventually it's parameters - * at address 0x84. I've have some trouble with those - * parameters however and I no longer use them. - */ - lis r5,grackle_wake_up@ha - addi r5,r5,grackle_wake_up@l - tophys(r5,r5) - stw r5,SL_PC(r1) - lis r4,KERNELBASE@h - tophys(r5,r1) - addi r5,r5,SL_PC - lis r6,MAGIC@ha - addi r6,r6,MAGIC@l - stw r5,0(r4) - stw r6,4(r4) - /* Setup stuffs at 0x80-0x84 for Core99 */ - lis r3,core99_wake_up@ha - addi r3,r3,core99_wake_up@l - tophys(r3,r3) - stw r3,0x80(r4) - stw r5,0x84(r4) - /* Store a pointer to our backup storage into - * a kernel global - */ - lis r3,sleep_storage@ha - addi r3,r3,sleep_storage@l - stw r5,0(r3) - - .globl low_cpu_die -low_cpu_die: - /* Flush & disable all caches */ - bl flush_disable_caches - - /* Turn off data relocation. */ - mfmsr r3 /* Save MSR in r7 */ - rlwinm r3,r3,0,28,26 /* Turn off DR bit */ - sync - mtmsr r3 - isync - -BEGIN_FTR_SECTION - /* Flush any pending L2 data prefetches to work around HW bug */ - sync - lis r3,0xfff0 - lwz r0,0(r3) /* perform cache-inhibited load to ROM */ - sync /* (caches are disabled at this point) */ -END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450) - -/* - * Set the HID0 and MSR for sleep. - */ - mfspr r2,SPRN_HID0 - rlwinm r2,r2,0,10,7 /* clear doze, nap */ - oris r2,r2,HID0_SLEEP@h - sync - isync - mtspr SPRN_HID0,r2 - sync - -/* This loop puts us back to sleep in case we have a spurrious - * wakeup so that the host bridge properly stays asleep. The - * CPU will be turned off, either after a known time (about 1 - * second) on wallstreet & lombard, or as soon as the CPU enters - * SLEEP mode on core99 - */ - mfmsr r2 - oris r2,r2,MSR_POW@h -1: sync - mtmsr r2 - isync - b 1b - -/* - * Here is the resume code. - */ - - -/* - * Core99 machines resume here - * r4 has the physical address of SL_PC(sp) (unused) - */ -_GLOBAL(core99_wake_up) - /* Make sure HID0 no longer contains any sleep bit and that data cache - * is disabled - */ - mfspr r3,SPRN_HID0 - rlwinm r3,r3,0,11,7 /* clear SLEEP, NAP, DOZE bits */ - rlwinm 3,r3,0,18,15 /* clear DCE, ICE */ - mtspr SPRN_HID0,r3 - sync - isync - - /* sanitize MSR */ - mfmsr r3 - ori r3,r3,MSR_EE|MSR_IP - xori r3,r3,MSR_EE|MSR_IP - sync - isync - mtmsr r3 - sync - isync - - /* Recover sleep storage */ - lis r3,sleep_storage@ha - addi r3,r3,sleep_storage@l - tophys(r3,r3) - lwz r1,0(r3) - - /* Pass thru to older resume code ... */ -/* - * Here is the resume code for older machines. - * r1 has the physical address of SL_PC(sp). - */ - -grackle_wake_up: - - /* Restore the kernel's segment registers before - * we do any r1 memory access as we are not sure they - * are in a sane state above the first 256Mb region - */ - li r0,16 /* load up segment register values */ - mtctr r0 /* for context 0 */ - lis r3,0x2000 /* Ku = 1, VSID = 0 */ - li r4,0 -3: mtsrin r3,r4 - addi r3,r3,0x111 /* increment VSID */ - addis r4,r4,0x1000 /* address of next segment */ - bdnz 3b - sync - isync - - subi r1,r1,SL_PC - - /* Restore various CPU config stuffs */ - bl __restore_cpu_setup - - /* Make sure all FPRs have been initialized */ - bl reloc_offset - bl __init_fpu_registers - - /* Invalidate & enable L1 cache, we don't care about - * whatever the ROM may have tried to write to memory - */ - bl __inval_enable_L1 - - /* Restore the BATs, and SDR1. Then we can turn on the MMU. */ - lwz r4,SL_SDR1(r1) - mtsdr1 r4 - lwz r4,SL_SPRG0(r1) - mtsprg 0,r4 - lwz r4,SL_SPRG0+4(r1) - mtsprg 1,r4 - lwz r4,SL_SPRG0+8(r1) - mtsprg 2,r4 - lwz r4,SL_SPRG0+12(r1) - mtsprg 3,r4 - - lwz r4,SL_DBAT0(r1) - mtdbatu 0,r4 - lwz r4,SL_DBAT0+4(r1) - mtdbatl 0,r4 - lwz r4,SL_DBAT1(r1) - mtdbatu 1,r4 - lwz r4,SL_DBAT1+4(r1) - mtdbatl 1,r4 - lwz r4,SL_DBAT2(r1) - mtdbatu 2,r4 - lwz r4,SL_DBAT2+4(r1) - mtdbatl 2,r4 - lwz r4,SL_DBAT3(r1) - mtdbatu 3,r4 - lwz r4,SL_DBAT3+4(r1) - mtdbatl 3,r4 - lwz r4,SL_IBAT0(r1) - mtibatu 0,r4 - lwz r4,SL_IBAT0+4(r1) - mtibatl 0,r4 - lwz r4,SL_IBAT1(r1) - mtibatu 1,r4 - lwz r4,SL_IBAT1+4(r1) - mtibatl 1,r4 - lwz r4,SL_IBAT2(r1) - mtibatu 2,r4 - lwz r4,SL_IBAT2+4(r1) - mtibatl 2,r4 - lwz r4,SL_IBAT3(r1) - mtibatu 3,r4 - lwz r4,SL_IBAT3+4(r1) - mtibatl 3,r4 - -BEGIN_FTR_SECTION - li r4,0 - mtspr SPRN_DBAT4U,r4 - mtspr SPRN_DBAT4L,r4 - mtspr SPRN_DBAT5U,r4 - mtspr SPRN_DBAT5L,r4 - mtspr SPRN_DBAT6U,r4 - mtspr SPRN_DBAT6L,r4 - mtspr SPRN_DBAT7U,r4 - mtspr SPRN_DBAT7L,r4 - mtspr SPRN_IBAT4U,r4 - mtspr SPRN_IBAT4L,r4 - mtspr SPRN_IBAT5U,r4 - mtspr SPRN_IBAT5L,r4 - mtspr SPRN_IBAT6U,r4 - mtspr SPRN_IBAT6L,r4 - mtspr SPRN_IBAT7U,r4 - mtspr SPRN_IBAT7L,r4 -END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS) - - /* Flush all TLBs */ - lis r4,0x1000 -1: addic. r4,r4,-0x1000 - tlbie r4 - blt 1b - sync - - /* restore the MSR and turn on the MMU */ - lwz r3,SL_MSR(r1) - bl turn_on_mmu - - /* get back the stack pointer */ - tovirt(r1,r1) - - /* Restore TB */ - li r3,0 - mttbl r3 - lwz r3,SL_TB(r1) - lwz r4,SL_TB+4(r1) - mttbu r3 - mttbl r4 - - /* Restore the callee-saved registers and return */ - lwz r0,SL_CR(r1) - mtcr r0 - lwz r2,SL_R2(r1) - lmw r12,SL_R12(r1) - addi r1,r1,SL_SIZE - lwz r0,4(r1) - mtlr r0 - blr - -turn_on_mmu: - mflr r4 - tovirt(r4,r4) - mtsrr0 r4 - mtsrr1 r3 - sync - isync - rfi - -#endif /* defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ) */ - - .section .data - .balign L1_CACHE_BYTES -sleep_storage: - .long 0 - .balign L1_CACHE_BYTES, 0 - -#endif /* CONFIG_6xx */ - .section .text diff --git a/arch/ppc/platforms/pmac_smp.c b/arch/ppc/platforms/pmac_smp.c deleted file mode 100644 index 26ff26238f0..00000000000 --- a/arch/ppc/platforms/pmac_smp.c +++ /dev/null @@ -1,692 +0,0 @@ -/* - * SMP support for power macintosh. - * - * We support both the old "powersurge" SMP architecture - * and the current Core99 (G4 PowerMac) machines. - * - * Note that we don't support the very first rev. of - * Apple/DayStar 2 CPUs board, the one with the funky - * watchdog. Hopefully, none of these should be there except - * maybe internally to Apple. I should probably still add some - * code to detect this card though and disable SMP. --BenH. - * - * Support Macintosh G4 SMP by Troy Benjegerdes (hozer@drgw.net) - * and Ben Herrenschmidt . - * - * Support for DayStar quad CPU cards - * Copyright (C) XLR8, Inc. 1994-2000 - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Powersurge (old powermac SMP) support. - */ - -extern void __secondary_start_pmac_0(void); - -/* Addresses for powersurge registers */ -#define HAMMERHEAD_BASE 0xf8000000 -#define HHEAD_CONFIG 0x90 -#define HHEAD_SEC_INTR 0xc0 - -/* register for interrupting the primary processor on the powersurge */ -/* N.B. this is actually the ethernet ROM! */ -#define PSURGE_PRI_INTR 0xf3019000 - -/* register for storing the start address for the secondary processor */ -/* N.B. this is the PCI config space address register for the 1st bridge */ -#define PSURGE_START 0xf2800000 - -/* Daystar/XLR8 4-CPU card */ -#define PSURGE_QUAD_REG_ADDR 0xf8800000 - -#define PSURGE_QUAD_IRQ_SET 0 -#define PSURGE_QUAD_IRQ_CLR 1 -#define PSURGE_QUAD_IRQ_PRIMARY 2 -#define PSURGE_QUAD_CKSTOP_CTL 3 -#define PSURGE_QUAD_PRIMARY_ARB 4 -#define PSURGE_QUAD_BOARD_ID 6 -#define PSURGE_QUAD_WHICH_CPU 7 -#define PSURGE_QUAD_CKSTOP_RDBK 8 -#define PSURGE_QUAD_RESET_CTL 11 - -#define PSURGE_QUAD_OUT(r, v) (out_8(quad_base + ((r) << 4) + 4, (v))) -#define PSURGE_QUAD_IN(r) (in_8(quad_base + ((r) << 4) + 4) & 0x0f) -#define PSURGE_QUAD_BIS(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) | (v))) -#define PSURGE_QUAD_BIC(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) & ~(v))) - -/* virtual addresses for the above */ -static volatile u8 __iomem *hhead_base; -static volatile u8 __iomem *quad_base; -static volatile u32 __iomem *psurge_pri_intr; -static volatile u8 __iomem *psurge_sec_intr; -static volatile u32 __iomem *psurge_start; - -/* values for psurge_type */ -#define PSURGE_NONE -1 -#define PSURGE_DUAL 0 -#define PSURGE_QUAD_OKEE 1 -#define PSURGE_QUAD_COTTON 2 -#define PSURGE_QUAD_ICEGRASS 3 - -/* what sort of powersurge board we have */ -static int psurge_type = PSURGE_NONE; - -/* L2 and L3 cache settings to pass from CPU0 to CPU1 */ -volatile static long int core99_l2_cache; -volatile static long int core99_l3_cache; - -/* Timebase freeze GPIO */ -static unsigned int core99_tb_gpio; - -/* Sync flag for HW tb sync */ -static volatile int sec_tb_reset = 0; -static unsigned int pri_tb_hi, pri_tb_lo; -static unsigned int pri_tb_stamp; - -static void __devinit core99_init_caches(int cpu) -{ - if (!cpu_has_feature(CPU_FTR_L2CR)) - return; - - if (cpu == 0) { - core99_l2_cache = _get_L2CR(); - printk("CPU0: L2CR is %lx\n", core99_l2_cache); - } else { - printk("CPU%d: L2CR was %lx\n", cpu, _get_L2CR()); - _set_L2CR(0); - _set_L2CR(core99_l2_cache); - printk("CPU%d: L2CR set to %lx\n", cpu, core99_l2_cache); - } - - if (!cpu_has_feature(CPU_FTR_L3CR)) - return; - - if (cpu == 0){ - core99_l3_cache = _get_L3CR(); - printk("CPU0: L3CR is %lx\n", core99_l3_cache); - } else { - printk("CPU%d: L3CR was %lx\n", cpu, _get_L3CR()); - _set_L3CR(0); - _set_L3CR(core99_l3_cache); - printk("CPU%d: L3CR set to %lx\n", cpu, core99_l3_cache); - } -} - -/* - * Set and clear IPIs for powersurge. - */ -static inline void psurge_set_ipi(int cpu) -{ - if (psurge_type == PSURGE_NONE) - return; - if (cpu == 0) - in_be32(psurge_pri_intr); - else if (psurge_type == PSURGE_DUAL) - out_8(psurge_sec_intr, 0); - else - PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_SET, 1 << cpu); -} - -static inline void psurge_clr_ipi(int cpu) -{ - if (cpu > 0) { - switch(psurge_type) { - case PSURGE_DUAL: - out_8(psurge_sec_intr, ~0); - case PSURGE_NONE: - break; - default: - PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, 1 << cpu); - } - } -} - -/* - * On powersurge (old SMP powermac architecture) we don't have - * separate IPIs for separate messages like openpic does. Instead - * we have a bitmap for each processor, where a 1 bit means that - * the corresponding message is pending for that processor. - * Ideally each cpu's entry would be in a different cache line. - * -- paulus. - */ -static unsigned long psurge_smp_message[NR_CPUS]; - -void psurge_smp_message_recv(struct pt_regs *regs) -{ - int cpu = smp_processor_id(); - int msg; - - /* clear interrupt */ - psurge_clr_ipi(cpu); - - if (num_online_cpus() < 2) - return; - - /* make sure there is a message there */ - for (msg = 0; msg < 4; msg++) - if (test_and_clear_bit(msg, &psurge_smp_message[cpu])) - smp_message_recv(msg, regs); -} - -irqreturn_t psurge_primary_intr(int irq, void *d, struct pt_regs *regs) -{ - psurge_smp_message_recv(regs); - return IRQ_HANDLED; -} - -static void smp_psurge_message_pass(int target, int msg) -{ - int i; - - if (num_online_cpus() < 2) - return; - - for (i = 0; i < NR_CPUS; i++) { - if (!cpu_online(i)) - continue; - if (target == MSG_ALL - || (target == MSG_ALL_BUT_SELF && i != smp_processor_id()) - || target == i) { - set_bit(msg, &psurge_smp_message[i]); - psurge_set_ipi(i); - } - } -} - -/* - * Determine a quad card presence. We read the board ID register, we - * force the data bus to change to something else, and we read it again. - * It it's stable, then the register probably exist (ugh !) - */ -static int __init psurge_quad_probe(void) -{ - int type; - unsigned int i; - - type = PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID); - if (type < PSURGE_QUAD_OKEE || type > PSURGE_QUAD_ICEGRASS - || type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID)) - return PSURGE_DUAL; - - /* looks OK, try a slightly more rigorous test */ - /* bogus is not necessarily cacheline-aligned, - though I don't suppose that really matters. -- paulus */ - for (i = 0; i < 100; i++) { - volatile u32 bogus[8]; - bogus[(0+i)%8] = 0x00000000; - bogus[(1+i)%8] = 0x55555555; - bogus[(2+i)%8] = 0xFFFFFFFF; - bogus[(3+i)%8] = 0xAAAAAAAA; - bogus[(4+i)%8] = 0x33333333; - bogus[(5+i)%8] = 0xCCCCCCCC; - bogus[(6+i)%8] = 0xCCCCCCCC; - bogus[(7+i)%8] = 0x33333333; - wmb(); - asm volatile("dcbf 0,%0" : : "r" (bogus) : "memory"); - mb(); - if (type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID)) - return PSURGE_DUAL; - } - return type; -} - -static void __init psurge_quad_init(void) -{ - int procbits; - - if (ppc_md.progress) ppc_md.progress("psurge_quad_init", 0x351); - procbits = ~PSURGE_QUAD_IN(PSURGE_QUAD_WHICH_CPU); - if (psurge_type == PSURGE_QUAD_ICEGRASS) - PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits); - else - PSURGE_QUAD_BIC(PSURGE_QUAD_CKSTOP_CTL, procbits); - mdelay(33); - out_8(psurge_sec_intr, ~0); - PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, procbits); - PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits); - if (psurge_type != PSURGE_QUAD_ICEGRASS) - PSURGE_QUAD_BIS(PSURGE_QUAD_CKSTOP_CTL, procbits); - PSURGE_QUAD_BIC(PSURGE_QUAD_PRIMARY_ARB, procbits); - mdelay(33); - PSURGE_QUAD_BIC(PSURGE_QUAD_RESET_CTL, procbits); - mdelay(33); - PSURGE_QUAD_BIS(PSURGE_QUAD_PRIMARY_ARB, procbits); - mdelay(33); -} - -static int __init smp_psurge_probe(void) -{ - int i, ncpus; - - /* We don't do SMP on the PPC601 -- paulus */ - if (PVR_VER(mfspr(SPRN_PVR)) == 1) - return 1; - - /* - * The powersurge cpu board can be used in the generation - * of powermacs that have a socket for an upgradeable cpu card, - * including the 7500, 8500, 9500, 9600. - * The device tree doesn't tell you if you have 2 cpus because - * OF doesn't know anything about the 2nd processor. - * Instead we look for magic bits in magic registers, - * in the hammerhead memory controller in the case of the - * dual-cpu powersurge board. -- paulus. - */ - if (find_devices("hammerhead") == NULL) - return 1; - - hhead_base = ioremap(HAMMERHEAD_BASE, 0x800); - quad_base = ioremap(PSURGE_QUAD_REG_ADDR, 1024); - psurge_sec_intr = hhead_base + HHEAD_SEC_INTR; - - psurge_type = psurge_quad_probe(); - if (psurge_type != PSURGE_DUAL) { - psurge_quad_init(); - /* All released cards using this HW design have 4 CPUs */ - ncpus = 4; - } else { - iounmap(quad_base); - if ((in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) { - /* not a dual-cpu card */ - iounmap(hhead_base); - psurge_type = PSURGE_NONE; - return 1; - } - ncpus = 2; - } - - psurge_start = ioremap(PSURGE_START, 4); - psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4); - - /* this is not actually strictly necessary -- paulus. */ - for (i = 1; i < ncpus; ++i) - smp_hw_index[i] = i; - - if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352); - - return ncpus; -} - -static void __init smp_psurge_kick_cpu(int nr) -{ - unsigned long start = __pa(__secondary_start_pmac_0) + nr * 8; - unsigned long a; - - /* may need to flush here if secondary bats aren't setup */ - for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32) - asm volatile("dcbf 0,%0" : : "r" (a) : "memory"); - asm volatile("sync"); - - if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu", 0x353); - - out_be32(psurge_start, start); - mb(); - - psurge_set_ipi(nr); - udelay(10); - psurge_clr_ipi(nr); - - if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354); -} - -/* - * With the dual-cpu powersurge board, the decrementers and timebases - * of both cpus are frozen after the secondary cpu is started up, - * until we give the secondary cpu another interrupt. This routine - * uses this to get the timebases synchronized. - * -- paulus. - */ -static void __init psurge_dual_sync_tb(int cpu_nr) -{ - int t; - - set_dec(tb_ticks_per_jiffy); - set_tb(0, 0); - last_jiffy_stamp(cpu_nr) = 0; - - if (cpu_nr > 0) { - mb(); - sec_tb_reset = 1; - return; - } - - /* wait for the secondary to have reset its TB before proceeding */ - for (t = 10000000; t > 0 && !sec_tb_reset; --t) - ; - - /* now interrupt the secondary, starting both TBs */ - psurge_set_ipi(1); - - smp_tb_synchronized = 1; -} - -static struct irqaction psurge_irqaction = { - .handler = psurge_primary_intr, - .flags = SA_INTERRUPT, - .mask = CPU_MASK_NONE, - .name = "primary IPI", -}; - -static void __init smp_psurge_setup_cpu(int cpu_nr) -{ - - if (cpu_nr == 0) { - /* If we failed to start the second CPU, we should still - * send it an IPI to start the timebase & DEC or we might - * have them stuck. - */ - if (num_online_cpus() < 2) { - if (psurge_type == PSURGE_DUAL) - psurge_set_ipi(1); - return; - } - /* reset the entry point so if we get another intr we won't - * try to startup again */ - out_be32(psurge_start, 0x100); - if (setup_irq(30, &psurge_irqaction)) - printk(KERN_ERR "Couldn't get primary IPI interrupt"); - } - - if (psurge_type == PSURGE_DUAL) - psurge_dual_sync_tb(cpu_nr); -} - -void __init smp_psurge_take_timebase(void) -{ - /* Dummy implementation */ -} - -void __init smp_psurge_give_timebase(void) -{ - /* Dummy implementation */ -} - -static int __init smp_core99_probe(void) -{ -#ifdef CONFIG_6xx - extern int powersave_nap; -#endif - struct device_node *cpus, *firstcpu; - int i, ncpus = 0, boot_cpu = -1; - u32 *tbprop = NULL; - - if (ppc_md.progress) ppc_md.progress("smp_core99_probe", 0x345); - cpus = firstcpu = find_type_devices("cpu"); - while(cpus != NULL) { - u32 *regprop = (u32 *)get_property(cpus, "reg", NULL); - char *stateprop = (char *)get_property(cpus, "state", NULL); - if (regprop != NULL && stateprop != NULL && - !strncmp(stateprop, "running", 7)) - boot_cpu = *regprop; - ++ncpus; - cpus = cpus->next; - } - if (boot_cpu == -1) - printk(KERN_WARNING "Couldn't detect boot CPU !\n"); - if (boot_cpu != 0) - printk(KERN_WARNING "Boot CPU is %d, unsupported setup !\n", boot_cpu); - - if (machine_is_compatible("MacRISC4")) { - extern struct smp_ops_t core99_smp_ops; - - core99_smp_ops.take_timebase = smp_generic_take_timebase; - core99_smp_ops.give_timebase = smp_generic_give_timebase; - } else { - if (firstcpu != NULL) - tbprop = (u32 *)get_property(firstcpu, "timebase-enable", NULL); - if (tbprop) - core99_tb_gpio = *tbprop; - else - core99_tb_gpio = KL_GPIO_TB_ENABLE; - } - - if (ncpus > 1) { - openpic_request_IPIs(); - for (i = 1; i < ncpus; ++i) - smp_hw_index[i] = i; -#ifdef CONFIG_6xx - powersave_nap = 0; -#endif - core99_init_caches(0); - } - - return ncpus; -} - -static void __devinit smp_core99_kick_cpu(int nr) -{ - unsigned long save_vector, new_vector; - unsigned long flags; - - volatile unsigned long *vector - = ((volatile unsigned long *)(KERNELBASE+0x100)); - if (nr < 0 || nr > 3) - return; - if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346); - - local_irq_save(flags); - local_irq_disable(); - - /* Save reset vector */ - save_vector = *vector; - - /* Setup fake reset vector that does - * b __secondary_start_pmac_0 + nr*8 - KERNELBASE - */ - new_vector = (unsigned long) __secondary_start_pmac_0 + nr * 8; - *vector = 0x48000002 + new_vector - KERNELBASE; - - /* flush data cache and inval instruction cache */ - flush_icache_range((unsigned long) vector, (unsigned long) vector + 4); - - /* Put some life in our friend */ - pmac_call_feature(PMAC_FTR_RESET_CPU, NULL, nr, 0); - - /* FIXME: We wait a bit for the CPU to take the exception, I should - * instead wait for the entry code to set something for me. Well, - * ideally, all that crap will be done in prom.c and the CPU left - * in a RAM-based wait loop like CHRP. - */ - mdelay(1); - - /* Restore our exception vector */ - *vector = save_vector; - flush_icache_range((unsigned long) vector, (unsigned long) vector + 4); - - local_irq_restore(flags); - if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347); -} - -static void __devinit smp_core99_setup_cpu(int cpu_nr) -{ - /* Setup L2/L3 */ - if (cpu_nr != 0) - core99_init_caches(cpu_nr); - - /* Setup openpic */ - do_openpic_setup_cpu(); - - if (cpu_nr == 0) { -#ifdef CONFIG_POWER4 - extern void g5_phy_disable_cpu1(void); - - /* If we didn't start the second CPU, we must take - * it off the bus - */ - if (machine_is_compatible("MacRISC4") && - num_online_cpus() < 2) - g5_phy_disable_cpu1(); -#endif /* CONFIG_POWER4 */ - if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349); - } -} - -/* not __init, called in sleep/wakeup code */ -void smp_core99_take_timebase(void) -{ - unsigned long flags; - - /* tell the primary we're here */ - sec_tb_reset = 1; - mb(); - - /* wait for the primary to set pri_tb_hi/lo */ - while (sec_tb_reset < 2) - mb(); - - /* set our stuff the same as the primary */ - local_irq_save(flags); - set_dec(1); - set_tb(pri_tb_hi, pri_tb_lo); - last_jiffy_stamp(smp_processor_id()) = pri_tb_stamp; - mb(); - - /* tell the primary we're done */ - sec_tb_reset = 0; - mb(); - local_irq_restore(flags); -} - -/* not __init, called in sleep/wakeup code */ -void smp_core99_give_timebase(void) -{ - unsigned long flags; - unsigned int t; - - /* wait for the secondary to be in take_timebase */ - for (t = 100000; t > 0 && !sec_tb_reset; --t) - udelay(10); - if (!sec_tb_reset) { - printk(KERN_WARNING "Timeout waiting sync on second CPU\n"); - return; - } - - /* freeze the timebase and read it */ - /* disable interrupts so the timebase is disabled for the - shortest possible time */ - local_irq_save(flags); - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 4); - pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0); - mb(); - pri_tb_hi = get_tbu(); - pri_tb_lo = get_tbl(); - pri_tb_stamp = last_jiffy_stamp(smp_processor_id()); - mb(); - - /* tell the secondary we're ready */ - sec_tb_reset = 2; - mb(); - - /* wait for the secondary to have taken it */ - for (t = 100000; t > 0 && sec_tb_reset; --t) - udelay(10); - if (sec_tb_reset) - printk(KERN_WARNING "Timeout waiting sync(2) on second CPU\n"); - else - smp_tb_synchronized = 1; - - /* Now, restart the timebase by leaving the GPIO to an open collector */ - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 0); - pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0); - local_irq_restore(flags); -} - - -/* PowerSurge-style Macs */ -struct smp_ops_t psurge_smp_ops = { - .message_pass = smp_psurge_message_pass, - .probe = smp_psurge_probe, - .kick_cpu = smp_psurge_kick_cpu, - .setup_cpu = smp_psurge_setup_cpu, - .give_timebase = smp_psurge_give_timebase, - .take_timebase = smp_psurge_take_timebase, -}; - -/* Core99 Macs (dual G4s) */ -struct smp_ops_t core99_smp_ops = { - .message_pass = smp_openpic_message_pass, - .probe = smp_core99_probe, - .kick_cpu = smp_core99_kick_cpu, - .setup_cpu = smp_core99_setup_cpu, - .give_timebase = smp_core99_give_timebase, - .take_timebase = smp_core99_take_timebase, -}; - -#ifdef CONFIG_HOTPLUG_CPU - -int __cpu_disable(void) -{ - cpu_clear(smp_processor_id(), cpu_online_map); - - /* XXX reset cpu affinity here */ - openpic_set_priority(0xf); - asm volatile("mtdec %0" : : "r" (0x7fffffff)); - mb(); - udelay(20); - asm volatile("mtdec %0" : : "r" (0x7fffffff)); - return 0; -} - -extern void low_cpu_die(void) __attribute__((noreturn)); /* in pmac_sleep.S */ -static int cpu_dead[NR_CPUS]; - -void cpu_die(void) -{ - local_irq_disable(); - cpu_dead[smp_processor_id()] = 1; - mb(); - low_cpu_die(); -} - -void __cpu_die(unsigned int cpu) -{ - int timeout; - - timeout = 1000; - while (!cpu_dead[cpu]) { - if (--timeout == 0) { - printk("CPU %u refused to die!\n", cpu); - break; - } - msleep(1); - } - cpu_callin_map[cpu] = 0; - cpu_dead[cpu] = 0; -} - -#endif diff --git a/arch/ppc/platforms/pmac_time.c b/arch/ppc/platforms/pmac_time.c deleted file mode 100644 index edb9fcc6479..00000000000 --- a/arch/ppc/platforms/pmac_time.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Support for periodic interrupts (100 per second) and for getting - * the current time from the RTC on Power Macintoshes. - * - * We use the decrementer register for our periodic interrupts. - * - * Paul Mackerras August 1996. - * Copyright (C) 1996 Paul Mackerras. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -/* Apparently the RTC stores seconds since 1 Jan 1904 */ -#define RTC_OFFSET 2082844800 - -/* - * Calibrate the decrementer frequency with the VIA timer 1. - */ -#define VIA_TIMER_FREQ_6 4700000 /* time 1 frequency * 6 */ - -/* VIA registers */ -#define RS 0x200 /* skip between registers */ -#define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */ -#define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */ -#define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */ -#define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */ -#define ACR (11*RS) /* Auxiliary control register */ -#define IFR (13*RS) /* Interrupt flag register */ - -/* Bits in ACR */ -#define T1MODE 0xc0 /* Timer 1 mode */ -#define T1MODE_CONT 0x40 /* continuous interrupts */ - -/* Bits in IFR and IER */ -#define T1_INT 0x40 /* Timer 1 interrupt */ - -extern struct timezone sys_tz; - -long __init -pmac_time_init(void) -{ -#ifdef CONFIG_NVRAM - s32 delta = 0; - int dst; - - delta = ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x9)) << 16; - delta |= ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xa)) << 8; - delta |= pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xb); - if (delta & 0x00800000UL) - delta |= 0xFF000000UL; - dst = ((pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x8) & 0x80) != 0); - printk("GMT Delta read from XPRAM: %d minutes, DST: %s\n", delta/60, - dst ? "on" : "off"); - return delta; -#else - return 0; -#endif -} - -unsigned long -pmac_get_rtc_time(void) -{ -#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU) - struct adb_request req; - unsigned long now; -#endif - - /* Get the time from the RTC */ - switch (sys_ctrler) { -#ifdef CONFIG_ADB_CUDA - case SYS_CTRLER_CUDA: - if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0) - return 0; - while (!req.complete) - cuda_poll(); - if (req.reply_len != 7) - printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n", - req.reply_len); - now = (req.reply[3] << 24) + (req.reply[4] << 16) - + (req.reply[5] << 8) + req.reply[6]; - return now - RTC_OFFSET; -#endif /* CONFIG_ADB_CUDA */ -#ifdef CONFIG_ADB_PMU - case SYS_CTRLER_PMU: - if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) - return 0; - while (!req.complete) - pmu_poll(); - if (req.reply_len != 4) - printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n", - req.reply_len); - now = (req.reply[0] << 24) + (req.reply[1] << 16) - + (req.reply[2] << 8) + req.reply[3]; - return now - RTC_OFFSET; -#endif /* CONFIG_ADB_PMU */ - default: ; - } - return 0; -} - -int -pmac_set_rtc_time(unsigned long nowtime) -{ -#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU) - struct adb_request req; -#endif - - nowtime += RTC_OFFSET; - - switch (sys_ctrler) { -#ifdef CONFIG_ADB_CUDA - case SYS_CTRLER_CUDA: - if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME, - nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0) - return 0; - while (!req.complete) - cuda_poll(); - if ((req.reply_len != 3) && (req.reply_len != 7)) - printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n", - req.reply_len); - return 1; -#endif /* CONFIG_ADB_CUDA */ -#ifdef CONFIG_ADB_PMU - case SYS_CTRLER_PMU: - if (pmu_request(&req, NULL, 5, PMU_SET_RTC, - nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0) - return 0; - while (!req.complete) - pmu_poll(); - if (req.reply_len != 0) - printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n", - req.reply_len); - return 1; -#endif /* CONFIG_ADB_PMU */ - default: - return 0; - } -} - -/* - * Calibrate the decrementer register using VIA timer 1. - * This is used both on powermacs and CHRP machines. - */ -int __init -via_calibrate_decr(void) -{ - struct device_node *vias; - volatile unsigned char __iomem *via; - int count = VIA_TIMER_FREQ_6 / 100; - unsigned int dstart, dend; - - vias = find_devices("via-cuda"); - if (vias == 0) - vias = find_devices("via-pmu"); - if (vias == 0) - vias = find_devices("via"); - if (vias == 0 || vias->n_addrs == 0) - return 0; - via = ioremap(vias->addrs[0].address, vias->addrs[0].size); - - /* set timer 1 for continuous interrupts */ - out_8(&via[ACR], (via[ACR] & ~T1MODE) | T1MODE_CONT); - /* set the counter to a small value */ - out_8(&via[T1CH], 2); - /* set the latch to `count' */ - out_8(&via[T1LL], count); - out_8(&via[T1LH], count >> 8); - /* wait until it hits 0 */ - while ((in_8(&via[IFR]) & T1_INT) == 0) - ; - dstart = get_dec(); - /* clear the interrupt & wait until it hits 0 again */ - in_8(&via[T1CL]); - while ((in_8(&via[IFR]) & T1_INT) == 0) - ; - dend = get_dec(); - - tb_ticks_per_jiffy = (dstart - dend) / ((6 * HZ)/100); - tb_to_us = mulhwu_scale_factor(dstart - dend, 60000); - - printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n", - tb_ticks_per_jiffy, dstart - dend); - - iounmap(via); - - return 1; -} - -#ifdef CONFIG_PM -/* - * Reset the time after a sleep. - */ -static int -time_sleep_notify(struct pmu_sleep_notifier *self, int when) -{ - static unsigned long time_diff; - unsigned long flags; - unsigned long seq; - - switch (when) { - case PBOOK_SLEEP_NOW: - do { - seq = read_seqbegin_irqsave(&xtime_lock, flags); - time_diff = xtime.tv_sec - pmac_get_rtc_time(); - } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); - break; - case PBOOK_WAKE: - write_seqlock_irqsave(&xtime_lock, flags); - xtime.tv_sec = pmac_get_rtc_time() + time_diff; - xtime.tv_nsec = 0; - last_rtc_update = xtime.tv_sec; - write_sequnlock_irqrestore(&xtime_lock, flags); - break; - } - return PBOOK_SLEEP_OK; -} - -static struct pmu_sleep_notifier time_sleep_notifier = { - time_sleep_notify, SLEEP_LEVEL_MISC, -}; -#endif /* CONFIG_PM */ - -/* - * Query the OF and get the decr frequency. - * This was taken from the pmac time_init() when merging the prep/pmac - * time functions. - */ -void __init -pmac_calibrate_decr(void) -{ - struct device_node *cpu; - unsigned int freq, *fp; - -#ifdef CONFIG_PM - pmu_register_sleep_notifier(&time_sleep_notifier); -#endif /* CONFIG_PM */ - - /* We assume MacRISC2 machines have correct device-tree - * calibration. That's better since the VIA itself seems - * to be slightly off. --BenH - */ - if (!machine_is_compatible("MacRISC2") && - !machine_is_compatible("MacRISC3") && - !machine_is_compatible("MacRISC4")) - if (via_calibrate_decr()) - return; - - /* Special case: QuickSilver G4s seem to have a badly calibrated - * timebase-frequency in OF, VIA is much better on these. We should - * probably implement calibration based on the KL timer on these - * machines anyway... -BenH - */ - if (machine_is_compatible("PowerMac3,5")) - if (via_calibrate_decr()) - return; - /* - * The cpu node should have a timebase-frequency property - * to tell us the rate at which the decrementer counts. - */ - cpu = find_type_devices("cpu"); - if (cpu == 0) - panic("can't find cpu node in time_init"); - fp = (unsigned int *) get_property(cpu, "timebase-frequency", NULL); - if (fp == 0) - panic("can't get cpu timebase frequency"); - freq = *fp; - printk("time_init: decrementer frequency = %u.%.6u MHz\n", - freq/1000000, freq%1000000); - tb_ticks_per_jiffy = freq / HZ; - tb_to_us = mulhwu_scale_factor(freq, 1000000); -} diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile index 84ef03018d0..159dcd92a6d 100644 --- a/arch/ppc/syslib/Makefile +++ b/arch/ppc/syslib/Makefile @@ -39,8 +39,6 @@ obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) \ ppc_sys.o mpc8xx_devices.o mpc8xx_sys.o obj-$(CONFIG_PCI_QSPAN) += qspan_pci.o obj-$(CONFIG_PPC_OF) += prom_init.o prom.o -obj-$(CONFIG_PPC_PMAC) += open_pic.o -obj-$(CONFIG_POWER4) += open_pic2.o obj-$(CONFIG_PPC_CHRP) += open_pic.o obj-$(CONFIG_PPC_PREP) += open_pic.o todc_time.o obj-$(CONFIG_BAMBOO) += pci_auto.o todc_time.o diff --git a/arch/ppc/syslib/prom.c b/arch/ppc/syslib/prom.c index af4deace49e..482f837fd37 100644 --- a/arch/ppc/syslib/prom.c +++ b/arch/ppc/syslib/prom.c @@ -70,8 +70,6 @@ int use_of_interrupt_tree; struct device_node *dflt_interrupt_controller; int num_interrupt_controllers; -int pmac_newworld; - extern unsigned int rtas_entry; /* physical pointer */ extern struct device_node *allnodes; @@ -123,22 +121,13 @@ finish_device_tree(void) unsigned long mem = (unsigned long) klimit; struct device_node *np; - /* All newworld pmac machines and CHRPs now use the interrupt tree */ + /* All CHRPs now use the interrupt tree */ for (np = allnodes; np != NULL; np = np->allnext) { if (get_property(np, "interrupt-parent", NULL)) { use_of_interrupt_tree = 1; break; } } - if (_machine == _MACH_Pmac && use_of_interrupt_tree) - pmac_newworld = 1; - -#ifdef CONFIG_BOOTX_TEXT - if (boot_infos && pmac_newworld) { - prom_print("WARNING ! BootX/miBoot booting is not supported on this machine\n"); - prom_print(" You should use an Open Firmware bootloader\n"); - } -#endif /* CONFIG_BOOTX_TEXT */ if (use_of_interrupt_tree) { /* @@ -434,16 +423,10 @@ finish_node_interrupts(struct device_node *np, unsigned long mem_start) * those machines, we want to offset interrupts from the * second openpic by 128 -- BenH */ - if (_machine != _MACH_Pmac && num_interrupt_controllers > 1 + if (num_interrupt_controllers > 1 && ic != NULL && get_property(ic, "interrupt-parent", NULL) == NULL) offset = 16; - else if (_machine == _MACH_Pmac && num_interrupt_controllers > 1 - && ic != NULL && ic->parent != NULL) { - char *name = get_property(ic->parent, "name", NULL); - if (name && !strcmp(name, "u3")) - offset = 128; - } np->intrs[i].line = irq[0] + offset; if (n > 1) diff --git a/arch/ppc/xmon/start.c b/arch/ppc/xmon/start.c index c80177f8ec0..4344cbe9b5c 100644 --- a/arch/ppc/xmon/start.c +++ b/arch/ppc/xmon/start.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -27,11 +26,9 @@ static volatile unsigned char *sccc, *sccd; unsigned int TXRDY, RXRDY, DLAB; static int xmon_expect(const char *str, unsigned int timeout); -static int use_serial; static int use_screen; static int via_modem; static int xmon_use_sccb; -static struct device_node *channel_node; #define TB_SPEED 25000000 @@ -112,96 +109,21 @@ xmon_map_scc(void) #ifdef CONFIG_PPC_MULTIPLATFORM volatile unsigned char *base; - if (_machine == _MACH_Pmac) { - struct device_node *np; - unsigned long addr; -#ifdef CONFIG_BOOTX_TEXT - if (!use_screen && !use_serial - && !machine_is_compatible("iMac")) { - /* see if there is a keyboard in the device tree - with a parent of type "adb" */ - for (np = find_devices("keyboard"); np; np = np->next) - if (np->parent && np->parent->type - && strcmp(np->parent->type, "adb") == 0) - break; - - /* needs to be hacked if xmon_printk is to be used - from within find_via_pmu() */ -#ifdef CONFIG_ADB_PMU - if (np != NULL && boot_text_mapped && find_via_pmu()) - use_screen = 1; -#endif -#ifdef CONFIG_ADB_CUDA - if (np != NULL && boot_text_mapped && find_via_cuda()) - use_screen = 1; -#endif - } - if (!use_screen && (np = find_devices("escc")) != NULL) { - /* - * look for the device node for the serial port - * we're using and see if it says it has a modem - */ - char *name = xmon_use_sccb? "ch-b": "ch-a"; - char *slots; - int l; - - np = np->child; - while (np != NULL && strcmp(np->name, name) != 0) - np = np->sibling; - if (np != NULL) { - /* XXX should parse this properly */ - channel_node = np; - slots = get_property(np, "slot-names", &l); - if (slots != NULL && l >= 10 - && strcmp(slots+4, "Modem") == 0) - via_modem = 1; - } - } - btext_drawstring("xmon uses "); - if (use_screen) - btext_drawstring("screen and keyboard\n"); - else { - if (via_modem) - btext_drawstring("modem on "); - btext_drawstring(xmon_use_sccb? "printer": "modem"); - btext_drawstring(" port\n"); - } - -#endif /* CONFIG_BOOTX_TEXT */ - -#ifdef CHRP_ESCC - addr = 0xc1013020; -#else - addr = 0xf3013020; -#endif - TXRDY = 4; - RXRDY = 1; - - np = find_devices("mac-io"); - if (np && np->n_addrs) - addr = np->addrs[0].address + 0x13020; - base = (volatile unsigned char *) ioremap(addr & PAGE_MASK, PAGE_SIZE); - sccc = base + (addr & ~PAGE_MASK); - sccd = sccc + 0x10; - - } #ifdef CONFIG_PPC_CHRP - else { - base = (volatile unsigned char *) isa_io_base; - if (_machine == _MACH_chrp) - base = (volatile unsigned char *) - ioremap(chrp_find_phys_io_base(), 0x1000); - - sccc = base + 0x3fd; - sccd = base + 0x3f8; - if (xmon_use_sccb) { - sccc -= 0x100; - sccd -= 0x100; - } - TXRDY = 0x20; - RXRDY = 1; - DLAB = 0x80; + base = (volatile unsigned char *) isa_io_base; + if (_machine == _MACH_chrp) + base = (volatile unsigned char *) + ioremap(chrp_find_phys_io_base(), 0x1000); + + sccc = base + 0x3fd; + sccd = base + 0x3f8; + if (xmon_use_sccb) { + sccc -= 0x100; + sccd -= 0x100; } + TXRDY = 0x20; + RXRDY = 1; + DLAB = 0x80; #endif /* CONFIG_PPC_CHRP */ #elif defined(CONFIG_GEMINI) /* should already be mapped by the kernel boot */ @@ -385,16 +307,6 @@ xmon_read_poll(void) return *sccd; } -static unsigned char scc_inittab[] = { - 13, 0, /* set baud rate divisor */ - 12, 1, - 14, 1, /* baud rate gen enable, src=rtxc */ - 11, 0x50, /* clocks = br gen */ - 5, 0xea, /* tx 8 bits, assert DTR & RTS */ - 4, 0x46, /* x16 clock, 1 stop */ - 3, 0xc1, /* rx enable, 8 bits */ -}; - void xmon_init_scc(void) { @@ -407,43 +319,6 @@ xmon_init_scc(void) sccd[3] = 3; eieio(); /* LCR = 8N1 */ sccd[1] = 0; eieio(); /* IER = 0 */ } - else if ( _machine == _MACH_Pmac ) - { - int i, x; - - if (channel_node != 0) - pmac_call_feature( - PMAC_FTR_SCC_ENABLE, - channel_node, - PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1); - printk(KERN_INFO "Serial port locked ON by debugger !\n"); - if (via_modem && channel_node != 0) { - unsigned int t0; - - pmac_call_feature( - PMAC_FTR_MODEM_ENABLE, - channel_node, 0, 1); - printk(KERN_INFO "Modem powered up by debugger !\n"); - t0 = readtb(); - while (readtb() - t0 < 3*TB_SPEED) - eieio(); - } - /* use the B channel if requested */ - if (xmon_use_sccb) { - sccc = (volatile unsigned char *) - ((unsigned long)sccc & ~0x20); - sccd = sccc + 0x10; - } - for (i = 20000; i != 0; --i) { - x = *sccc; eieio(); - } - *sccc = 9; eieio(); /* reset A or B side */ - *sccc = ((unsigned long)sccc & 0x20)? 0x80: 0x40; eieio(); - for (i = 0; i < sizeof(scc_inittab); ++i) { - *sccc = scc_inittab[i]; - eieio(); - } - } scc_initialized = 1; if (via_modem) { for (;;) { @@ -632,19 +507,9 @@ xmon_fgets(char *str, int nb, void *f) void xmon_enter(void) { -#ifdef CONFIG_ADB_PMU - if (_machine == _MACH_Pmac) { - pmu_suspend(); - } -#endif } void xmon_leave(void) { -#ifdef CONFIG_ADB_PMU - if (_machine == _MACH_Pmac) { - pmu_resume(); - } -#endif } diff --git a/arch/ppc/xmon/xmon.c b/arch/ppc/xmon/xmon.c index 9075a7538e2..bdaf6597b4c 100644 --- a/arch/ppc/xmon/xmon.c +++ b/arch/ppc/xmon/xmon.c @@ -16,9 +16,6 @@ #include #include #include -#ifdef CONFIG_PMAC_BACKLIGHT -#include -#endif #include "nonstdio.h" #include "privinst.h" @@ -260,16 +257,6 @@ int xmon(struct pt_regs *excp) */ #endif /* CONFIG_SMP */ remove_bpts(); -#ifdef CONFIG_PMAC_BACKLIGHT - if( setjmp(bus_error_jmp) == 0 ) { - debugger_fault_handler = handle_fault; - sync(); - set_backlight_enable(1); - set_backlight_level(BACKLIGHT_MAX); - sync(); - } - debugger_fault_handler = NULL; -#endif /* CONFIG_PMAC_BACKLIGHT */ cmd = cmds(excp); if (cmd == 's') { xmon_trace[smp_processor_id()] = SSTEP; diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index 097d668c4fe..556895e9964 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c @@ -2734,7 +2734,7 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk) * BIOS does tho. Right now, all this PM stuff is pmac-only for that * reason. --BenH */ -#if defined(CONFIG_PM) && defined(CONFIG_PPC_OF) +#if defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC) if (_machine == _MACH_Pmac && rinfo->of_node) { if (rinfo->is_mobility && rinfo->pm_reg && rinfo->family <= CHIP_FAMILY_RV250) @@ -2778,12 +2778,12 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk) OUTREG(TV_DAC_CNTL, INREG(TV_DAC_CNTL) | 0x07000000); #endif } -#endif /* defined(CONFIG_PM) && defined(CONFIG_PPC_OF) */ +#endif /* defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC) */ } void radeonfb_pm_exit(struct radeonfb_info *rinfo) { -#if defined(CONFIG_PM) && defined(CONFIG_PPC_OF) +#if defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC) if (rinfo->pm_mode != radeon_pm_none) pmac_set_early_video_resume(NULL, NULL); #endif diff --git a/include/asm-ppc/prom.h b/include/asm-ppc/prom.h index eb317a0806e..6d431d6fb02 100644 --- a/include/asm-ppc/prom.h +++ b/include/asm-ppc/prom.h @@ -167,6 +167,14 @@ extern int of_address_to_resource(struct device_node *dev, int index, extern int of_pci_address_to_resource(struct device_node *dev, int bar, struct resource *r); +#ifndef CONFIG_PPC_OF +/* + * Fallback definitions for builds where we don't have prom.c included. + */ +#define machine_is_compatible(x) 0 +#define of_find_compatible_node(f, t, c) NULL +#define get_property(p, n, l) NULL +#endif #endif /* _PPC_PROM_H */ #endif /* __KERNEL__ */ -- GitLab From 820a8ce7931d18338e5c089725ec083518da1644 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sun, 15 Jan 2006 17:33:52 +1100 Subject: [PATCH 314/465] powerpc: Make ARCH=powerpc the default for 32-bit ppc This makes ARCH=powerpc the default on 32-bit powerpc machines, where uname -m returns ppc, as well as on 64-bit powerpc machines. Most people who would be likely to build their own kernels on 32-bit powerpc machines would be using powermacs or CHRP machines, both of which are supported with ARCH=powerpc now. Embedded ppc developers whose ports haven't been moved over to arch/powerpc yet will have to explicitly set ARCH=ppc now. Signed-off-by: Paul Mackerras --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index deedaf79cdc..673148e0760 100644 --- a/Makefile +++ b/Makefile @@ -151,7 +151,7 @@ export srctree objtree VPATH TOPDIR SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ -e s/arm.*/arm/ -e s/sa110/arm/ \ -e s/s390x/s390/ -e s/parisc64/parisc/ \ - -e s/ppc64/powerpc/ ) + -e s/ppc.*/powerpc/ ) # Cross compiling and selecting different set of gcc/bin-utils # --------------------------------------------------------------------------- -- GitLab From 436eddd035c0ff807f4c64551a5a6edc7fb299d0 Mon Sep 17 00:00:00 2001 From: Tyler Trafford Date: Fri, 13 Jan 2006 14:38:18 -0200 Subject: [PATCH 315/465] V4L/DVB (3365): i2c ids for upd64031a saa717x upd64083 wm8739 - Add i2c ids for drivers: upd64031a saa717x upd64083 wm8739 Signed-off-by: Tyler Trafford Signed-off-by: Mauro Carvalho Chehab --- include/linux/i2c-id.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index 6ff2d365895..474c8f4f5d4 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h @@ -104,6 +104,10 @@ #define I2C_DRIVERID_AKITAIOEXP 74 /* IO Expander on Sharp SL-C1000 */ #define I2C_DRIVERID_INFRARED 75 /* I2C InfraRed on Video boards */ #define I2C_DRIVERID_TVP5150 76 /* TVP5150 video decoder */ +#define I2C_DRIVERID_WM8739 77 /* wm8739 audio processor */ +#define I2C_DRIVERID_UPD64083 78 /* upd64083 video processor */ +#define I2C_DRIVERID_UPD64031A 79 /* upd64031a video processor */ +#define I2C_DRIVERID_SAA717X 80 /* saa717x video encoder */ #define I2C_DRIVERID_I2CDEV 900 #define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */ -- GitLab From 0f79c3637a871c6ebcf8b8c1762725152d5a18d7 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Sat, 14 Jan 2006 21:26:44 -0200 Subject: [PATCH 316/465] V4L/DVB (3371): Turn frame locked sound on, basic support for FM radio with TDA8275(a) - Enabled audio PLL. This is mandatory for NICAM sound - modify FM IF frequency to 5.5MHz for SAA7133/35 if tuner is tda8290 Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 6 ++++++ drivers/media/video/saa7134/saa7134-tvaudio.c | 11 ++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 275d06af69d..c64718aec9c 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2515,6 +2515,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .mpeg = SAA7134_MPEG_DVB, + .gpiomask = 1 << 21, .inputs = {{ .name = name_tv, .vmux = 1, @@ -2529,6 +2530,11 @@ struct saa7134_board saa7134_boards[] = { .vmux = 8, .amux = LINE1, }}, + .radio = { + .name = name_radio, + .amux = TV, + .gpio = 0x0200000, + }, }, [SAA7134_BOARD_MSI_TVATANYWHERE_PLUS] = { .name = "MSI TV@Anywhere plus", diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c index 93268427750..afa4dcb3f96 100644 --- a/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/drivers/media/video/saa7134/saa7134-tvaudio.c @@ -180,8 +180,8 @@ static void tvaudio_init(struct saa7134_dev *dev) saa_writeb(SAA7134_AUDIO_CLOCK0, clock & 0xff); saa_writeb(SAA7134_AUDIO_CLOCK1, (clock >> 8) & 0xff); saa_writeb(SAA7134_AUDIO_CLOCK2, (clock >> 16) & 0xff); - // frame locked audio was reported not to be reliable - saa_writeb(SAA7134_AUDIO_PLL_CTRL, 0x02); + /* frame locked audio is mandatory for NICAM */ + saa_writeb(SAA7134_AUDIO_PLL_CTRL, 0x01); saa_writeb(SAA7134_NICAM_ERROR_LOW, 0x14); saa_writeb(SAA7134_NICAM_ERROR_HIGH, 0x50); @@ -809,7 +809,12 @@ static int tvaudio_thread_ddep(void *data) dprintk("ddep override: %s\n",stdres[audio_ddep]); } else if (&card(dev).radio == dev->input) { dprintk("FM Radio\n"); - norms = (0x0f << 2) | 0x01; + if (dev->tuner_type == TUNER_PHILIPS_TDA8290) { + norms = (0x11 << 2) | 0x01; + saa_dsp_writel(dev, 0x42c >> 2, 0x729555); + } else { + norms = (0x0f << 2) | 0x01; + } } else { /* (let chip) scan for sound carrier */ norms = 0; -- GitLab From 15192b1d53506f739b36d37543c42619ac290ebc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 15 Jan 2006 06:50:01 -0200 Subject: [PATCH 317/465] V4L/DVB (3376): cx88 Kconfig fixes for cx88-alsa - Cx88 alsa is experimental. - Removed need of PCM OSS for an ALSA module. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 76fcb4e995c..53308911ae6 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -31,8 +31,7 @@ config VIDEO_CX88_DVB config VIDEO_CX88_ALSA tristate "ALSA DMA audio support" - depends on VIDEO_CX88 && SND - select SND_PCM_OSS + depends on VIDEO_CX88 && SND && EXPERIMENTAL ---help--- This is a video4linux driver for direct (DMA) audio on Conexant 2388x based TV cards. -- GitLab From a9cff90ed9a23e9f73963fe73b71ef7e5de3e822 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 15 Jan 2006 06:56:15 -0200 Subject: [PATCH 318/465] V4L/DVB (3377): make some code static - This patch makes some needlessly global code static. Signed-off-by: Adrian Bunk Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25840/cx25840-core.c | 2 +- drivers/media/video/tvp5150.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 0da744c1d23..c66c2c1f480 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -43,7 +43,7 @@ MODULE_LICENSE("GPL"); static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; -int cx25840_debug; +static int cx25840_debug; module_param_named(debug,cx25840_debug, int, 0644); diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index e86b522938f..8713c4d0dcc 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -634,7 +634,7 @@ struct i2c_vbi_ram_value { unsigned char values[26]; }; -struct i2c_vbi_ram_value vbi_ram_default[] = +static struct i2c_vbi_ram_value vbi_ram_default[] = { {0x010, /* WST SECAM 6 */ { 0xaa, 0xaa, 0xff, 0xff , 0xe7, 0x2e, 0x20, 0x26, 0xe6, 0xb4, 0x0e, 0x0, 0x0, 0x0, 0x10, 0x0 } -- GitLab From 7d83e8431ae531e907f09c277ab4ab4620092518 Mon Sep 17 00:00:00 2001 From: Panagiotis Christeas Date: Sun, 15 Jan 2006 07:01:54 -0200 Subject: [PATCH 319/465] V4L/DVB (3378): Fix for lack of analog output on some cx88 boards - Workaround to fix a known regression at cx88-tvaudio.c - provide a module parameter workaround to always enable analog output. Signed-off-by: Panagiotis Christeas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-tvaudio.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index 24118e43e73..da8d97ce0c4 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c @@ -60,6 +60,11 @@ static unsigned int audio_debug = 0; module_param(audio_debug, int, 0644); MODULE_PARM_DESC(audio_debug, "enable debug messages [audio]"); +static unsigned int always_analog = 0; +module_param(always_analog,int,0644); +MODULE_PARM_DESC(always_analog,"force analog audio out"); + + #define dprintk(fmt, arg...) if (audio_debug) \ printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg) @@ -155,7 +160,8 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl) cx_write(AUD_I2SOUTPUTCNTL, 1); cx_write(AUD_I2SCNTL, 0); /* cx_write(AUD_APB_IN_RATE_ADJ, 0); */ - } else { + } + if ((always_analog) || (!cx88_boards[core->board].blackbird)) { ctl |= EN_DAC_ENABLE; cx_write(AUD_CTL, ctl); } -- GitLab From 1e4baed379a2bff3c728ea34602d3432fb047af8 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 15 Jan 2006 07:52:23 -0200 Subject: [PATCH 320/465] V4L/DVB (3380): Semaphore to mutex conversion on drivers/media - Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvbdev.c | 22 +++++++++---------- drivers/media/video/cx88/cx88-core.c | 15 +++++++------ drivers/media/video/em28xx/em28xx-video.c | 7 +++--- drivers/media/video/saa7134/saa7134-core.c | 19 ++++++++-------- drivers/media/video/videodev.c | 25 +++++++++++----------- 5 files changed, 45 insertions(+), 43 deletions(-) diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c index 06b696e9acb..54f8b95717b 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ b/drivers/media/dvb/dvb-core/dvbdev.c @@ -33,7 +33,7 @@ #include #include #include - +#include #include "dvbdev.h" static int dvbdev_debug; @@ -44,7 +44,7 @@ MODULE_PARM_DESC(dvbdev_debug, "Turn on/off device debugging (default:off)."); #define dprintk if (dvbdev_debug) printk static LIST_HEAD(dvb_adapter_list); -static DECLARE_MUTEX(dvbdev_register_lock); +static DEFINE_MUTEX(dvbdev_register_lock); static const char * const dnames[] = { "video", "audio", "sec", "frontend", "demux", "dvr", "ca", @@ -202,11 +202,11 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, struct dvb_device *dvbdev; int id; - if (down_interruptible (&dvbdev_register_lock)) + if (mutex_lock_interruptible(&dvbdev_register_lock)) return -ERESTARTSYS; if ((id = dvbdev_get_free_id (adap, type)) < 0) { - up (&dvbdev_register_lock); + mutex_unlock(&dvbdev_register_lock); *pdvbdev = NULL; printk ("%s: could get find free device id...\n", __FUNCTION__); return -ENFILE; @@ -215,11 +215,11 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, *pdvbdev = dvbdev = kmalloc(sizeof(struct dvb_device), GFP_KERNEL); if (!dvbdev) { - up(&dvbdev_register_lock); + mutex_unlock(&dvbdev_register_lock); return -ENOMEM; } - up (&dvbdev_register_lock); + mutex_unlock(&dvbdev_register_lock); memcpy(dvbdev, template, sizeof(struct dvb_device)); dvbdev->type = type; @@ -289,11 +289,11 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct modu { int num; - if (down_interruptible (&dvbdev_register_lock)) + if (mutex_lock_interruptible(&dvbdev_register_lock)) return -ERESTARTSYS; if ((num = dvbdev_get_free_adapter_num ()) < 0) { - up (&dvbdev_register_lock); + mutex_unlock(&dvbdev_register_lock); return -ENFILE; } @@ -309,7 +309,7 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct modu list_add_tail (&adap->list_head, &dvb_adapter_list); - up (&dvbdev_register_lock); + mutex_unlock(&dvbdev_register_lock); return num; } @@ -320,10 +320,10 @@ int dvb_unregister_adapter(struct dvb_adapter *adap) { devfs_remove("dvb/adapter%d", adap->num); - if (down_interruptible (&dvbdev_register_lock)) + if (mutex_lock_interruptible(&dvbdev_register_lock)) return -ERESTARTSYS; list_del (&adap->list_head); - up (&dvbdev_register_lock); + mutex_unlock(&dvbdev_register_lock); return 0; } EXPORT_SYMBOL(dvb_unregister_adapter); diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index 194446f28c5..8d6d6a6cf78 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "cx88.h" #include @@ -75,7 +76,7 @@ MODULE_PARM_DESC(nocomb,"disable comb filter"); static unsigned int cx88_devcount; static LIST_HEAD(cx88_devlist); -static DECLARE_MUTEX(devlist); +static DEFINE_MUTEX(devlist); #define NO_SYNC_LINE (-1U) @@ -1036,7 +1037,7 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci) struct list_head *item; int i; - down(&devlist); + mutex_lock(&devlist); list_for_each(item,&cx88_devlist) { core = list_entry(item, struct cx88_core, devlist); if (pci->bus->number != core->pci_bus) @@ -1047,7 +1048,7 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci) if (0 != get_ressources(core,pci)) goto fail_unlock; atomic_inc(&core->refcount); - up(&devlist); + mutex_unlock(&devlist); return core; } core = kzalloc(sizeof(*core),GFP_KERNEL); @@ -1122,13 +1123,13 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci) cx88_card_setup(core); cx88_ir_init(core,pci); - up(&devlist); + mutex_unlock(&devlist); return core; fail_free: kfree(core); fail_unlock: - up(&devlist); + mutex_unlock(&devlist); return NULL; } @@ -1140,14 +1141,14 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci) if (!atomic_dec_and_test(&core->refcount)) return; - down(&devlist); + mutex_lock(&devlist); cx88_ir_fini(core); if (0 == core->i2c_rc) i2c_bit_del_bus(&core->i2c_adap); list_del(&core->devlist); iounmap(core->lmmio); cx88_devcount--; - up(&devlist); + mutex_unlock(&devlist); kfree(core); } diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 3323dffe26a..eea304f7517 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "em28xx.h" #include @@ -191,7 +192,7 @@ static struct v4l2_queryctrl saa711x_qctrl[] = { static struct usb_driver em28xx_usb_driver; -static DECLARE_MUTEX(em28xx_sysfs_lock); +static DEFINE_MUTEX(em28xx_sysfs_lock); static DECLARE_RWSEM(em28xx_disconnect); /********************* v4l2 interface ******************************************/ @@ -394,7 +395,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) */ static void em28xx_release_resources(struct em28xx *dev) { - down(&em28xx_sysfs_lock); + mutex_lock(&em28xx_sysfs_lock); em28xx_info("V4L2 device /dev/video%d deregistered\n", dev->vdev->minor); @@ -403,7 +404,7 @@ static void em28xx_release_resources(struct em28xx *dev) /* video_unregister_device(dev->vbi_dev); */ em28xx_i2c_unregister(dev); usb_put_dev(dev->udev); - up(&em28xx_sysfs_lock); + mutex_unlock(&em28xx_sysfs_lock); } /* diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 3dd42efe369..028904bd94a 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "saa7134-reg.h" #include "saa7134.h" @@ -84,7 +85,7 @@ MODULE_PARM_DESC(radio_nr, "radio device number"); MODULE_PARM_DESC(tuner, "tuner type"); MODULE_PARM_DESC(card, "card type"); -static DECLARE_MUTEX(devlist_lock); +static DEFINE_MUTEX(devlist_lock); LIST_HEAD(saa7134_devlist); static LIST_HEAD(mops_list); static unsigned int saa7134_devcount; @@ -969,13 +970,13 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, pci_set_drvdata(pci_dev,dev); saa7134_devcount++; - down(&devlist_lock); + mutex_lock(&devlist_lock); list_for_each(item,&mops_list) { mops = list_entry(item, struct saa7134_mpeg_ops, next); mpeg_ops_attach(mops, dev); } list_add_tail(&dev->devlist,&saa7134_devlist); - up(&devlist_lock); + mutex_unlock(&devlist_lock); /* check for signal */ saa7134_irq_video_intl(dev); @@ -1031,13 +1032,13 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) saa7134_hwfini(dev); /* unregister */ - down(&devlist_lock); + mutex_lock(&devlist_lock); list_del(&dev->devlist); list_for_each(item,&mops_list) { mops = list_entry(item, struct saa7134_mpeg_ops, next); mpeg_ops_detach(mops, dev); } - up(&devlist_lock); + mutex_unlock(&devlist_lock); saa7134_devcount--; saa7134_i2c_unregister(dev); @@ -1071,13 +1072,13 @@ int saa7134_ts_register(struct saa7134_mpeg_ops *ops) struct list_head *item; struct saa7134_dev *dev; - down(&devlist_lock); + mutex_lock(&devlist_lock); list_for_each(item,&saa7134_devlist) { dev = list_entry(item, struct saa7134_dev, devlist); mpeg_ops_attach(ops, dev); } list_add_tail(&ops->next,&mops_list); - up(&devlist_lock); + mutex_unlock(&devlist_lock); return 0; } @@ -1086,13 +1087,13 @@ void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops) struct list_head *item; struct saa7134_dev *dev; - down(&devlist_lock); + mutex_lock(&devlist_lock); list_del(&ops->next); list_for_each(item,&saa7134_devlist) { dev = list_entry(item, struct saa7134_dev, devlist); mpeg_ops_detach(ops, dev); } - up(&devlist_lock); + mutex_unlock(&devlist_lock); } EXPORT_SYMBOL(saa7134_ts_register); diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index d5be2598714..078880e4c8c 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -29,7 +29,6 @@ #include #include #include -#include #include @@ -83,7 +82,7 @@ static struct class video_class = { */ static struct video_device *video_device[VIDEO_NUM_DEVICES]; -static DECLARE_MUTEX(videodev_lock); +static DEFINE_MUTEX(videodev_lock); struct video_device* video_devdata(struct file *file) { @@ -102,15 +101,15 @@ static int video_open(struct inode *inode, struct file *file) if(minor>=VIDEO_NUM_DEVICES) return -ENODEV; - down(&videodev_lock); + mutex_lock(&videodev_lock); vfl=video_device[minor]; if(vfl==NULL) { - up(&videodev_lock); + mutex_unlock(&videodev_lock); request_module("char-major-%d-%d", VIDEO_MAJOR, minor); - down(&videodev_lock); + mutex_lock(&videodev_lock); vfl=video_device[minor]; if (vfl==NULL) { - up(&videodev_lock); + mutex_unlock(&videodev_lock); return -ENODEV; } } @@ -123,7 +122,7 @@ static int video_open(struct inode *inode, struct file *file) file->f_op = fops_get(old_fops); } fops_put(old_fops); - up(&videodev_lock); + mutex_unlock(&videodev_lock); return err; } @@ -304,12 +303,12 @@ int video_register_device(struct video_device *vfd, int type, int nr) } /* pick a minor number */ - down(&videodev_lock); + mutex_lock(&videodev_lock); if (nr >= 0 && nr < end-base) { /* use the one the driver asked for */ i = base+nr; if (NULL != video_device[i]) { - up(&videodev_lock); + mutex_unlock(&videodev_lock); return -ENFILE; } } else { @@ -318,13 +317,13 @@ int video_register_device(struct video_device *vfd, int type, int nr) if (NULL == video_device[i]) break; if (i == end) { - up(&videodev_lock); + mutex_unlock(&videodev_lock); return -ENFILE; } } video_device[i]=vfd; vfd->minor=i; - up(&videodev_lock); + mutex_unlock(&videodev_lock); sprintf(vfd->devfs_name, "v4l/%s%d", name_base, i - base); devfs_mk_cdev(MKDEV(VIDEO_MAJOR, vfd->minor), @@ -362,14 +361,14 @@ int video_register_device(struct video_device *vfd, int type, int nr) void video_unregister_device(struct video_device *vfd) { - down(&videodev_lock); + mutex_lock(&videodev_lock); if(video_device[vfd->minor]!=vfd) panic("videodev: bad unregister"); devfs_remove(vfd->devfs_name); video_device[vfd->minor]=NULL; class_device_unregister(&vfd->class_dev); - up(&videodev_lock); + mutex_unlock(&videodev_lock); } -- GitLab From fabd23862ba34f217f154c225c59eb5267c4a5d1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 15 Jan 2006 08:12:14 -0200 Subject: [PATCH 321/465] V4L/DVB (3381): Fix compilation with Alpha - BOOT_SIZE name is also used at alpha and were breaking compiling with allyesconfig. - All BOOT_* renamed to AV7110_BOOT* to fix and keep names with the same style. Thanks to Andrew Morton for pointing this. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/av7110_hw.c | 40 ++++++++++++++--------------- drivers/media/dvb/ttpci/av7110_hw.h | 12 ++++----- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c index cb377452b57..b2e63e9fc05 100644 --- a/drivers/media/dvb/ttpci/av7110_hw.c +++ b/drivers/media/dvb/ttpci/av7110_hw.c @@ -146,52 +146,52 @@ static int load_dram(struct av7110 *av7110, u32 *data, int len) { int i; int blocks, rest; - u32 base, bootblock = BOOT_BLOCK; + u32 base, bootblock = AV7110_BOOT_BLOCK; dprintk(4, "%p\n", av7110); - blocks = len / BOOT_MAX_SIZE; - rest = len % BOOT_MAX_SIZE; + blocks = len / AV7110_BOOT_MAX_SIZE; + rest = len % AV7110_BOOT_MAX_SIZE; base = DRAM_START_CODE; for (i = 0; i < blocks; i++) { - if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) { + if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) { printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at block %d\n", i); return -ETIMEDOUT; } dprintk(4, "writing DRAM block %d\n", i); mwdebi(av7110, DEBISWAB, bootblock, - ((char*)data) + i * BOOT_MAX_SIZE, BOOT_MAX_SIZE); + ((char*)data) + i * AV7110_BOOT_MAX_SIZE, AV7110_BOOT_MAX_SIZE); bootblock ^= 0x1400; - iwdebi(av7110, DEBISWAB, BOOT_BASE, swab32(base), 4); - iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, BOOT_MAX_SIZE, 2); - iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2); - base += BOOT_MAX_SIZE; + iwdebi(av7110, DEBISWAB, AV7110_BOOT_BASE, swab32(base), 4); + iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, AV7110_BOOT_MAX_SIZE, 2); + iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2); + base += AV7110_BOOT_MAX_SIZE; } if (rest > 0) { - if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) { + if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) { printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at last block\n"); return -ETIMEDOUT; } if (rest > 4) mwdebi(av7110, DEBISWAB, bootblock, - ((char*)data) + i * BOOT_MAX_SIZE, rest); + ((char*)data) + i * AV7110_BOOT_MAX_SIZE, rest); else mwdebi(av7110, DEBISWAB, bootblock, - ((char*)data) + i * BOOT_MAX_SIZE - 4, rest + 4); + ((char*)data) + i * AV7110_BOOT_MAX_SIZE - 4, rest + 4); - iwdebi(av7110, DEBISWAB, BOOT_BASE, swab32(base), 4); - iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, rest, 2); - iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2); + iwdebi(av7110, DEBISWAB, AV7110_BOOT_BASE, swab32(base), 4); + iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, rest, 2); + iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2); } - if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) { + if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) { printk(KERN_ERR "dvb-ttpci: load_dram(): timeout after last block\n"); return -ETIMEDOUT; } - iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, 0, 2); - iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2); - if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BOOT_COMPLETE) < 0) { + iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, 0, 2); + iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2); + if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_AV7110_BOOT_COMPLETE) < 0) { printk(KERN_ERR "dvb-ttpci: load_dram(): final handshake timeout\n"); return -ETIMEDOUT; } @@ -262,7 +262,7 @@ int av7110_bootarm(struct av7110 *av7110) //saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT); mwdebi(av7110, DEBISWAB, DPRAM_BASE, bootcode, sizeof(bootcode)); - iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2); + iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2); if (saa7146_wait_for_debi_done(av7110->dev, 1)) { printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): " diff --git a/drivers/media/dvb/ttpci/av7110_hw.h b/drivers/media/dvb/ttpci/av7110_hw.h index 84b83299b8b..4e173c67fbb 100644 --- a/drivers/media/dvb/ttpci/av7110_hw.h +++ b/drivers/media/dvb/ttpci/av7110_hw.h @@ -18,7 +18,7 @@ enum av7110_bootstate { BOOTSTATE_BUFFER_EMPTY = 0, BOOTSTATE_BUFFER_FULL = 1, - BOOTSTATE_BOOT_COMPLETE = 2 + BOOTSTATE_AV7110_BOOT_COMPLETE = 2 }; enum av7110_type_rec_play_format @@ -295,11 +295,11 @@ enum av7110_command_type { #define DPRAM_BASE 0x4000 /* boot protocol area */ -#define BOOT_STATE (DPRAM_BASE + 0x3F8) -#define BOOT_SIZE (DPRAM_BASE + 0x3FA) -#define BOOT_BASE (DPRAM_BASE + 0x3FC) -#define BOOT_BLOCK (DPRAM_BASE + 0x400) -#define BOOT_MAX_SIZE 0xc00 +#define AV7110_BOOT_STATE (DPRAM_BASE + 0x3F8) +#define AV7110_BOOT_SIZE (DPRAM_BASE + 0x3FA) +#define AV7110_BOOT_BASE (DPRAM_BASE + 0x3FC) +#define AV7110_BOOT_BLOCK (DPRAM_BASE + 0x400) +#define AV7110_BOOT_MAX_SIZE 0xc00 /* firmware command protocol area */ #define IRQ_STATE (DPRAM_BASE + 0x0F4) -- GitLab From e05b3b4adbaeea508bd1c195f1f2e22c8251176b Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sun, 15 Jan 2006 22:05:47 +1100 Subject: [PATCH 322/465] powerpc/32: Restore previous version of 32-bit PCI code When I removed the powermac support from arch/ppc/kernel/pci.c, I overlooked the fact that that file is used in 32-bit ARCH=powerpc builds. To prevent problems in future, restore the original version of that file as arch/powerpc/kernel/pci_32.c, and use that. Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/Makefile | 3 +- arch/powerpc/kernel/pci_32.c | 1897 ++++++++++++++++++++++++++++++++++ arch/ppc/kernel/Makefile | 1 - 3 files changed, 1899 insertions(+), 2 deletions(-) create mode 100644 arch/powerpc/kernel/pci_32.c diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index a94699d8dc5..c287980b7e6 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -60,7 +60,8 @@ obj-$(CONFIG_MODULES) += $(module-y) pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o pci_iommu.o \ pci_direct_iommu.o iomap.o -obj-$(CONFIG_PCI) += $(pci64-y) +pci32-$(CONFIG_PPC32) := pci_32.o +obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y) kexec-$(CONFIG_PPC64) := machine_kexec_64.o crash.o kexec-$(CONFIG_PPC32) := machine_kexec_32.o obj-$(CONFIG_KEXEC) += machine_kexec.o $(kexec-y) diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c new file mode 100644 index 00000000000..704c846b2b0 --- /dev/null +++ b/arch/powerpc/kernel/pci_32.c @@ -0,0 +1,1897 @@ +/* + * Common pmac/prep/chrp pci routines. -- Cort + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG + +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +unsigned long pci_dram_offset = 0; +int pcibios_assign_bus_offset = 1; + +void pcibios_make_OF_bus_map(void); + +static int pci_relocate_bridge_resource(struct pci_bus *bus, int i); +static int probe_resource(struct pci_bus *parent, struct resource *pr, + struct resource *res, struct resource **conflict); +static void update_bridge_base(struct pci_bus *bus, int i); +static void pcibios_fixup_resources(struct pci_dev* dev); +static void fixup_broken_pcnet32(struct pci_dev* dev); +static int reparent_resources(struct resource *parent, struct resource *res); +static void fixup_cpc710_pci64(struct pci_dev* dev); +#ifdef CONFIG_PPC_OF +static u8* pci_to_OF_bus_map; +#endif + +/* By default, we don't re-assign bus numbers. We do this only on + * some pmacs + */ +int pci_assign_all_buses; + +struct pci_controller* hose_head; +struct pci_controller** hose_tail = &hose_head; + +static int pci_bus_count; + +static void +fixup_broken_pcnet32(struct pci_dev* dev) +{ + if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) { + dev->vendor = PCI_VENDOR_ID_AMD; + pci_write_config_word(dev, PCI_VENDOR_ID, PCI_VENDOR_ID_AMD); + } +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32); + +static void +fixup_cpc710_pci64(struct pci_dev* dev) +{ + /* Hide the PCI64 BARs from the kernel as their content doesn't + * fit well in the resource management + */ + dev->resource[0].start = dev->resource[0].end = 0; + dev->resource[0].flags = 0; + dev->resource[1].start = dev->resource[1].end = 0; + dev->resource[1].flags = 0; +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CPC710_PCI64, fixup_cpc710_pci64); + +static void +pcibios_fixup_resources(struct pci_dev *dev) +{ + struct pci_controller* hose = (struct pci_controller *)dev->sysdata; + int i; + unsigned long offset; + + if (!hose) { + printk(KERN_ERR "No hose for PCI dev %s!\n", pci_name(dev)); + return; + } + for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { + struct resource *res = dev->resource + i; + if (!res->flags) + continue; + if (res->end == 0xffffffff) { + DBG("PCI:%s Resource %d [%08lx-%08lx] is unassigned\n", + pci_name(dev), i, res->start, res->end); + res->end -= res->start; + res->start = 0; + res->flags |= IORESOURCE_UNSET; + continue; + } + offset = 0; + if (res->flags & IORESOURCE_MEM) { + offset = hose->pci_mem_offset; + } else if (res->flags & IORESOURCE_IO) { + offset = (unsigned long) hose->io_base_virt + - isa_io_base; + } + if (offset != 0) { + res->start += offset; + res->end += offset; +#ifdef DEBUG + printk("Fixup res %d (%lx) of dev %s: %lx -> %lx\n", + i, res->flags, pci_name(dev), + res->start - offset, res->start); +#endif + } + } + + /* Call machine specific resource fixup */ + if (ppc_md.pcibios_fixup_resources) + ppc_md.pcibios_fixup_resources(dev); +} +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources); + +void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, + struct resource *res) +{ + unsigned long offset = 0; + struct pci_controller *hose = dev->sysdata; + + if (hose && res->flags & IORESOURCE_IO) + offset = (unsigned long)hose->io_base_virt - isa_io_base; + else if (hose && res->flags & IORESOURCE_MEM) + offset = hose->pci_mem_offset; + region->start = res->start - offset; + region->end = res->end - offset; +} +EXPORT_SYMBOL(pcibios_resource_to_bus); + +void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, + struct pci_bus_region *region) +{ + unsigned long offset = 0; + struct pci_controller *hose = dev->sysdata; + + if (hose && res->flags & IORESOURCE_IO) + offset = (unsigned long)hose->io_base_virt - isa_io_base; + else if (hose && res->flags & IORESOURCE_MEM) + offset = hose->pci_mem_offset; + res->start = region->start + offset; + res->end = region->end + offset; +} +EXPORT_SYMBOL(pcibios_bus_to_resource); + +/* + * We need to avoid collisions with `mirrored' VGA ports + * and other strange ISA hardware, so we always want the + * addresses to be allocated in the 0x000-0x0ff region + * modulo 0x400. + * + * Why? Because some silly external IO cards only decode + * the low 10 bits of the IO address. The 0x00-0xff region + * is reserved for motherboard devices that decode all 16 + * bits, so it's ok to allocate at, say, 0x2800-0x28ff, + * but we want to try to avoid allocating at 0x2900-0x2bff + * which might have be mirrored at 0x0100-0x03ff.. + */ +void pcibios_align_resource(void *data, struct resource *res, unsigned long size, + unsigned long align) +{ + struct pci_dev *dev = data; + + if (res->flags & IORESOURCE_IO) { + unsigned long start = res->start; + + if (size > 0x100) { + printk(KERN_ERR "PCI: I/O Region %s/%d too large" + " (%ld bytes)\n", pci_name(dev), + dev->resource - res, size); + } + + if (start & 0x300) { + start = (start + 0x3ff) & ~0x3ff; + res->start = start; + } + } +} +EXPORT_SYMBOL(pcibios_align_resource); + +/* + * Handle resources of PCI devices. If the world were perfect, we could + * just allocate all the resource regions and do nothing more. It isn't. + * On the other hand, we cannot just re-allocate all devices, as it would + * require us to know lots of host bridge internals. So we attempt to + * keep as much of the original configuration as possible, but tweak it + * when it's found to be wrong. + * + * Known BIOS problems we have to work around: + * - I/O or memory regions not configured + * - regions configured, but not enabled in the command register + * - bogus I/O addresses above 64K used + * - expansion ROMs left enabled (this may sound harmless, but given + * the fact the PCI specs explicitly allow address decoders to be + * shared between expansion ROMs and other resource regions, it's + * at least dangerous) + * + * Our solution: + * (1) Allocate resources for all buses behind PCI-to-PCI bridges. + * This gives us fixed barriers on where we can allocate. + * (2) Allocate resources for all enabled devices. If there is + * a collision, just mark the resource as unallocated. Also + * disable expansion ROMs during this step. + * (3) Try to allocate resources for disabled devices. If the + * resources were assigned correctly, everything goes well, + * if they weren't, they won't disturb allocation of other + * resources. + * (4) Assign new addresses to resources which were either + * not configured at all or misconfigured. If explicitly + * requested by the user, configure expansion ROM address + * as well. + */ + +static void __init +pcibios_allocate_bus_resources(struct list_head *bus_list) +{ + struct pci_bus *bus; + int i; + struct resource *res, *pr; + + /* Depth-First Search on bus tree */ + list_for_each_entry(bus, bus_list, node) { + for (i = 0; i < 4; ++i) { + if ((res = bus->resource[i]) == NULL || !res->flags + || res->start > res->end) + continue; + if (bus->parent == NULL) + pr = (res->flags & IORESOURCE_IO)? + &ioport_resource: &iomem_resource; + else { + pr = pci_find_parent_resource(bus->self, res); + if (pr == res) { + /* this happens when the generic PCI + * code (wrongly) decides that this + * bridge is transparent -- paulus + */ + continue; + } + } + + DBG("PCI: bridge rsrc %lx..%lx (%lx), parent %p\n", + res->start, res->end, res->flags, pr); + if (pr) { + if (request_resource(pr, res) == 0) + continue; + /* + * Must be a conflict with an existing entry. + * Move that entry (or entries) under the + * bridge resource and try again. + */ + if (reparent_resources(pr, res) == 0) + continue; + } + printk(KERN_ERR "PCI: Cannot allocate resource region " + "%d of PCI bridge %d\n", i, bus->number); + if (pci_relocate_bridge_resource(bus, i)) + bus->resource[i] = NULL; + } + pcibios_allocate_bus_resources(&bus->children); + } +} + +/* + * Reparent resource children of pr that conflict with res + * under res, and make res replace those children. + */ +static int __init +reparent_resources(struct resource *parent, struct resource *res) +{ + struct resource *p, **pp; + struct resource **firstpp = NULL; + + for (pp = &parent->child; (p = *pp) != NULL; pp = &p->sibling) { + if (p->end < res->start) + continue; + if (res->end < p->start) + break; + if (p->start < res->start || p->end > res->end) + return -1; /* not completely contained */ + if (firstpp == NULL) + firstpp = pp; + } + if (firstpp == NULL) + return -1; /* didn't find any conflicting entries? */ + res->parent = parent; + res->child = *firstpp; + res->sibling = *pp; + *firstpp = res; + *pp = NULL; + for (p = res->child; p != NULL; p = p->sibling) { + p->parent = res; + DBG(KERN_INFO "PCI: reparented %s [%lx..%lx] under %s\n", + p->name, p->start, p->end, res->name); + } + return 0; +} + +/* + * A bridge has been allocated a range which is outside the range + * of its parent bridge, so it needs to be moved. + */ +static int __init +pci_relocate_bridge_resource(struct pci_bus *bus, int i) +{ + struct resource *res, *pr, *conflict; + unsigned long try, size; + int j; + struct pci_bus *parent = bus->parent; + + if (parent == NULL) { + /* shouldn't ever happen */ + printk(KERN_ERR "PCI: can't move host bridge resource\n"); + return -1; + } + res = bus->resource[i]; + if (res == NULL) + return -1; + pr = NULL; + for (j = 0; j < 4; j++) { + struct resource *r = parent->resource[j]; + if (!r) + continue; + if ((res->flags ^ r->flags) & (IORESOURCE_IO | IORESOURCE_MEM)) + continue; + if (!((res->flags ^ r->flags) & IORESOURCE_PREFETCH)) { + pr = r; + break; + } + if (res->flags & IORESOURCE_PREFETCH) + pr = r; + } + if (pr == NULL) + return -1; + size = res->end - res->start; + if (pr->start > pr->end || size > pr->end - pr->start) + return -1; + try = pr->end; + for (;;) { + res->start = try - size; + res->end = try; + if (probe_resource(bus->parent, pr, res, &conflict) == 0) + break; + if (conflict->start <= pr->start + size) + return -1; + try = conflict->start - 1; + } + if (request_resource(pr, res)) { + DBG(KERN_ERR "PCI: huh? couldn't move to %lx..%lx\n", + res->start, res->end); + return -1; /* "can't happen" */ + } + update_bridge_base(bus, i); + printk(KERN_INFO "PCI: bridge %d resource %d moved to %lx..%lx\n", + bus->number, i, res->start, res->end); + return 0; +} + +static int __init +probe_resource(struct pci_bus *parent, struct resource *pr, + struct resource *res, struct resource **conflict) +{ + struct pci_bus *bus; + struct pci_dev *dev; + struct resource *r; + int i; + + for (r = pr->child; r != NULL; r = r->sibling) { + if (r->end >= res->start && res->end >= r->start) { + *conflict = r; + return 1; + } + } + list_for_each_entry(bus, &parent->children, node) { + for (i = 0; i < 4; ++i) { + if ((r = bus->resource[i]) == NULL) + continue; + if (!r->flags || r->start > r->end || r == res) + continue; + if (pci_find_parent_resource(bus->self, r) != pr) + continue; + if (r->end >= res->start && res->end >= r->start) { + *conflict = r; + return 1; + } + } + } + list_for_each_entry(dev, &parent->devices, bus_list) { + for (i = 0; i < 6; ++i) { + r = &dev->resource[i]; + if (!r->flags || (r->flags & IORESOURCE_UNSET)) + continue; + if (pci_find_parent_resource(dev, r) != pr) + continue; + if (r->end >= res->start && res->end >= r->start) { + *conflict = r; + return 1; + } + } + } + return 0; +} + +static void __init +update_bridge_base(struct pci_bus *bus, int i) +{ + struct resource *res = bus->resource[i]; + u8 io_base_lo, io_limit_lo; + u16 mem_base, mem_limit; + u16 cmd; + unsigned long start, end, off; + struct pci_dev *dev = bus->self; + struct pci_controller *hose = dev->sysdata; + + if (!hose) { + printk("update_bridge_base: no hose?\n"); + return; + } + pci_read_config_word(dev, PCI_COMMAND, &cmd); + pci_write_config_word(dev, PCI_COMMAND, + cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY)); + if (res->flags & IORESOURCE_IO) { + off = (unsigned long) hose->io_base_virt - isa_io_base; + start = res->start - off; + end = res->end - off; + io_base_lo = (start >> 8) & PCI_IO_RANGE_MASK; + io_limit_lo = (end >> 8) & PCI_IO_RANGE_MASK; + if (end > 0xffff) { + pci_write_config_word(dev, PCI_IO_BASE_UPPER16, + start >> 16); + pci_write_config_word(dev, PCI_IO_LIMIT_UPPER16, + end >> 16); + io_base_lo |= PCI_IO_RANGE_TYPE_32; + } else + io_base_lo |= PCI_IO_RANGE_TYPE_16; + pci_write_config_byte(dev, PCI_IO_BASE, io_base_lo); + pci_write_config_byte(dev, PCI_IO_LIMIT, io_limit_lo); + + } else if ((res->flags & (IORESOURCE_MEM | IORESOURCE_PREFETCH)) + == IORESOURCE_MEM) { + off = hose->pci_mem_offset; + mem_base = ((res->start - off) >> 16) & PCI_MEMORY_RANGE_MASK; + mem_limit = ((res->end - off) >> 16) & PCI_MEMORY_RANGE_MASK; + pci_write_config_word(dev, PCI_MEMORY_BASE, mem_base); + pci_write_config_word(dev, PCI_MEMORY_LIMIT, mem_limit); + + } else if ((res->flags & (IORESOURCE_MEM | IORESOURCE_PREFETCH)) + == (IORESOURCE_MEM | IORESOURCE_PREFETCH)) { + off = hose->pci_mem_offset; + mem_base = ((res->start - off) >> 16) & PCI_PREF_RANGE_MASK; + mem_limit = ((res->end - off) >> 16) & PCI_PREF_RANGE_MASK; + pci_write_config_word(dev, PCI_PREF_MEMORY_BASE, mem_base); + pci_write_config_word(dev, PCI_PREF_MEMORY_LIMIT, mem_limit); + + } else { + DBG(KERN_ERR "PCI: ugh, bridge %s res %d has flags=%lx\n", + pci_name(dev), i, res->flags); + } + pci_write_config_word(dev, PCI_COMMAND, cmd); +} + +static inline void alloc_resource(struct pci_dev *dev, int idx) +{ + struct resource *pr, *r = &dev->resource[idx]; + + DBG("PCI:%s: Resource %d: %08lx-%08lx (f=%lx)\n", + pci_name(dev), idx, r->start, r->end, r->flags); + pr = pci_find_parent_resource(dev, r); + if (!pr || request_resource(pr, r) < 0) { + printk(KERN_ERR "PCI: Cannot allocate resource region %d" + " of device %s\n", idx, pci_name(dev)); + if (pr) + DBG("PCI: parent is %p: %08lx-%08lx (f=%lx)\n", + pr, pr->start, pr->end, pr->flags); + /* We'll assign a new address later */ + r->flags |= IORESOURCE_UNSET; + r->end -= r->start; + r->start = 0; + } +} + +static void __init +pcibios_allocate_resources(int pass) +{ + struct pci_dev *dev = NULL; + int idx, disabled; + u16 command; + struct resource *r; + + for_each_pci_dev(dev) { + pci_read_config_word(dev, PCI_COMMAND, &command); + for (idx = 0; idx < 6; idx++) { + r = &dev->resource[idx]; + if (r->parent) /* Already allocated */ + continue; + if (!r->flags || (r->flags & IORESOURCE_UNSET)) + continue; /* Not assigned at all */ + if (r->flags & IORESOURCE_IO) + disabled = !(command & PCI_COMMAND_IO); + else + disabled = !(command & PCI_COMMAND_MEMORY); + if (pass == disabled) + alloc_resource(dev, idx); + } + if (pass) + continue; + r = &dev->resource[PCI_ROM_RESOURCE]; + if (r->flags & IORESOURCE_ROM_ENABLE) { + /* Turn the ROM off, leave the resource region, but keep it unregistered. */ + u32 reg; + DBG("PCI: Switching off ROM of %s\n", pci_name(dev)); + r->flags &= ~IORESOURCE_ROM_ENABLE; + pci_read_config_dword(dev, dev->rom_base_reg, ®); + pci_write_config_dword(dev, dev->rom_base_reg, + reg & ~PCI_ROM_ADDRESS_ENABLE); + } + } +} + +static void __init +pcibios_assign_resources(void) +{ + struct pci_dev *dev = NULL; + int idx; + struct resource *r; + + for_each_pci_dev(dev) { + int class = dev->class >> 8; + + /* Don't touch classless devices and host bridges */ + if (!class || class == PCI_CLASS_BRIDGE_HOST) + continue; + + for (idx = 0; idx < 6; idx++) { + r = &dev->resource[idx]; + + /* + * We shall assign a new address to this resource, + * either because the BIOS (sic) forgot to do so + * or because we have decided the old address was + * unusable for some reason. + */ + if ((r->flags & IORESOURCE_UNSET) && r->end && + (!ppc_md.pcibios_enable_device_hook || + !ppc_md.pcibios_enable_device_hook(dev, 1))) { + r->flags &= ~IORESOURCE_UNSET; + pci_assign_resource(dev, idx); + } + } + +#if 0 /* don't assign ROMs */ + r = &dev->resource[PCI_ROM_RESOURCE]; + r->end -= r->start; + r->start = 0; + if (r->end) + pci_assign_resource(dev, PCI_ROM_RESOURCE); +#endif + } +} + + +int +pcibios_enable_resources(struct pci_dev *dev, int mask) +{ + u16 cmd, old_cmd; + int idx; + struct resource *r; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + old_cmd = cmd; + for (idx=0; idx<6; idx++) { + /* Only set up the requested stuff */ + if (!(mask & (1<resource[idx]; + if (r->flags & IORESOURCE_UNSET) { + printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev)); + return -EINVAL; + } + if (r->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (r->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + if (dev->resource[PCI_ROM_RESOURCE].start) + cmd |= PCI_COMMAND_MEMORY; + if (cmd != old_cmd) { + printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd); + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + return 0; +} + +static int next_controller_index; + +struct pci_controller * __init +pcibios_alloc_controller(void) +{ + struct pci_controller *hose; + + hose = (struct pci_controller *)alloc_bootmem(sizeof(*hose)); + memset(hose, 0, sizeof(struct pci_controller)); + + *hose_tail = hose; + hose_tail = &hose->next; + + hose->index = next_controller_index++; + + return hose; +} + +#ifdef CONFIG_PPC_OF +/* + * Functions below are used on OpenFirmware machines. + */ +static void +make_one_node_map(struct device_node* node, u8 pci_bus) +{ + int *bus_range; + int len; + + if (pci_bus >= pci_bus_count) + return; + bus_range = (int *) get_property(node, "bus-range", &len); + if (bus_range == NULL || len < 2 * sizeof(int)) { + printk(KERN_WARNING "Can't get bus-range for %s, " + "assuming it starts at 0\n", node->full_name); + pci_to_OF_bus_map[pci_bus] = 0; + } else + pci_to_OF_bus_map[pci_bus] = bus_range[0]; + + for (node=node->child; node != 0;node = node->sibling) { + struct pci_dev* dev; + unsigned int *class_code, *reg; + + class_code = (unsigned int *) get_property(node, "class-code", NULL); + if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI && + (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) + continue; + reg = (unsigned int *)get_property(node, "reg", NULL); + if (!reg) + continue; + dev = pci_find_slot(pci_bus, ((reg[0] >> 8) & 0xff)); + if (!dev || !dev->subordinate) + continue; + make_one_node_map(node, dev->subordinate->number); + } +} + +void +pcibios_make_OF_bus_map(void) +{ + int i; + struct pci_controller* hose; + u8* of_prop_map; + + pci_to_OF_bus_map = (u8*)kmalloc(pci_bus_count, GFP_KERNEL); + if (!pci_to_OF_bus_map) { + printk(KERN_ERR "Can't allocate OF bus map !\n"); + return; + } + + /* We fill the bus map with invalid values, that helps + * debugging. + */ + for (i=0; inext) { + struct device_node* node; + node = (struct device_node *)hose->arch_data; + if (!node) + continue; + make_one_node_map(node, hose->first_busno); + } + of_prop_map = get_property(find_path_device("/"), "pci-OF-bus-map", NULL); + if (of_prop_map) + memcpy(of_prop_map, pci_to_OF_bus_map, pci_bus_count); +#ifdef DEBUG + printk("PCI->OF bus map:\n"); + for (i=0; i %d\n", i, pci_to_OF_bus_map[i]); + } +#endif +} + +typedef int (*pci_OF_scan_iterator)(struct device_node* node, void* data); + +static struct device_node* +scan_OF_pci_childs(struct device_node* node, pci_OF_scan_iterator filter, void* data) +{ + struct device_node* sub_node; + + for (; node != 0;node = node->sibling) { + unsigned int *class_code; + + if (filter(node, data)) + return node; + + /* For PCI<->PCI bridges or CardBus bridges, we go down + * Note: some OFs create a parent node "multifunc-device" as + * a fake root for all functions of a multi-function device, + * we go down them as well. + */ + class_code = (unsigned int *) get_property(node, "class-code", NULL); + if ((!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI && + (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) && + strcmp(node->name, "multifunc-device")) + continue; + sub_node = scan_OF_pci_childs(node->child, filter, data); + if (sub_node) + return sub_node; + } + return NULL; +} + +static int +scan_OF_pci_childs_iterator(struct device_node* node, void* data) +{ + unsigned int *reg; + u8* fdata = (u8*)data; + + reg = (unsigned int *) get_property(node, "reg", NULL); + if (reg && ((reg[0] >> 8) & 0xff) == fdata[1] + && ((reg[0] >> 16) & 0xff) == fdata[0]) + return 1; + return 0; +} + +static struct device_node* +scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn) +{ + u8 filter_data[2] = {bus, dev_fn}; + + return scan_OF_pci_childs(node, scan_OF_pci_childs_iterator, filter_data); +} + +/* + * Scans the OF tree for a device node matching a PCI device + */ +struct device_node * +pci_busdev_to_OF_node(struct pci_bus *bus, int devfn) +{ + struct pci_controller *hose; + struct device_node *node; + int busnr; + + if (!have_of) + return NULL; + + /* Lookup the hose */ + busnr = bus->number; + hose = pci_bus_to_hose(busnr); + if (!hose) + return NULL; + + /* Check it has an OF node associated */ + node = (struct device_node *) hose->arch_data; + if (!node) + return NULL; + + /* Fixup bus number according to what OF think it is. */ +#ifdef CONFIG_PPC_PMAC + /* The G5 need a special case here. Basically, we don't remap all + * busses on it so we don't create the pci-OF-map. However, we do + * remap the AGP bus and so have to deal with it. A future better + * fix has to be done by making the remapping per-host and always + * filling the pci_to_OF map. --BenH + */ + if (_machine == _MACH_Pmac && busnr >= 0xf0) + busnr -= 0xf0; + else +#endif + if (pci_to_OF_bus_map) + busnr = pci_to_OF_bus_map[busnr]; + if (busnr == 0xff) + return NULL; + + /* Now, lookup childs of the hose */ + return scan_OF_childs_for_device(node->child, busnr, devfn); +} +EXPORT_SYMBOL(pci_busdev_to_OF_node); + +struct device_node* +pci_device_to_OF_node(struct pci_dev *dev) +{ + return pci_busdev_to_OF_node(dev->bus, dev->devfn); +} +EXPORT_SYMBOL(pci_device_to_OF_node); + +/* This routine is meant to be used early during boot, when the + * PCI bus numbers have not yet been assigned, and you need to + * issue PCI config cycles to an OF device. + * It could also be used to "fix" RTAS config cycles if you want + * to set pci_assign_all_buses to 1 and still use RTAS for PCI + * config cycles. + */ +struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node) +{ + if (!have_of) + return NULL; + while(node) { + struct pci_controller* hose; + for (hose=hose_head;hose;hose=hose->next) + if (hose->arch_data == node) + return hose; + node=node->parent; + } + return NULL; +} + +static int +find_OF_pci_device_filter(struct device_node* node, void* data) +{ + return ((void *)node == data); +} + +/* + * Returns the PCI device matching a given OF node + */ +int +pci_device_from_OF_node(struct device_node* node, u8* bus, u8* devfn) +{ + unsigned int *reg; + struct pci_controller* hose; + struct pci_dev* dev = NULL; + + if (!have_of) + return -ENODEV; + /* Make sure it's really a PCI device */ + hose = pci_find_hose_for_OF_device(node); + if (!hose || !hose->arch_data) + return -ENODEV; + if (!scan_OF_pci_childs(((struct device_node*)hose->arch_data)->child, + find_OF_pci_device_filter, (void *)node)) + return -ENODEV; + reg = (unsigned int *) get_property(node, "reg", NULL); + if (!reg) + return -ENODEV; + *bus = (reg[0] >> 16) & 0xff; + *devfn = ((reg[0] >> 8) & 0xff); + + /* Ok, here we need some tweak. If we have already renumbered + * all busses, we can't rely on the OF bus number any more. + * the pci_to_OF_bus_map is not enough as several PCI busses + * may match the same OF bus number. + */ + if (!pci_to_OF_bus_map) + return 0; + + for_each_pci_dev(dev) + if (pci_to_OF_bus_map[dev->bus->number] == *bus && + dev->devfn == *devfn) { + *bus = dev->bus->number; + pci_dev_put(dev); + return 0; + } + + return -ENODEV; +} +EXPORT_SYMBOL(pci_device_from_OF_node); + +void __init +pci_process_bridge_OF_ranges(struct pci_controller *hose, + struct device_node *dev, int primary) +{ + static unsigned int static_lc_ranges[256] __initdata; + unsigned int *dt_ranges, *lc_ranges, *ranges, *prev; + unsigned int size; + int rlen = 0, orig_rlen; + int memno = 0; + struct resource *res; + int np, na = prom_n_addr_cells(dev); + np = na + 5; + + /* First we try to merge ranges to fix a problem with some pmacs + * that can have more than 3 ranges, fortunately using contiguous + * addresses -- BenH + */ + dt_ranges = (unsigned int *) get_property(dev, "ranges", &rlen); + if (!dt_ranges) + return; + /* Sanity check, though hopefully that never happens */ + if (rlen > sizeof(static_lc_ranges)) { + printk(KERN_WARNING "OF ranges property too large !\n"); + rlen = sizeof(static_lc_ranges); + } + lc_ranges = static_lc_ranges; + memcpy(lc_ranges, dt_ranges, rlen); + orig_rlen = rlen; + + /* Let's work on a copy of the "ranges" property instead of damaging + * the device-tree image in memory + */ + ranges = lc_ranges; + prev = NULL; + while ((rlen -= np * sizeof(unsigned int)) >= 0) { + if (prev) { + if (prev[0] == ranges[0] && prev[1] == ranges[1] && + (prev[2] + prev[na+4]) == ranges[2] && + (prev[na+2] + prev[na+4]) == ranges[na+2]) { + prev[na+4] += ranges[na+4]; + ranges[0] = 0; + ranges += np; + continue; + } + } + prev = ranges; + ranges += np; + } + + /* + * The ranges property is laid out as an array of elements, + * each of which comprises: + * cells 0 - 2: a PCI address + * cells 3 or 3+4: a CPU physical address + * (size depending on dev->n_addr_cells) + * cells 4+5 or 5+6: the size of the range + */ + ranges = lc_ranges; + rlen = orig_rlen; + while (ranges && (rlen -= np * sizeof(unsigned int)) >= 0) { + res = NULL; + size = ranges[na+4]; + switch ((ranges[0] >> 24) & 0x3) { + case 1: /* I/O space */ + if (ranges[2] != 0) + break; + hose->io_base_phys = ranges[na+2]; + /* limit I/O space to 16MB */ + if (size > 0x01000000) + size = 0x01000000; + hose->io_base_virt = ioremap(ranges[na+2], size); + if (primary) + isa_io_base = (unsigned long) hose->io_base_virt; + res = &hose->io_resource; + res->flags = IORESOURCE_IO; + res->start = ranges[2]; + DBG("PCI: IO 0x%lx -> 0x%lx\n", + res->start, res->start + size - 1); + break; + case 2: /* memory space */ + memno = 0; + if (ranges[1] == 0 && ranges[2] == 0 + && ranges[na+4] <= (16 << 20)) { + /* 1st 16MB, i.e. ISA memory area */ + if (primary) + isa_mem_base = ranges[na+2]; + memno = 1; + } + while (memno < 3 && hose->mem_resources[memno].flags) + ++memno; + if (memno == 0) + hose->pci_mem_offset = ranges[na+2] - ranges[2]; + if (memno < 3) { + res = &hose->mem_resources[memno]; + res->flags = IORESOURCE_MEM; + if(ranges[0] & 0x40000000) + res->flags |= IORESOURCE_PREFETCH; + res->start = ranges[na+2]; + DBG("PCI: MEM[%d] 0x%lx -> 0x%lx\n", memno, + res->start, res->start + size - 1); + } + break; + } + if (res != NULL) { + res->name = dev->full_name; + res->end = res->start + size - 1; + res->parent = NULL; + res->sibling = NULL; + res->child = NULL; + } + ranges += np; + } +} + +/* We create the "pci-OF-bus-map" property now so it appears in the + * /proc device tree + */ +void __init +pci_create_OF_bus_map(void) +{ + struct property* of_prop; + + of_prop = (struct property*) alloc_bootmem(sizeof(struct property) + 256); + if (of_prop && find_path_device("/")) { + memset(of_prop, -1, sizeof(struct property) + 256); + of_prop->name = "pci-OF-bus-map"; + of_prop->length = 256; + of_prop->value = (unsigned char *)&of_prop[1]; + prom_add_property(find_path_device("/"), of_prop); + } +} + +static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct pci_dev *pdev; + struct device_node *np; + + pdev = to_pci_dev (dev); + np = pci_device_to_OF_node(pdev); + if (np == NULL || np->full_name == NULL) + return 0; + return sprintf(buf, "%s", np->full_name); +} +static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); + +#else /* CONFIG_PPC_OF */ +void pcibios_make_OF_bus_map(void) +{ +} +#endif /* CONFIG_PPC_OF */ + +/* Add sysfs properties */ +void pcibios_add_platform_entries(struct pci_dev *pdev) +{ +#ifdef CONFIG_PPC_OF + device_create_file(&pdev->dev, &dev_attr_devspec); +#endif /* CONFIG_PPC_OF */ +} + + +#ifdef CONFIG_PPC_PMAC +/* + * This set of routines checks for PCI<->PCI bridges that have closed + * IO resources and have child devices. It tries to re-open an IO + * window on them. + * + * This is a _temporary_ fix to workaround a problem with Apple's OF + * closing IO windows on P2P bridges when the OF drivers of cards + * below this bridge don't claim any IO range (typically ATI or + * Adaptec). + * + * A more complete fix would be to use drivers/pci/setup-bus.c, which + * involves a working pcibios_fixup_pbus_ranges(), some more care about + * ordering when creating the host bus resources, and maybe a few more + * minor tweaks + */ + +/* Initialize bridges with base/limit values we have collected */ +static void __init +do_update_p2p_io_resource(struct pci_bus *bus, int enable_vga) +{ + struct pci_dev *bridge = bus->self; + struct pci_controller* hose = (struct pci_controller *)bridge->sysdata; + u32 l; + u16 w; + struct resource res; + + if (bus->resource[0] == NULL) + return; + res = *(bus->resource[0]); + + DBG("Remapping Bus %d, bridge: %s\n", bus->number, pci_name(bridge)); + res.start -= ((unsigned long) hose->io_base_virt - isa_io_base); + res.end -= ((unsigned long) hose->io_base_virt - isa_io_base); + DBG(" IO window: %08lx-%08lx\n", res.start, res.end); + + /* Set up the top and bottom of the PCI I/O segment for this bus. */ + pci_read_config_dword(bridge, PCI_IO_BASE, &l); + l &= 0xffff000f; + l |= (res.start >> 8) & 0x00f0; + l |= res.end & 0xf000; + pci_write_config_dword(bridge, PCI_IO_BASE, l); + + if ((l & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) { + l = (res.start >> 16) | (res.end & 0xffff0000); + pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, l); + } + + pci_read_config_word(bridge, PCI_COMMAND, &w); + w |= PCI_COMMAND_IO; + pci_write_config_word(bridge, PCI_COMMAND, w); + +#if 0 /* Enabling this causes XFree 4.2.0 to hang during PCI probe */ + if (enable_vga) { + pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &w); + w |= PCI_BRIDGE_CTL_VGA; + pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, w); + } +#endif +} + +/* This function is pretty basic and actually quite broken for the + * general case, it's enough for us right now though. It's supposed + * to tell us if we need to open an IO range at all or not and what + * size. + */ +static int __init +check_for_io_childs(struct pci_bus *bus, struct resource* res, int *found_vga) +{ + struct pci_dev *dev; + int i; + int rc = 0; + +#define push_end(res, size) do { unsigned long __sz = (size) ; \ + res->end = ((res->end + __sz) / (__sz + 1)) * (__sz + 1) + __sz; \ + } while (0) + + list_for_each_entry(dev, &bus->devices, bus_list) { + u16 class = dev->class >> 8; + + if (class == PCI_CLASS_DISPLAY_VGA || + class == PCI_CLASS_NOT_DEFINED_VGA) + *found_vga = 1; + if (class >> 8 == PCI_BASE_CLASS_BRIDGE && dev->subordinate) + rc |= check_for_io_childs(dev->subordinate, res, found_vga); + if (class == PCI_CLASS_BRIDGE_CARDBUS) + push_end(res, 0xfff); + + for (i=0; iclass >> 8 == PCI_CLASS_BRIDGE_PCI + && i >= PCI_BRIDGE_RESOURCES) + continue; + r = &dev->resource[i]; + r_size = r->end - r->start; + if (r_size < 0xfff) + r_size = 0xfff; + if (r->flags & IORESOURCE_IO && (r_size) != 0) { + rc = 1; + push_end(res, r_size); + } + } + } + + return rc; +} + +/* Here we scan all P2P bridges of a given level that have a closed + * IO window. Note that the test for the presence of a VGA card should + * be improved to take into account already configured P2P bridges, + * currently, we don't see them and might end up configuring 2 bridges + * with VGA pass through enabled + */ +static void __init +do_fixup_p2p_level(struct pci_bus *bus) +{ + struct pci_bus *b; + int i, parent_io; + int has_vga = 0; + + for (parent_io=0; parent_io<4; parent_io++) + if (bus->resource[parent_io] + && bus->resource[parent_io]->flags & IORESOURCE_IO) + break; + if (parent_io >= 4) + return; + + list_for_each_entry(b, &bus->children, node) { + struct pci_dev *d = b->self; + struct pci_controller* hose = (struct pci_controller *)d->sysdata; + struct resource *res = b->resource[0]; + struct resource tmp_res; + unsigned long max; + int found_vga = 0; + + memset(&tmp_res, 0, sizeof(tmp_res)); + tmp_res.start = bus->resource[parent_io]->start; + + /* We don't let low addresses go through that closed P2P bridge, well, + * that may not be necessary but I feel safer that way + */ + if (tmp_res.start == 0) + tmp_res.start = 0x1000; + + if (!list_empty(&b->devices) && res && res->flags == 0 && + res != bus->resource[parent_io] && + (d->class >> 8) == PCI_CLASS_BRIDGE_PCI && + check_for_io_childs(b, &tmp_res, &found_vga)) { + u8 io_base_lo; + + printk(KERN_INFO "Fixing up IO bus %s\n", b->name); + + if (found_vga) { + if (has_vga) { + printk(KERN_WARNING "Skipping VGA, already active" + " on bus segment\n"); + found_vga = 0; + } else + has_vga = 1; + } + pci_read_config_byte(d, PCI_IO_BASE, &io_base_lo); + + if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) + max = ((unsigned long) hose->io_base_virt + - isa_io_base) + 0xffffffff; + else + max = ((unsigned long) hose->io_base_virt + - isa_io_base) + 0xffff; + + *res = tmp_res; + res->flags = IORESOURCE_IO; + res->name = b->name; + + /* Find a resource in the parent where we can allocate */ + for (i = 0 ; i < 4; i++) { + struct resource *r = bus->resource[i]; + if (!r) + continue; + if ((r->flags & IORESOURCE_IO) == 0) + continue; + DBG("Trying to allocate from %08lx, size %08lx from parent" + " res %d: %08lx -> %08lx\n", + res->start, res->end, i, r->start, r->end); + + if (allocate_resource(r, res, res->end + 1, res->start, max, + res->end + 1, NULL, NULL) < 0) { + DBG("Failed !\n"); + continue; + } + do_update_p2p_io_resource(b, found_vga); + break; + } + } + do_fixup_p2p_level(b); + } +} + +static void +pcibios_fixup_p2p_bridges(void) +{ + struct pci_bus *b; + + list_for_each_entry(b, &pci_root_buses, node) + do_fixup_p2p_level(b); +} + +#endif /* CONFIG_PPC_PMAC */ + +static int __init +pcibios_init(void) +{ + struct pci_controller *hose; + struct pci_bus *bus; + int next_busno; + + printk(KERN_INFO "PCI: Probing PCI hardware\n"); + + /* Scan all of the recorded PCI controllers. */ + for (next_busno = 0, hose = hose_head; hose; hose = hose->next) { + if (pci_assign_all_buses) + hose->first_busno = next_busno; + hose->last_busno = 0xff; + bus = pci_scan_bus(hose->first_busno, hose->ops, hose); + hose->last_busno = bus->subordinate; + if (pci_assign_all_buses || next_busno <= hose->last_busno) + next_busno = hose->last_busno + pcibios_assign_bus_offset; + } + pci_bus_count = next_busno; + + /* OpenFirmware based machines need a map of OF bus + * numbers vs. kernel bus numbers since we may have to + * remap them. + */ + if (pci_assign_all_buses && have_of) + pcibios_make_OF_bus_map(); + + /* Do machine dependent PCI interrupt routing */ + if (ppc_md.pci_swizzle && ppc_md.pci_map_irq) + pci_fixup_irqs(ppc_md.pci_swizzle, ppc_md.pci_map_irq); + + /* Call machine dependent fixup */ + if (ppc_md.pcibios_fixup) + ppc_md.pcibios_fixup(); + + /* Allocate and assign resources */ + pcibios_allocate_bus_resources(&pci_root_buses); + pcibios_allocate_resources(0); + pcibios_allocate_resources(1); +#ifdef CONFIG_PPC_PMAC + pcibios_fixup_p2p_bridges(); +#endif /* CONFIG_PPC_PMAC */ + pcibios_assign_resources(); + + /* Call machine dependent post-init code */ + if (ppc_md.pcibios_after_init) + ppc_md.pcibios_after_init(); + + return 0; +} + +subsys_initcall(pcibios_init); + +unsigned char __init +common_swizzle(struct pci_dev *dev, unsigned char *pinp) +{ + struct pci_controller *hose = dev->sysdata; + + if (dev->bus->number != hose->first_busno) { + u8 pin = *pinp; + do { + pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)); + /* Move up the chain of bridges. */ + dev = dev->bus->self; + } while (dev->bus->self); + *pinp = pin; + + /* The slot is the idsel of the last bridge. */ + } + return PCI_SLOT(dev->devfn); +} + +unsigned long resource_fixup(struct pci_dev * dev, struct resource * res, + unsigned long start, unsigned long size) +{ + return start; +} + +void __init pcibios_fixup_bus(struct pci_bus *bus) +{ + struct pci_controller *hose = (struct pci_controller *) bus->sysdata; + unsigned long io_offset; + struct resource *res; + int i; + + io_offset = (unsigned long)hose->io_base_virt - isa_io_base; + if (bus->parent == NULL) { + /* This is a host bridge - fill in its resources */ + hose->bus = bus; + + bus->resource[0] = res = &hose->io_resource; + if (!res->flags) { + if (io_offset) + printk(KERN_ERR "I/O resource not set for host" + " bridge %d\n", hose->index); + res->start = 0; + res->end = IO_SPACE_LIMIT; + res->flags = IORESOURCE_IO; + } + res->start += io_offset; + res->end += io_offset; + + for (i = 0; i < 3; ++i) { + res = &hose->mem_resources[i]; + if (!res->flags) { + if (i > 0) + continue; + printk(KERN_ERR "Memory resource not set for " + "host bridge %d\n", hose->index); + res->start = hose->pci_mem_offset; + res->end = ~0U; + res->flags = IORESOURCE_MEM; + } + bus->resource[i+1] = res; + } + } else { + /* This is a subordinate bridge */ + pci_read_bridge_bases(bus); + + for (i = 0; i < 4; ++i) { + if ((res = bus->resource[i]) == NULL) + continue; + if (!res->flags) + continue; + if (io_offset && (res->flags & IORESOURCE_IO)) { + res->start += io_offset; + res->end += io_offset; + } else if (hose->pci_mem_offset + && (res->flags & IORESOURCE_MEM)) { + res->start += hose->pci_mem_offset; + res->end += hose->pci_mem_offset; + } + } + } + + if (ppc_md.pcibios_fixup_bus) + ppc_md.pcibios_fixup_bus(bus); +} + +char __init *pcibios_setup(char *str) +{ + return str; +} + +/* the next one is stolen from the alpha port... */ +void __init +pcibios_update_irq(struct pci_dev *dev, int irq) +{ + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); + /* XXX FIXME - update OF device tree node interrupt property */ +} + +int pcibios_enable_device(struct pci_dev *dev, int mask) +{ + u16 cmd, old_cmd; + int idx; + struct resource *r; + + if (ppc_md.pcibios_enable_device_hook) + if (ppc_md.pcibios_enable_device_hook(dev, 0)) + return -EINVAL; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + old_cmd = cmd; + for (idx=0; idx<6; idx++) { + r = &dev->resource[idx]; + if (r->flags & IORESOURCE_UNSET) { + printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev)); + return -EINVAL; + } + if (r->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (r->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + if (cmd != old_cmd) { + printk("PCI: Enabling device %s (%04x -> %04x)\n", + pci_name(dev), old_cmd, cmd); + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + return 0; +} + +struct pci_controller* +pci_bus_to_hose(int bus) +{ + struct pci_controller* hose = hose_head; + + for (; hose; hose = hose->next) + if (bus >= hose->first_busno && bus <= hose->last_busno) + return hose; + return NULL; +} + +void __iomem * +pci_bus_io_base(unsigned int bus) +{ + struct pci_controller *hose; + + hose = pci_bus_to_hose(bus); + if (!hose) + return NULL; + return hose->io_base_virt; +} + +unsigned long +pci_bus_io_base_phys(unsigned int bus) +{ + struct pci_controller *hose; + + hose = pci_bus_to_hose(bus); + if (!hose) + return 0; + return hose->io_base_phys; +} + +unsigned long +pci_bus_mem_base_phys(unsigned int bus) +{ + struct pci_controller *hose; + + hose = pci_bus_to_hose(bus); + if (!hose) + return 0; + return hose->pci_mem_offset; +} + +unsigned long +pci_resource_to_bus(struct pci_dev *pdev, struct resource *res) +{ + /* Hack alert again ! See comments in chrp_pci.c + */ + struct pci_controller* hose = + (struct pci_controller *)pdev->sysdata; + if (hose && res->flags & IORESOURCE_MEM) + return res->start - hose->pci_mem_offset; + /* We may want to do something with IOs here... */ + return res->start; +} + + +static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, + unsigned long *offset, + enum pci_mmap_state mmap_state) +{ + struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); + unsigned long io_offset = 0; + int i, res_bit; + + if (hose == 0) + return NULL; /* should never happen */ + + /* If memory, add on the PCI bridge address offset */ + if (mmap_state == pci_mmap_mem) { + *offset += hose->pci_mem_offset; + res_bit = IORESOURCE_MEM; + } else { + io_offset = hose->io_base_virt - ___IO_BASE; + *offset += io_offset; + res_bit = IORESOURCE_IO; + } + + /* + * Check that the offset requested corresponds to one of the + * resources of the device. + */ + for (i = 0; i <= PCI_ROM_RESOURCE; i++) { + struct resource *rp = &dev->resource[i]; + int flags = rp->flags; + + /* treat ROM as memory (should be already) */ + if (i == PCI_ROM_RESOURCE) + flags |= IORESOURCE_MEM; + + /* Active and same type? */ + if ((flags & res_bit) == 0) + continue; + + /* In the range of this resource? */ + if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end) + continue; + + /* found it! construct the final physical address */ + if (mmap_state == pci_mmap_io) + *offset += hose->io_base_phys - io_offset; + return rp; + } + + return NULL; +} + +/* + * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci + * device mapping. + */ +static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, + pgprot_t protection, + enum pci_mmap_state mmap_state, + int write_combine) +{ + unsigned long prot = pgprot_val(protection); + + /* Write combine is always 0 on non-memory space mappings. On + * memory space, if the user didn't pass 1, we check for a + * "prefetchable" resource. This is a bit hackish, but we use + * this to workaround the inability of /sysfs to provide a write + * combine bit + */ + if (mmap_state != pci_mmap_mem) + write_combine = 0; + else if (write_combine == 0) { + if (rp->flags & IORESOURCE_PREFETCH) + write_combine = 1; + } + + /* XXX would be nice to have a way to ask for write-through */ + prot |= _PAGE_NO_CACHE; + if (write_combine) + prot &= ~_PAGE_GUARDED; + else + prot |= _PAGE_GUARDED; + + printk("PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start, + prot); + + return __pgprot(prot); +} + +/* + * This one is used by /dev/mem and fbdev who have no clue about the + * PCI device, it tries to find the PCI device first and calls the + * above routine + */ +pgprot_t pci_phys_mem_access_prot(struct file *file, + unsigned long pfn, + unsigned long size, + pgprot_t protection) +{ + struct pci_dev *pdev = NULL; + struct resource *found = NULL; + unsigned long prot = pgprot_val(protection); + unsigned long offset = pfn << PAGE_SHIFT; + int i; + + if (page_is_ram(pfn)) + return prot; + + prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; + + for_each_pci_dev(pdev) { + for (i = 0; i <= PCI_ROM_RESOURCE; i++) { + struct resource *rp = &pdev->resource[i]; + int flags = rp->flags; + + /* Active and same type? */ + if ((flags & IORESOURCE_MEM) == 0) + continue; + /* In the range of this resource? */ + if (offset < (rp->start & PAGE_MASK) || + offset > rp->end) + continue; + found = rp; + break; + } + if (found) + break; + } + if (found) { + if (found->flags & IORESOURCE_PREFETCH) + prot &= ~_PAGE_GUARDED; + pci_dev_put(pdev); + } + + DBG("non-PCI map for %lx, prot: %lx\n", offset, prot); + + return __pgprot(prot); +} + + +/* + * Perform the actual remap of the pages for a PCI device mapping, as + * appropriate for this architecture. The region in the process to map + * is described by vm_start and vm_end members of VMA, the base physical + * address is found in vm_pgoff. + * The pci device structure is provided so that architectures may make mapping + * decisions on a per-device or per-bus basis. + * + * Returns a negative error code on failure, zero on success. + */ +int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, + enum pci_mmap_state mmap_state, + int write_combine) +{ + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; + struct resource *rp; + int ret; + + rp = __pci_mmap_make_offset(dev, &offset, mmap_state); + if (rp == NULL) + return -EINVAL; + + vma->vm_pgoff = offset >> PAGE_SHIFT; + vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO; + vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp, + vma->vm_page_prot, + mmap_state, write_combine); + + ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, + vma->vm_end - vma->vm_start, vma->vm_page_prot); + + return ret; +} + +/* Obsolete functions. Should be removed once the symbios driver + * is fixed + */ +unsigned long +phys_to_bus(unsigned long pa) +{ + struct pci_controller *hose; + int i; + + for (hose = hose_head; hose; hose = hose->next) { + for (i = 0; i < 3; ++i) { + if (pa >= hose->mem_resources[i].start + && pa <= hose->mem_resources[i].end) { + /* + * XXX the hose->pci_mem_offset really + * only applies to mem_resources[0]. + * We need a way to store an offset for + * the others. -- paulus + */ + if (i == 0) + pa -= hose->pci_mem_offset; + return pa; + } + } + } + /* hmmm, didn't find it */ + return 0; +} + +unsigned long +pci_phys_to_bus(unsigned long pa, int busnr) +{ + struct pci_controller* hose = pci_bus_to_hose(busnr); + if (!hose) + return pa; + return pa - hose->pci_mem_offset; +} + +unsigned long +pci_bus_to_phys(unsigned int ba, int busnr) +{ + struct pci_controller* hose = pci_bus_to_hose(busnr); + if (!hose) + return ba; + return ba + hose->pci_mem_offset; +} + +/* Provide information on locations of various I/O regions in physical + * memory. Do this on a per-card basis so that we choose the right + * root bridge. + * Note that the returned IO or memory base is a physical address + */ + +long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn) +{ + struct pci_controller* hose; + long result = -EOPNOTSUPP; + + /* Argh ! Please forgive me for that hack, but that's the + * simplest way to get existing XFree to not lockup on some + * G5 machines... So when something asks for bus 0 io base + * (bus 0 is HT root), we return the AGP one instead. + */ +#ifdef CONFIG_PPC_PMAC + if (_machine == _MACH_Pmac && machine_is_compatible("MacRISC4")) + if (bus == 0) + bus = 0xf0; +#endif /* CONFIG_PPC_PMAC */ + + hose = pci_bus_to_hose(bus); + if (!hose) + return -ENODEV; + + switch (which) { + case IOBASE_BRIDGE_NUMBER: + return (long)hose->first_busno; + case IOBASE_MEMORY: + return (long)hose->pci_mem_offset; + case IOBASE_IO: + return (long)hose->io_base_phys; + case IOBASE_ISA_IO: + return (long)isa_io_base; + case IOBASE_ISA_MEM: + return (long)isa_mem_base; + } + + return result; +} + +void pci_resource_to_user(const struct pci_dev *dev, int bar, + const struct resource *rsrc, + u64 *start, u64 *end) +{ + struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); + unsigned long offset = 0; + + if (hose == NULL) + return; + + if (rsrc->flags & IORESOURCE_IO) + offset = ___IO_BASE - hose->io_base_virt + hose->io_base_phys; + + *start = rsrc->start + offset; + *end = rsrc->end + offset; +} + +void __init +pci_init_resource(struct resource *res, unsigned long start, unsigned long end, + int flags, char *name) +{ + res->start = start; + res->end = end; + res->flags = flags; + res->name = name; + res->parent = NULL; + res->sibling = NULL; + res->child = NULL; +} + +void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max) +{ + unsigned long start = pci_resource_start(dev, bar); + unsigned long len = pci_resource_len(dev, bar); + unsigned long flags = pci_resource_flags(dev, bar); + + if (!len) + return NULL; + if (max && len > max) + len = max; + if (flags & IORESOURCE_IO) + return ioport_map(start, len); + if (flags & IORESOURCE_MEM) + /* Not checking IORESOURCE_CACHEABLE because PPC does + * not currently distinguish between ioremap and + * ioremap_nocache. + */ + return ioremap(start, len); + /* What? */ + return NULL; +} + +void pci_iounmap(struct pci_dev *dev, void __iomem *addr) +{ + /* Nothing to do */ +} +EXPORT_SYMBOL(pci_iomap); +EXPORT_SYMBOL(pci_iounmap); + +unsigned long pci_address_to_pio(phys_addr_t address) +{ + struct pci_controller* hose = hose_head; + + for (; hose; hose = hose->next) { + unsigned int size = hose->io_resource.end - + hose->io_resource.start + 1; + if (address >= hose->io_base_phys && + address < (hose->io_base_phys + size)) { + unsigned long base = + (unsigned long)hose->io_base_virt - _IO_BASE; + return base + (address - hose->io_base_phys); + } + } + return (unsigned int)-1; +} +EXPORT_SYMBOL(pci_address_to_pio); + +/* + * Null PCI config access functions, for the case when we can't + * find a hose. + */ +#define NULL_PCI_OP(rw, size, type) \ +static int \ +null_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \ +{ \ + return PCIBIOS_DEVICE_NOT_FOUND; \ +} + +static int +null_read_config(struct pci_bus *bus, unsigned int devfn, int offset, + int len, u32 *val) +{ + return PCIBIOS_DEVICE_NOT_FOUND; +} + +static int +null_write_config(struct pci_bus *bus, unsigned int devfn, int offset, + int len, u32 val) +{ + return PCIBIOS_DEVICE_NOT_FOUND; +} + +static struct pci_ops null_pci_ops = +{ + null_read_config, + null_write_config +}; + +/* + * These functions are used early on before PCI scanning is done + * and all of the pci_dev and pci_bus structures have been created. + */ +static struct pci_bus * +fake_pci_bus(struct pci_controller *hose, int busnr) +{ + static struct pci_bus bus; + + if (hose == 0) { + hose = pci_bus_to_hose(busnr); + if (hose == 0) + printk(KERN_ERR "Can't find hose for PCI bus %d!\n", busnr); + } + bus.number = busnr; + bus.sysdata = hose; + bus.ops = hose? hose->ops: &null_pci_ops; + return &bus; +} + +#define EARLY_PCI_OP(rw, size, type) \ +int early_##rw##_config_##size(struct pci_controller *hose, int bus, \ + int devfn, int offset, type value) \ +{ \ + return pci_bus_##rw##_config_##size(fake_pci_bus(hose, bus), \ + devfn, offset, value); \ +} + +EARLY_PCI_OP(read, byte, u8 *) +EARLY_PCI_OP(read, word, u16 *) +EARLY_PCI_OP(read, dword, u32 *) +EARLY_PCI_OP(write, byte, u8) +EARLY_PCI_OP(write, word, u16) +EARLY_PCI_OP(write, dword, u32) diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index 647da4c1d21..e399bbb969a 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -40,7 +40,6 @@ obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-mapping.o -obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_KGDB) += ppc-stub.o obj-$(CONFIG_TAU) += temp.o ifndef CONFIG_E200 -- GitLab From e0ad8486266c3415ab9c17f5c03c47edc7b93d7b Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 15 Jan 2006 06:45:20 -0200 Subject: [PATCH 323/465] V4L/DVB (3375): git dvb callbacks fix - Not sure what went wrong here, but SND_PCI_PM_CALLBACKS got deleted. Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-alsa.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index fd8bc718f0e..e649f678d47 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c @@ -805,7 +805,6 @@ static struct pci_driver cx88_audio_pci_driver = { .id_table = cx88_audio_pci_tbl, .probe = cx88_audio_initdev, .remove = cx88_audio_finidev, - SND_PCI_PM_CALLBACKS }; /**************************************************************************** -- GitLab From 60f33b80443a3e7e79e2a3ddc625ab6246a61d3d Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 15 Jan 2006 15:28:35 +0100 Subject: [PATCH 324/465] kconfig: get rid of stray a.o, support ncursesw scripts/kconfig/lxdialog/check-lxdialog.sh uses gcc to check for what libraries are present. Redirect output to /dev/null so we do not generate an a.out. Also included support for ncursesw - so if present prefer that instead of ncurses. The order is now (first is preferred): 1) ncursesw 2) ncurses 3) curses The latter is to support SunOS. Signed-off-by: Sam Ravnborg --- scripts/kconfig/lxdialog/Makefile | 6 +++--- scripts/kconfig/lxdialog/check-lxdialog.sh | 23 +++++++++++++++++----- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/scripts/kconfig/lxdialog/Makefile b/scripts/kconfig/lxdialog/Makefile index 8f41d9a57aa..fae3e29fc92 100644 --- a/scripts/kconfig/lxdialog/Makefile +++ b/scripts/kconfig/lxdialog/Makefile @@ -1,9 +1,9 @@ # Makefile to build lxdialog package # -check-lxdialog := $(srctree)/$(src)/check-lxdialog.sh -HOST_EXTRACFLAGS := $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) -HOST_LOADLIBES := $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags) +check-lxdialog := $(srctree)/$(src)/check-lxdialog.sh +HOST_EXTRACFLAGS:= $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) +HOST_LOADLIBES := $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC)) HOST_EXTRACFLAGS += -DLOCALE diff --git a/scripts/kconfig/lxdialog/check-lxdialog.sh b/scripts/kconfig/lxdialog/check-lxdialog.sh index a3c141b4967..448e353923f 100644 --- a/scripts/kconfig/lxdialog/check-lxdialog.sh +++ b/scripts/kconfig/lxdialog/check-lxdialog.sh @@ -4,11 +4,22 @@ # What library to link ldflags() { - if [ `uname` == SunOS ]; then - echo '-lcurses' - else + echo "main() {}" | $cc -lncursesw -xc - -o /dev/null 2> /dev/null + if [ $? -eq 0 ]; then + echo '-lncursesw' + exit + fi + echo "main() {}" | $cc -lncurses -xc - -o /dev/null 2> /dev/null + if [ $? -eq 0 ]; then echo '-lncurses' + exit fi + echo "main() {}" | $cc -lcurses -xc - -o /dev/null 2> /dev/null + if [ $? -eq 0 ]; then + echo '-lcurses' + exit + fi + exit 1 } # Where is ncurses.h? @@ -28,7 +39,7 @@ ccflags() compiler="" # Check if we can link to ncurses check() { - echo "main() {}" | $compiler -xc - + echo "main() {}" | $cc -xc - -o /dev/null 2> /dev/null if [ $? != 0 ]; then echo " *** Unable to find the ncurses libraries." 1>&2 echo " *** make menuconfig require the ncurses libraries" 1>&2 @@ -51,13 +62,15 @@ fi case "$1" in "-check") shift - compiler="$@" + cc="$@" check ;; "-ccflags") ccflags ;; "-ldflags") + shift + cc="$@" ldflags ;; "*") -- GitLab From ef0498a7bfbb5773e7ba4235207054b81ad5120e Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 15 Jan 2006 17:03:45 +0000 Subject: [PATCH 325/465] [ARM] Fix missing compiler.h include asm/mach/arch.h introduced a __deprecated, but didn't include compiler.h, causing: In file included from arch/arm/mach-at91rm9200/devices.c:13: include/asm/mach/arch.h:23: warning: no semicolon at end of struct or union include/asm/mach/arch.h:23: error: syntax error before 'phys_ram' include/asm/mach/arch.h:34: error: syntax error before ':' token include/asm/mach/arch.h:35: error: syntax error before ':' token include/asm/mach/arch.h:36: error: syntax error before ':' token include/asm/mach/arch.h:37: error: syntax error before ':' token include/asm/mach/arch.h:45: error: syntax error before '}' token Add the necessary include. Signed-off-by: Russell King --- include/asm-arm/mach/arch.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/asm-arm/mach/arch.h b/include/asm-arm/mach/arch.h index 8222bf9fc36..2cd57b4d64d 100644 --- a/include/asm-arm/mach/arch.h +++ b/include/asm-arm/mach/arch.h @@ -10,6 +10,8 @@ #ifndef __ASSEMBLY__ +#include + struct tag; struct meminfo; struct sys_timer; -- GitLab From 69ff56c166629224e9fe914b8543021dc2f001f0 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 15 Jan 2006 13:13:13 +0100 Subject: [PATCH 326/465] [PATCH] Fix zoran_card compilation warning Fix the following warning which was introduced in 2.6.15-git8 by commit 7408187d223f63d46a13b6a35b8f96b032c2f623: CC [M] drivers/media/video/zoran_card.o drivers/media/video/zoran_card.c: In function `zr36057_init': drivers/media/video/zoran_card.c:1053: warning: assignment makes integer from pointer without a cast Signed-off-by: Jean Delvare Acked-by: Ronald S. Bultje Signed-off-by: Linus Torvalds --- drivers/media/video/zoran_card.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c index ea3288661a3..246e67cd8b5 100644 --- a/drivers/media/video/zoran_card.c +++ b/drivers/media/video/zoran_card.c @@ -995,7 +995,7 @@ test_interrupts (struct zoran *zr) static int __devinit zr36057_init (struct zoran *zr) { - unsigned long mem; + u32 *mem; void *vdev; unsigned mem_needed; int j; @@ -1058,10 +1058,10 @@ zr36057_init (struct zoran *zr) "%s: zr36057_init() - kmalloc (STAT_COM) failed\n", ZR_DEVNAME(zr)); kfree(vdev); - kfree((void *)mem); + kfree(mem); return -ENOMEM; } - zr->stat_com = (u32 *) mem; + zr->stat_com = mem; for (j = 0; j < BUZ_NUM_STAT_COM; j++) { zr->stat_com[j] = 1; /* mark as unavailable to zr36057 */ } -- GitLab From 6b4977ce0fb9a989ba24fd6b757d07a566abc23d Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Sun, 15 Jan 2006 12:10:55 -0500 Subject: [PATCH 327/465] [PATCH] Use atomic64_set for 64-bit case of atomic_long_set For some reason, the BITS_PER_LONG == 64 case of atomic_long_set was using atomic_set instead of atomic64_set. This does not jive with architectures which use an inline instead of a #define to implement their atomic_set() primitives. Signed-off-by: Kyle McMartin Signed-off-by: Linus Torvalds --- include/asm-generic/atomic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/asm-generic/atomic.h b/include/asm-generic/atomic.h index 0fada8f16dc..42a95d9a064 100644 --- a/include/asm-generic/atomic.h +++ b/include/asm-generic/atomic.h @@ -35,7 +35,7 @@ static inline void atomic_long_set(atomic_long_t *l, long i) { atomic64_t *v = (atomic64_t *)l; - atomic_set(v, i); + atomic64_set(v, i); } static inline void atomic_long_inc(atomic_long_t *l) -- GitLab From 296e0855b0f9a4ec9be17106ac541745a55b2ce1 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 15 Jan 2006 20:02:31 +0100 Subject: [PATCH 328/465] kbuild: fix make -jN with multiple targets with O=... The way multiple targets was handled with make O=... broke because for each high-level target make spawned a parallel make resulting in a broken build. Reported by Keith Owens Signed-off-by: Sam Ravnborg --- Makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index deedaf79cdc..b3dd9dbdc29 100644 --- a/Makefile +++ b/Makefile @@ -106,12 +106,13 @@ KBUILD_OUTPUT := $(shell cd $(KBUILD_OUTPUT) && /bin/pwd) $(if $(KBUILD_OUTPUT),, \ $(error output directory "$(saved-output)" does not exist)) -.PHONY: $(MAKECMDGOALS) +.PHONY: $(MAKECMDGOALS) cdbuilddir +$(MAKECMDGOALS) _all: cdbuilddir -$(filter-out _all,$(MAKECMDGOALS)) _all: +cdbuilddir: $(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \ KBUILD_SRC=$(CURDIR) \ - KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f $(CURDIR)/Makefile $@ + KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f $(CURDIR)/Makefile $(MAKECMDGOALS) # Leave processing to above invocation of make skip-makefile := 1 -- GitLab From a073404272e8003816d9198f639b1bf11ff0a864 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Wed, 2 Nov 2005 08:56:49 +0000 Subject: [PATCH 329/465] [WATCHDOG] sa1100_wdt.c sparse cleanups The following makes drivers/char/watchdog/sa1100_wdt.c sparse clean. Signed-off-by: Ian Campbell Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/sa1100_wdt.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c index fb88b4041dc..b474ea52d6e 100644 --- a/drivers/char/watchdog/sa1100_wdt.c +++ b/drivers/char/watchdog/sa1100_wdt.c @@ -74,7 +74,7 @@ static int sa1100dog_release(struct inode *inode, struct file *file) return 0; } -static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos) +static ssize_t sa1100dog_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { if (len) /* Refresh OSMR3 timer. */ @@ -96,20 +96,20 @@ static int sa1100dog_ioctl(struct inode *inode, struct file *file, switch (cmd) { case WDIOC_GETSUPPORT: - ret = copy_to_user((struct watchdog_info *)arg, &ident, + ret = copy_to_user((struct watchdog_info __user *)arg, &ident, sizeof(ident)) ? -EFAULT : 0; break; case WDIOC_GETSTATUS: - ret = put_user(0, (int *)arg); + ret = put_user(0, (int __user *)arg); break; case WDIOC_GETBOOTSTATUS: - ret = put_user(boot_status, (int *)arg); + ret = put_user(boot_status, (int __user *)arg); break; case WDIOC_SETTIMEOUT: - ret = get_user(time, (int *)arg); + ret = get_user(time, (int __user *)arg); if (ret) break; @@ -123,7 +123,7 @@ static int sa1100dog_ioctl(struct inode *inode, struct file *file, /*fall through*/ case WDIOC_GETTIMEOUT: - ret = put_user(pre_margin / OSCR_FREQ, (int *)arg); + ret = put_user(pre_margin / OSCR_FREQ, (int __user *)arg); break; case WDIOC_KEEPALIVE: -- GitLab From 3527761cb403fba72a37c4e6a1fad76eeedd990c Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Sun, 15 Jan 2006 21:21:14 +0100 Subject: [PATCH 330/465] [PATCH] MAINTAINERS: watchdog device drivers Add a MAINTAINER entry for the watchdog device drivers. Signed-off-by: Wim Van Sebroeck --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 513f3b6c35b..ce3c8f52c91 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2965,6 +2965,12 @@ M: dm@sangoma.com W: http://www.sangoma.com S: Supported +WATCHDOG DEVICE DRIVERS +P: Wim Van Sebroeck +M: wim@iguana.be +T: git kernel.org:/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog.git +S: Maintained + WAVELAN NETWORK DRIVER & WIRELESS EXTENSIONS P: Jean Tourrilhes M: jt@hpl.hp.com -- GitLab From 8f0bb9c069fc487dadebe4cdd1e03f0df5ebf0e6 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 15 Jan 2006 12:46:18 -0200 Subject: [PATCH 331/465] V4L/DVB (3383): Move tda988x options into tuner_params struct. - Tda988x parameters should be defined per tuner_param_type, for each tuner_params array member. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- include/media/tuner-types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/media/tuner-types.h b/include/media/tuner-types.h index 64b16b1f192..75669318899 100644 --- a/include/media/tuner-types.h +++ b/include/media/tuner-types.h @@ -19,6 +19,7 @@ struct tuner_range { struct tuner_params { enum param_type type; + unsigned int tda988x; unsigned char config; /* to be moved into struct tuner_range for dvb-pll merge */ unsigned int count; @@ -27,7 +28,6 @@ struct tuner_params { struct tunertype { char *name; - unsigned int has_tda988x:1; struct tuner_params *params; }; -- GitLab From 27487d44712aaa37710cc508d5bd6119f5e9f976 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 15 Jan 2006 15:04:52 -0200 Subject: [PATCH 332/465] V4L/DVB (3384): Separate tv & radio freqs, fix cb/freq transmit order for tuners that need this. - Moved MSP_SET_MATRIX to v4l2-common.h - Fix typos and integer overflows in tea5767.c - Split old freq field into a tv_freq and a radio_freq. Prevents that a radio tuner is initialized with a tv frequency or vice versa. - When switching to radio mode initialize the tuner with the last used radio frequency (this was already done for the TV mode). As a result of these changes the tuner module now remembers the last set radio and TV frequencies, which is what you would expect to happen. - Move out of range frequencies to the closest valid frequency as per v4l2 API spec. - Fix incorrect initial radio frequency (multiplier is 16000, not 16) - Add boundary check for out of range frequencies. - Use new flag to check if the order of the CB and freq. depends on the last set frequency. That is needed for some tuners or you can get static as a result. The flag is added for those tuners where I know that the datasheet indicates that this is necessary. - For this new check use the last set div value, not the last frequency as radio frequencies are always much higher due to the 16000 multiplier. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/msp3400.h | 8 --- drivers/media/video/mt20xx.c | 12 ++--- drivers/media/video/tda8290.c | 4 +- drivers/media/video/tea5767.c | 18 +++---- drivers/media/video/tuner-core.c | 85 ++++++++++++++++++------------ drivers/media/video/tuner-simple.c | 44 ++++++++-------- drivers/media/video/tuner-types.c | 6 +++ drivers/media/video/v4l2-common.c | 1 + include/media/tuner-types.h | 18 +++++++ include/media/tuner.h | 8 +-- include/media/v4l2-common.h | 7 +++ 11 files changed, 129 insertions(+), 82 deletions(-) diff --git a/drivers/media/video/msp3400.h b/drivers/media/video/msp3400.h index 70a5ef8ba01..a9ac57d0700 100644 --- a/drivers/media/video/msp3400.h +++ b/drivers/media/video/msp3400.h @@ -6,14 +6,6 @@ /* ---------------------------------------------------------------------- */ -struct msp_matrix { - int input; - int output; -}; - -/* ioctl for MSP_SET_MATRIX will have to be registered */ -#define MSP_SET_MATRIX _IOW('m',17,struct msp_matrix) - /* This macro is allowed for *constants* only, gcc must calculate it at compile time. Remember -- no floats in kernel mode */ #define MSP_CARRIER(freq) ((int)((float)(freq / 18.432) * (1 << 24))) diff --git a/drivers/media/video/mt20xx.c b/drivers/media/video/mt20xx.c index 0bf1caac588..c7c9f3f8715 100644 --- a/drivers/media/video/mt20xx.c +++ b/drivers/media/video/mt20xx.c @@ -353,8 +353,8 @@ static int mt2032_init(struct i2c_client *c) } while (xok != 1 ); t->xogc=xogc; - t->tv_freq = mt2032_set_tv_freq; - t->radio_freq = mt2032_set_radio_freq; + t->set_tv_freq = mt2032_set_tv_freq; + t->set_radio_freq = mt2032_set_radio_freq; return(1); } @@ -481,8 +481,8 @@ static int mt2050_init(struct i2c_client *c) i2c_master_recv(c,buf,1); tuner_dbg("mt2050: sro is %x\n",buf[0]); - t->tv_freq = mt2050_set_tv_freq; - t->radio_freq = mt2050_set_radio_freq; + t->set_tv_freq = mt2050_set_tv_freq; + t->set_radio_freq = mt2050_set_radio_freq; return 0; } @@ -494,8 +494,8 @@ int microtune_init(struct i2c_client *c) int company_code; memset(buf,0,sizeof(buf)); - t->tv_freq = NULL; - t->radio_freq = NULL; + t->set_tv_freq = NULL; + t->set_radio_freq = NULL; t->standby = NULL; if (t->std & V4L2_STD_525_60) { tuner_dbg("pinnacle ntsc\n"); diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 2498b76df42..7b4fb282ac8 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -567,8 +567,8 @@ int tda8290_init(struct i2c_client *c) } tuner_info("tuner: type set to %s\n", c->name); - t->tv_freq = set_tv_freq; - t->radio_freq = set_radio_freq; + t->set_tv_freq = set_tv_freq; + t->set_radio_freq = set_radio_freq; t->has_signal = has_signal; t->standby = standby; t->tda827x_lpsel = 0; diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c index 921fe72f23d..c2b98f81c19 100644 --- a/drivers/media/video/tea5767.c +++ b/drivers/media/video/tea5767.c @@ -62,7 +62,7 @@ extern int tuner_debug; #define TEA5767_PORT1_HIGH 0x01 -/* Forth register */ +/* Fourth register */ #define TEA5767_PORT2_HIGH 0x80 /* Chips stops working. Only I2C bus remains on */ #define TEA5767_STDBY 0x40 @@ -85,7 +85,7 @@ extern int tuner_debug; /* If activate PORT 1 indicates SEARCH or else it is used as PORT1 */ #define TEA5767_SRCH_IND 0x01 -/* Fiveth register */ +/* Fifth register */ /* By activating, it will use Xtal at 13 MHz as reference for divider */ #define TEA5767_PLLREF_ENABLE 0x80 @@ -109,13 +109,13 @@ extern int tuner_debug; #define TEA5767_STEREO_MASK 0x80 #define TEA5767_IF_CNTR_MASK 0x7f -/* Four register */ +/* Fourth register */ #define TEA5767_ADC_LEVEL_MASK 0xf0 /* should be 0 */ #define TEA5767_CHIP_ID_MASK 0x0f -/* Fiveth register */ +/* Fifth register */ /* Reserved for future extensions */ #define TEA5767_RESERVED_MASK 0xff @@ -220,19 +220,19 @@ static void set_radio_freq(struct i2c_client *c, unsigned int frq) tuner_dbg ("TEA5767 radio HIGH LO inject xtal @ 13 MHz\n"); buffer[2] |= TEA5767_HIGH_LO_INJECT; buffer[4] |= TEA5767_PLLREF_ENABLE; - div = (frq * 4000 / 16 + 700000 + 225000 + 25000) / 50000; + div = (frq * (4000 / 16) + 700000 + 225000 + 25000) / 50000; break; case TEA5767_LOW_LO_13MHz: tuner_dbg ("TEA5767 radio LOW LO inject xtal @ 13 MHz\n"); buffer[4] |= TEA5767_PLLREF_ENABLE; - div = (frq * 4000 / 16 - 700000 - 225000 + 25000) / 50000; + div = (frq * (4000 / 16) - 700000 - 225000 + 25000) / 50000; break; case TEA5767_LOW_LO_32768: tuner_dbg ("TEA5767 radio LOW LO inject xtal @ 32,768 MHz\n"); buffer[3] |= TEA5767_XTAL_32768; /* const 700=4000*175 Khz - to adjust freq to right value */ - div = ((frq * 4000 / 16 - 700000 - 225000) + 16384) >> 15; + div = ((frq * (4000 / 16) - 700000 - 225000) + 16384) >> 15; break; case TEA5767_HIGH_LO_32768: default: @@ -350,8 +350,8 @@ int tea5767_tuner_init(struct i2c_client *c) tuner_info("type set to %d (%s)\n", t->type, "Philips TEA5767HN FM Radio"); strlcpy(c->name, "tea5767", sizeof(c->name)); - t->tv_freq = set_tv_freq; - t->radio_freq = set_radio_freq; + t->set_tv_freq = set_tv_freq; + t->set_radio_freq = set_radio_freq; t->has_signal = tea5767_signal; t->is_stereo = tea5767_stereo; t->standby = tea5767_standby; diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index f30ef79d795..2995b22acb4 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -82,7 +82,7 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq) tuner_warn ("tuner type not set\n"); return; } - if (NULL == t->tv_freq) { + if (NULL == t->set_tv_freq) { tuner_warn ("Tuner has no way to set tv freq\n"); return; } @@ -90,8 +90,14 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq) tuner_dbg ("TV freq (%d.%02d) out of range (%d-%d)\n", freq / 16, freq % 16 * 100 / 16, tv_range[0], tv_range[1]); + /* V4L2 spec: if the freq is not possible then the closest + possible value should be selected */ + if (freq < tv_range[0] * 16) + freq = tv_range[0] * 16; + else + freq = tv_range[1] * 16; } - t->tv_freq(c, freq); + t->set_tv_freq(c, freq); } static void set_radio_freq(struct i2c_client *c, unsigned int freq) @@ -102,18 +108,23 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq) tuner_warn ("tuner type not set\n"); return; } - if (NULL == t->radio_freq) { + if (NULL == t->set_radio_freq) { tuner_warn ("tuner has no way to set radio frequency\n"); return; } - if (freq <= radio_range[0] * 16000 || freq >= radio_range[1] * 16000) { + if (freq < radio_range[0] * 16000 || freq > radio_range[1] * 16000) { tuner_dbg ("radio freq (%d.%02d) out of range (%d-%d)\n", freq / 16000, freq % 16000 * 100 / 16000, radio_range[0], radio_range[1]); + /* V4L2 spec: if the freq is not possible then the closest + possible value should be selected */ + if (freq < radio_range[0] * 16000) + freq = radio_range[0] * 16000; + else + freq = radio_range[1] * 16000; } - t->radio_freq(c, freq); - return; + t->set_radio_freq(c, freq); } static void set_freq(struct i2c_client *c, unsigned long freq) @@ -125,15 +136,16 @@ static void set_freq(struct i2c_client *c, unsigned long freq) tuner_dbg("radio freq set to %lu.%02lu\n", freq / 16000, freq % 16000 * 100 / 16000); set_radio_freq(c, freq); + t->radio_freq = freq; break; case V4L2_TUNER_ANALOG_TV: case V4L2_TUNER_DIGITAL_TV: tuner_dbg("tv freq set to %lu.%02lu\n", freq / 16, freq % 16 * 100 / 16); set_tv_freq(c, freq); + t->tv_freq = freq; break; } - t->freq = freq; } static void set_type(struct i2c_client *c, unsigned int type, @@ -212,7 +224,7 @@ static void set_type(struct i2c_client *c, unsigned int type, if (t->mode_mask == T_UNINITIALIZED) t->mode_mask = new_mode_mask; - set_freq(c, t->freq); + set_freq(c, (V4L2_TUNER_RADIO == t->mode) ? t->radio_freq : t->tv_freq); tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n", c->adapter->name, c->driver->driver.name, c->addr << 1, type, t->mode_mask); @@ -377,11 +389,11 @@ static void tuner_status(struct i2c_client *client) default: p = "undefined"; break; } if (t->mode == V4L2_TUNER_RADIO) { - freq = t->freq / 16000; - freq_fraction = (t->freq % 16000) * 100 / 16000; + freq = t->radio_freq / 16000; + freq_fraction = (t->radio_freq % 16000) * 100 / 16000; } else { - freq = t->freq / 16; - freq_fraction = (t->freq % 16) * 100 / 16; + freq = t->tv_freq / 16; + freq_fraction = (t->tv_freq % 16) * 100 / 16; } tuner_info("Tuner mode: %s\n", p); tuner_info("Frequency: %lu.%02lu MHz\n", freq, freq_fraction); @@ -456,7 +468,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) t->type = TUNER_TEA5767; t->mode_mask = T_RADIO; t->mode = T_STANDBY; - t->freq = 87.5 * 16; /* Sets freq to FM range */ + t->radio_freq = 87.5 * 16000; /* Sets freq to FM range */ default_mode_mask &= ~T_RADIO; goto register_client; @@ -469,7 +481,8 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) if (default_mode_mask != T_UNINITIALIZED) { tuner_dbg ("Setting mode_mask to 0x%02x\n", default_mode_mask); t->mode_mask = default_mode_mask; - t->freq = 400 * 16; /* Sets freq to VHF High */ + t->tv_freq = 400 * 16; /* Sets freq to VHF High */ + t->radio_freq = 87.5 * 16000; /* Sets freq to FM range */ default_mode_mask = T_UNINITIALIZED; } @@ -565,16 +578,18 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) set_addr(client, (struct tuner_setup *)arg); break; case AUDC_SET_RADIO: - set_mode(client,t,V4L2_TUNER_RADIO, "AUDC_SET_RADIO"); + if (set_mode(client, t, V4L2_TUNER_RADIO, "AUDC_SET_RADIO") + == EINVAL) + return 0; + if (t->radio_freq) + set_freq(client, t->radio_freq); break; case TUNER_SET_STANDBY: - { - if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL) - return 0; - if (t->standby) - t->standby (client); - break; - } + if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL) + return 0; + if (t->standby) + t->standby (client); + break; case VIDIOCSAUDIO: if (check_mode(t, "VIDIOCSAUDIO") == EINVAL) return 0; @@ -583,7 +598,6 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) /* Should be implemented, since bttv calls it */ tuner_dbg("VIDIOCSAUDIO not implemented.\n"); - break; /* --- v4l ioctls --- */ /* take care: bttv does userspace copying, we'll get a @@ -609,8 +623,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) if (vc->norm < ARRAY_SIZE(map)) t->std = map[vc->norm]; tuner_fixup_std(t); - if (t->freq) - set_tv_freq(client, t->freq); + if (t->tv_freq) + set_tv_freq(client, t->tv_freq); return 0; } case VIDIOCSFREQ: @@ -684,15 +698,14 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) t->std = *id; tuner_fixup_std(t); - if (t->freq) - set_freq(client, t->freq); + if (t->tv_freq) + set_freq(client, t->tv_freq); break; } case VIDIOC_S_FREQUENCY: { struct v4l2_frequency *f = arg; - t->freq = f->frequency; switch_v4l2(); if (V4L2_TUNER_RADIO == f->type && V4L2_TUNER_RADIO != t->mode) { @@ -700,7 +713,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) == EINVAL) return 0; } - set_freq(client,t->freq); + set_freq(client,f->frequency); break; } @@ -712,7 +725,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) return 0; switch_v4l2(); f->type = t->mode; - f->frequency = t->freq; + f->frequency = (V4L2_TUNER_RADIO == t->mode) ? + t->radio_freq : t->tv_freq; break; } case VIDIOC_G_TUNER: @@ -763,7 +777,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) if (V4L2_TUNER_RADIO == t->mode) { t->audmode = tuner->audmode; - set_radio_freq(client, t->freq); + set_radio_freq(client, t->radio_freq); } break; } @@ -791,8 +805,13 @@ static int tuner_resume(struct device *dev) struct tuner *t = i2c_get_clientdata (c); tuner_dbg ("resume\n"); - if (t->freq) - set_freq(c, t->freq); + if (V4L2_TUNER_RADIO == t->mode) { + if (t->radio_freq) + set_freq(c, t->radio_freq); + } else { + if (t->tv_freq) + set_freq(c, t->tv_freq); + } return 0; } diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 3879262cf4c..37977ff4978 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -136,7 +136,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) u8 config, tuneraddr; u16 div; struct tunertype *tun; - unsigned char buffer[4]; + u8 buffer[4]; int rc, IFPCoff, i, j; tun = &tuners[t->type]; @@ -147,6 +147,11 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) continue; break; } + if (i == tun->params[j].count) { + tuner_dbg("TV frequency out of range (%d > %d)", + freq, tun->params[j].ranges[i - 1].limit); + freq = tun->params[j].ranges[--i].limit; + } config = tun->params[j].ranges[i].cb; /* i == 0 -> VHF_LO */ /* i == 1 -> VHF_HI */ @@ -239,20 +244,6 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) break; } - /* - * Philips FI1216MK2 remark from specification : - * for channel selection involving band switching, and to ensure - * smooth tuning to the desired channel without causing - * unnecessary charge pump action, it is recommended to consider - * the difference between wanted channel frequency and the - * current channel frequency. Unnecessary charge pump action - * will result in very low tuning voltage which may drive the - * oscillator to extreme conditions. - * - * Progfou: specification says to send config data before - * frequency in case (wanted frequency < current frequency). - */ - /* IFPCoff = Video Intermediate Frequency - Vif: 940 =16*58.75 NTSC/J (Japan) 732 =16*45.75 M/N STD @@ -284,7 +275,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) offset / 16, offset % 16 * 100 / 16, div); - if (t->type == TUNER_PHILIPS_SECAM && freq < t->freq) { + if (tuners[t->type].params->cb_first_if_lower_freq && div < t->last_div) { buffer[0] = tun->params[j].config; buffer[1] = config; buffer[2] = (div>>8) & 0x7f; @@ -295,6 +286,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) buffer[2] = tun->params[j].config; buffer[3] = config; } + t->last_div = div; tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", buffer[0],buffer[1],buffer[2],buffer[3]); @@ -337,8 +329,8 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) { struct tunertype *tun; struct tuner *t = i2c_get_clientdata(c); - unsigned char buffer[4]; - unsigned div; + u8 buffer[4]; + u16 div; int rc, j; tun = &tuners[t->type]; @@ -374,9 +366,19 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) } buffer[0] = (div>>8) & 0x7f; buffer[1] = div & 0xff; + if (tuners[t->type].params->cb_first_if_lower_freq && div < t->last_div) { + buffer[0] = buffer[2]; + buffer[1] = buffer[3]; + buffer[2] = (div>>8) & 0x7f; + buffer[3] = div & 0xff; + } else { + buffer[0] = (div>>8) & 0x7f; + buffer[1] = div & 0xff; + } tuner_dbg("radio 0x%02x 0x%02x 0x%02x 0x%02x\n", buffer[0],buffer[1],buffer[2],buffer[3]); + t->last_div = div; if (4 != (rc = i2c_master_send(c,buffer,4))) tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); @@ -390,10 +392,10 @@ int default_tuner_init(struct i2c_client *c) t->type, tuners[t->type].name); strlcpy(c->name, tuners[t->type].name, sizeof(c->name)); - t->tv_freq = default_set_tv_freq; - t->radio_freq = default_set_radio_freq; + t->set_tv_freq = default_set_tv_freq; + t->set_radio_freq = default_set_radio_freq; t->has_signal = tuner_signal; - t->is_stereo = tuner_stereo; + t->is_stereo = tuner_stereo; t->standby = NULL; return 0; diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index 32c9be4c5ca..6fe781798d8 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -81,6 +81,7 @@ static struct tuner_params tuner_philips_ntsc_params[] = { .ranges = tuner_philips_ntsc_ranges, .count = ARRAY_SIZE(tuner_philips_ntsc_ranges), .config = 0x8e, + .cb_first_if_lower_freq = 1, }, }; @@ -98,6 +99,7 @@ static struct tuner_params tuner_philips_secam_params[] = { .ranges = tuner_philips_secam_ranges, .count = ARRAY_SIZE(tuner_philips_secam_ranges), .config = 0x8e, + .cb_first_if_lower_freq = 1, }, }; @@ -115,6 +117,7 @@ static struct tuner_params tuner_philips_pal_params[] = { .ranges = tuner_philips_pal_ranges, .count = ARRAY_SIZE(tuner_philips_pal_ranges), .config = 0x8e, + .cb_first_if_lower_freq = 1, }, }; @@ -596,6 +599,7 @@ static struct tuner_params tuner_fm1216me_mk3_params[] = { .ranges = tuner_fm1216me_mk3_pal_ranges, .count = ARRAY_SIZE(tuner_fm1216me_mk3_pal_ranges), .config = 0x8e, + .cb_first_if_lower_freq = 1, }, }; @@ -670,6 +674,7 @@ static struct tuner_params tuner_fm1236_mk3_params[] = { .ranges = tuner_fm1236_mk3_ntsc_ranges, .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges), .config = 0x8e, + .cb_first_if_lower_freq = 1, }, }; @@ -784,6 +789,7 @@ static struct tuner_params tuner_tcl_2002n_params[] = { .ranges = tuner_tcl_2002n_ntsc_ranges, .count = ARRAY_SIZE(tuner_tcl_2002n_ntsc_ranges), .config = 0x8e, + .cb_first_if_lower_freq = 1, }, }; diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 5dbd7c1b362..cd2c4475525 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -306,6 +306,7 @@ static const char *v4l2_int_ioctls[] = { #endif [_IOC_NR(AUDC_SET_RADIO)] = "AUDC_SET_RADIO", [_IOC_NR(AUDC_SET_INPUT)] = "AUDC_SET_INPUT", + [_IOC_NR(MSP_SET_MATRIX)] = "MSP_SET_MATRIX", [_IOC_NR(TUNER_SET_TYPE_ADDR)] = "TUNER_SET_TYPE_ADDR", [_IOC_NR(TUNER_SET_STANDBY)] = "TUNER_SET_STANDBY", diff --git a/include/media/tuner-types.h b/include/media/tuner-types.h index 75669318899..b37d59d5a10 100644 --- a/include/media/tuner-types.h +++ b/include/media/tuner-types.h @@ -20,6 +20,24 @@ struct tuner_range { struct tuner_params { enum param_type type; unsigned int tda988x; + /* Many Philips based tuners have a comment like this in their + * datasheet: + * + * For channel selection involving band switching, and to ensure + * smooth tuning to the desired channel without causing + * unnecessary charge pump action, it is recommended to consider + * the difference between wanted channel frequency and the + * current channel frequency. Unnecessary charge pump action + * will result in very low tuning voltage which may drive the + * oscillator to extreme conditions. + * + * Set this flag to 1 if this tuner needs this check. + * + * I tested this for PAL by first setting the TV frequency to + * 203 MHz and then switching to 96.6 MHz FM radio. The result was + * static unless the control byte was sent first. + */ + unsigned int cb_first_if_lower_freq:1; unsigned char config; /* to be moved into struct tuner_range for dvb-pll merge */ unsigned int count; diff --git a/include/media/tuner.h b/include/media/tuner.h index a1d63787bc0..a5beeac495c 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -179,7 +179,9 @@ struct tuner { unsigned int mode; unsigned int mode_mask; /* Combination of allowable modes */ - unsigned int freq; /* keep track of the current settings */ + unsigned int tv_freq; /* keep track of the current settings */ + unsigned int radio_freq; + u16 last_div; unsigned int audmode; v4l2_std_id std; @@ -197,8 +199,8 @@ struct tuner { unsigned int sgIF; /* function ptrs */ - void (*tv_freq)(struct i2c_client *c, unsigned int freq); - void (*radio_freq)(struct i2c_client *c, unsigned int freq); + void (*set_tv_freq)(struct i2c_client *c, unsigned int freq); + void (*set_radio_freq)(struct i2c_client *c, unsigned int freq); int (*has_signal)(struct i2c_client *c); int (*is_stereo)(struct i2c_client *c); void (*standby)(struct i2c_client *c); diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index c74052abb18..d4030a7e16e 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -120,6 +120,13 @@ enum v4l2_chip_ident { /* select from TV,radio,extern,MUTE */ #define AUDC_SET_INPUT _IOW('d',89,int) +/* msp3400 ioctl: will be removed in the near future */ +struct msp_matrix { + int input; + int output; +}; +#define MSP_SET_MATRIX _IOW('m',17,struct msp_matrix) + /* tuner ioctls */ /* Sets tuner type and its I2C addr */ #define TUNER_SET_TYPE_ADDR _IOW('d',90,int) -- GitLab From cb8d1aa78e31d7f3511c0b3f25f5a61a4687235f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 15 Jan 2006 15:09:23 -0200 Subject: [PATCH 333/465] V4L/DVB (3385): Return -EINVAL for unknown commands in msp3400 module. - Return -EINVAL for unknown commands. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/msp3400-driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index 09ff25b554b..69ed369c2f4 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c @@ -1031,8 +1031,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) } default: - /* nothing */ - break; + /* unknown */ + return -EINVAL; } return 0; } -- GitLab From 18adfe7ac0777c3cc364cccb6823aafe2a009aa3 Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Sun, 15 Jan 2006 15:33:02 -0200 Subject: [PATCH 334/465] V4L/DVB (3386): fix some sound quality & distortion problems. - Fix some sound quality & distortion problems. Signed-off-by: Ricardo Cerqueira Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-alsa.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index e649f678d47..a2e36a1e5f5 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c @@ -333,10 +333,10 @@ static snd_pcm_hardware_t snd_cx88_digital_hw = { .channels_min = 1, .channels_max = 2, .buffer_bytes_max = (2*2048), - .period_bytes_min = 256, + .period_bytes_min = 2048, .period_bytes_max = 2048, .periods_min = 2, - .periods_max = 16, + .periods_max = 2, }; /* -- GitLab From 01872c5d253298b9f360c7c9b9f33504b6ad5469 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 15 Jan 2006 15:47:02 -0200 Subject: [PATCH 335/465] V4L/DVB (3387): clean up some comments - clean up some comments Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- include/media/tuner-types.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/media/tuner-types.h b/include/media/tuner-types.h index b37d59d5a10..9f0e9c1cb6f 100644 --- a/include/media/tuner-types.h +++ b/include/media/tuner-types.h @@ -31,7 +31,8 @@ struct tuner_params { * will result in very low tuning voltage which may drive the * oscillator to extreme conditions. * - * Set this flag to 1 if this tuner needs this check. + * Set cb_first_if_lower_freq to 1, if this check is + * required for this tuner. * * I tested this for PAL by first setting the TV frequency to * 203 MHz and then switching to 96.6 MHz FM radio. The result was -- GitLab From de03d21b908bd4c49f1fe7b0c4dc5876551cf819 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 15 Jan 2006 16:04:04 -0200 Subject: [PATCH 336/465] V4L/DVB (3388): tuner_params->tda988x is currently unused, so disable - Tuner_params->tda988x is unused right now, so let's disable it for 2.6.16 - This is currently happening at the card level, but the plan is to move this configuration into the tuner_params configuration. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- include/media/tuner-types.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/media/tuner-types.h b/include/media/tuner-types.h index 9f0e9c1cb6f..15821ab14a9 100644 --- a/include/media/tuner-types.h +++ b/include/media/tuner-types.h @@ -19,7 +19,6 @@ struct tuner_range { struct tuner_params { enum param_type type; - unsigned int tda988x; /* Many Philips based tuners have a comment like this in their * datasheet: * @@ -31,7 +30,7 @@ struct tuner_params { * will result in very low tuning voltage which may drive the * oscillator to extreme conditions. * - * Set cb_first_if_lower_freq to 1, if this check is + * Set cb_first_if_lower_freq to 1, if this check is * required for this tuner. * * I tested this for PAL by first setting the TV frequency to -- GitLab From 17c37efbb5163e5df118510c7b4243b7d3b32ce2 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 15 Jan 2006 19:04:04 -0200 Subject: [PATCH 337/465] V4L/DVB (3389): Samsung TBMV30111IN has 6 entries - Samsung TBMV30111IN has 6 entries Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dvb-pll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 757075f007c..1b9934ea5b0 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -333,7 +333,7 @@ struct dvb_pll_desc dvb_pll_tbmv30111in = { .name = "Samsung TBMV30111IN", .min = 54000000, .max = 860000000, - .count = 4, + .count = 6, .entries = { { 172000000, 44000000, 166666, 0xb4, 0x01 }, { 214000000, 44000000, 166666, 0xb4, 0x02 }, -- GitLab From 366cc64b0d9ac922ac4f0f54e06c13ec95249928 Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Sun, 15 Jan 2006 21:04:27 -0200 Subject: [PATCH 338/465] V4L/DVB (3390): Added remote control support for pinnacle pctv - Added remote control support for pinnacle pctv Signed-off-by: Markus Rechberger Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-input.c | 77 +++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 9b94f77d6fd..30dfa5370c7 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -76,6 +76,58 @@ static IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE] = { [ 0x40 ] = KEY_ZOOM, }; +static IR_KEYTAB_TYPE ir_codes_em_pinnacle_usb[IR_KEYTAB_SIZE] = { + [ 0x3a ] = KEY_KP0, + [ 0x31 ] = KEY_KP1, + [ 0x32 ] = KEY_KP2, + [ 0x33 ] = KEY_KP3, + [ 0x34 ] = KEY_KP4, + [ 0x35 ] = KEY_KP5, + [ 0x36 ] = KEY_KP6, + [ 0x37 ] = KEY_KP7, + [ 0x38 ] = KEY_KP8, + [ 0x39 ] = KEY_KP9, + + [ 0x2f ] = KEY_POWER, + + [ 0x2e ] = KEY_P, + [ 0x1f ] = KEY_L, + [ 0x2b ] = KEY_I, + + [ 0x2d ] = KEY_ZOOM, + [ 0x1e ] = KEY_ZOOM, + [ 0x1b ] = KEY_VOLUMEUP, + [ 0x0f ] = KEY_VOLUMEDOWN, + [ 0x17 ] = KEY_CHANNELUP, + [ 0x1c ] = KEY_CHANNELDOWN, + [ 0x25 ] = KEY_INFO, + + [ 0x3c ] = KEY_MUTE, + + [ 0x3d ] = KEY_LEFT, + [ 0x3b ] = KEY_RIGHT, + + [ 0x3f ] = KEY_UP, + [ 0x3e ] = KEY_DOWN, + [ 0x1a ] = KEY_PAUSE, + + [ 0x1d ] = KEY_MENU, + [ 0x19 ] = KEY_PLAY, + [ 0x16 ] = KEY_REWIND, + [ 0x13 ] = KEY_FORWARD, + [ 0x15 ] = KEY_PAUSE, + [ 0x0e ] = KEY_REWIND, + [ 0x0d ] = KEY_PLAY, + [ 0x0b ] = KEY_STOP, + [ 0x07 ] = KEY_FORWARD, + [ 0x27 ] = KEY_RECORD, + [ 0x26 ] = KEY_TUNER, + [ 0x29 ] = KEY_TEXT, + [ 0x2a ] = KEY_MEDIA, + [ 0x18 ] = KEY_EPG, + [ 0x27 ] = KEY_RECORD, +}; + /* ----------------------------------------------------------------------- */ static int get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) @@ -138,6 +190,28 @@ static int get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) return 1; } +static int get_key_pinnacle_usb(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +{ + unsigned char buf[3]; + + /* poll IR chip */ + + if (3 != i2c_master_recv(&ir->c,buf,3)) { + dprintk("read error\n"); + return -EIO; + } + + dprintk("key %02x\n", buf[2]&0x3f); + if (buf[0]!=0x00){ + return 0; + } + + *ir_key = buf[2]&0x3f; + *ir_raw = buf[2]&0x3f; + + return 1; +} + /* ----------------------------------------------------------------------- */ void em28xx_set_ir(struct em28xx * dev,struct IR_i2c *ir) { @@ -159,6 +233,9 @@ void em28xx_set_ir(struct em28xx * dev,struct IR_i2c *ir) snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM28XX Terratec)"); break; case (EM2820_BOARD_PINNACLE_USB_2): + ir->ir_codes = ir_codes_em_pinnacle_usb; + ir->get_key = get_key_pinnacle_usb; + snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM28XX Pinnacle PCTV)"); break; case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2): ir->ir_codes = ir_codes_hauppauge_new; -- GitLab From 54245702ab63a9a0b1ccf78bc37b57e778bb3bcc Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Mon, 16 Jan 2006 15:54:05 +1100 Subject: [PATCH 339/465] [XFS] Fix symlink creation too, with respect to initialising SELinux context. SGI-PV: 946762 SGI-Modid: xfs-linux-melb:xfs-kern:24983a Signed-off-by: Nathan Scott --- fs/xfs/linux-2.6/xfs_iops.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 4bd3d03b23e..521bf3834b4 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -474,11 +474,14 @@ linvfs_symlink( error = 0; VOP_SYMLINK(dvp, dentry, &va, (char *)symname, &cvp, NULL, error); - if (!error && cvp) { - ip = LINVFS_GET_IP(cvp); - d_instantiate(dentry, ip); - validate_fields(dir); - validate_fields(ip); /* size needs update */ + if (likely(!error && cvp)) { + error = linvfs_init_security(cvp, dir); + if (likely(!error)) { + ip = LINVFS_GET_IP(cvp); + d_instantiate(dentry, ip); + validate_fields(dir); + validate_fields(ip); + } } return -error; } -- GitLab From c2e81432201d99cc48ff6492567fe05204cc8d7e Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Mon, 16 Jan 2006 16:21:34 +1100 Subject: [PATCH 340/465] [XFS] mutex fallout - fix debug builds and remove no-longer-useful comment. Signed-off-by: Nathan Scott --- fs/xfs/linux-2.6/mutex.h | 12 +----------- fs/xfs/quota/xfs_qm.c | 2 +- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/fs/xfs/linux-2.6/mutex.h b/fs/xfs/linux-2.6/mutex.h index d3369b6ca16..2a88d56c4dc 100644 --- a/fs/xfs/linux-2.6/mutex.h +++ b/fs/xfs/linux-2.6/mutex.h @@ -18,18 +18,8 @@ #ifndef __XFS_SUPPORT_MUTEX_H__ #define __XFS_SUPPORT_MUTEX_H__ -#include #include -/* - * Map the mutex'es from IRIX to Linux semaphores. - * - * Destroy just simply initializes to -99 which should block all other - * callers. - */ -#define MUTEX_DEFAULT 0x0 - -typedef struct mutex mutex_t; -//#define mutex_destroy(lock) do{}while(0) +typedef struct mutex mutex_t; #endif /* __XFS_SUPPORT_MUTEX_H__ */ diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 7dcdd0640c3..3384bfefee5 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c @@ -167,7 +167,7 @@ xfs_Gqm_init(void) xqm->qm_dqfree_ratio = XFS_QM_DQFREE_RATIO; xqm->qm_nrefs = 0; #ifdef DEBUG - xfs_mutex_init(&qcheck_lock, MUTEX_DEFAULT, "qchk"); + mutex_init(&qcheck_lock); #endif return xqm; } -- GitLab From 107a09c44b65d5e2a5313edfda91c498df3b3f2a Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Mon, 16 Jan 2006 16:28:07 +1100 Subject: [PATCH 341/465] [XFS] remove no-longer-needed IS_NOATIME macro, twas just a build workaround Signed-off-by: Christoph Hellwig Signed-off-by: Nathan Scott --- fs/xfs/linux-2.6/xfs_iops.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 521bf3834b4..76c6df34d0d 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -56,9 +56,6 @@ #include #include -#define IS_NOATIME(inode) ((inode->i_sb->s_flags & MS_NOATIME) || \ - (S_ISDIR(inode->i_mode) && inode->i_sb->s_flags & MS_NODIRATIME)) - /* * Get a XFS inode from a given vnode. */ -- GitLab From 5a225791374dca35bba871a007c78a3d0b14b559 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 16 Jan 2006 09:45:58 +0100 Subject: [PATCH 342/465] barrier.txt got lost while the new barrier patchset was climbing up the ladder to the mainline. Add it back. Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- Documentation/block/barrier.txt | 271 ++++++++++++++++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 Documentation/block/barrier.txt diff --git a/Documentation/block/barrier.txt b/Documentation/block/barrier.txt new file mode 100644 index 00000000000..03971518b22 --- /dev/null +++ b/Documentation/block/barrier.txt @@ -0,0 +1,271 @@ +I/O Barriers +============ +Tejun Heo , July 22 2005 + +I/O barrier requests are used to guarantee ordering around the barrier +requests. Unless you're crazy enough to use disk drives for +implementing synchronization constructs (wow, sounds interesting...), +the ordering is meaningful only for write requests for things like +journal checkpoints. All requests queued before a barrier request +must be finished (made it to the physical medium) before the barrier +request is started, and all requests queued after the barrier request +must be started only after the barrier request is finished (again, +made it to the physical medium). + +In other words, I/O barrier requests have the following two properties. + +1. Request ordering + +Requests cannot pass the barrier request. Preceding requests are +processed before the barrier and following requests after. + +Depending on what features a drive supports, this can be done in one +of the following three ways. + +i. For devices which have queue depth greater than 1 (TCQ devices) and +support ordered tags, block layer can just issue the barrier as an +ordered request and the lower level driver, controller and drive +itself are responsible for making sure that the ordering contraint is +met. Most modern SCSI controllers/drives should support this. + +NOTE: SCSI ordered tag isn't currently used due to limitation in the + SCSI midlayer, see the following random notes section. + +ii. For devices which have queue depth greater than 1 but don't +support ordered tags, block layer ensures that the requests preceding +a barrier request finishes before issuing the barrier request. Also, +it defers requests following the barrier until the barrier request is +finished. Older SCSI controllers/drives and SATA drives fall in this +category. + +iii. Devices which have queue depth of 1. This is a degenerate case +of ii. Just keeping issue order suffices. Ancient SCSI +controllers/drives and IDE drives are in this category. + +2. Forced flushing to physcial medium + +Again, if you're not gonna do synchronization with disk drives (dang, +it sounds even more appealing now!), the reason you use I/O barriers +is mainly to protect filesystem integrity when power failure or some +other events abruptly stop the drive from operating and possibly make +the drive lose data in its cache. So, I/O barriers need to guarantee +that requests actually get written to non-volatile medium in order. + +There are four cases, + +i. No write-back cache. Keeping requests ordered is enough. + +ii. Write-back cache but no flush operation. There's no way to +gurantee physical-medium commit order. This kind of devices can't to +I/O barriers. + +iii. Write-back cache and flush operation but no FUA (forced unit +access). We need two cache flushes - before and after the barrier +request. + +iv. Write-back cache, flush operation and FUA. We still need one +flush to make sure requests preceding a barrier are written to medium, +but post-barrier flush can be avoided by using FUA write on the +barrier itself. + + +How to support barrier requests in drivers +------------------------------------------ + +All barrier handling is done inside block layer proper. All low level +drivers have to are implementing its prepare_flush_fn and using one +the following two functions to indicate what barrier type it supports +and how to prepare flush requests. Note that the term 'ordered' is +used to indicate the whole sequence of performing barrier requests +including draining and flushing. + +typedef void (prepare_flush_fn)(request_queue_t *q, struct request *rq); + +int blk_queue_ordered(request_queue_t *q, unsigned ordered, + prepare_flush_fn *prepare_flush_fn, + unsigned gfp_mask); + +int blk_queue_ordered_locked(request_queue_t *q, unsigned ordered, + prepare_flush_fn *prepare_flush_fn, + unsigned gfp_mask); + +The only difference between the two functions is whether or not the +caller is holding q->queue_lock on entry. The latter expects the +caller is holding the lock. + +@q : the queue in question +@ordered : the ordered mode the driver/device supports +@prepare_flush_fn : this function should prepare @rq such that it + flushes cache to physical medium when executed +@gfp_mask : gfp_mask used when allocating data structures + for ordered processing + +For example, SCSI disk driver's prepare_flush_fn looks like the +following. + +static void sd_prepare_flush(request_queue_t *q, struct request *rq) +{ + memset(rq->cmd, 0, sizeof(rq->cmd)); + rq->flags |= REQ_BLOCK_PC; + rq->timeout = SD_TIMEOUT; + rq->cmd[0] = SYNCHRONIZE_CACHE; +} + +The following seven ordered modes are supported. The following table +shows which mode should be used depending on what features a +device/driver supports. In the leftmost column of table, +QUEUE_ORDERED_ prefix is omitted from the mode names to save space. + +The table is followed by description of each mode. Note that in the +descriptions of QUEUE_ORDERED_DRAIN*, '=>' is used whereas '->' is +used for QUEUE_ORDERED_TAG* descriptions. '=>' indicates that the +preceding step must be complete before proceeding to the next step. +'->' indicates that the next step can start as soon as the previous +step is issued. + + write-back cache ordered tag flush FUA +----------------------------------------------------------------------- +NONE yes/no N/A no N/A +DRAIN no no N/A N/A +DRAIN_FLUSH yes no yes no +DRAIN_FUA yes no yes yes +TAG no yes N/A N/A +TAG_FLUSH yes yes yes no +TAG_FUA yes yes yes yes + + +QUEUE_ORDERED_NONE + I/O barriers are not needed and/or supported. + + Sequence: N/A + +QUEUE_ORDERED_DRAIN + Requests are ordered by draining the request queue and cache + flushing isn't needed. + + Sequence: drain => barrier + +QUEUE_ORDERED_DRAIN_FLUSH + Requests are ordered by draining the request queue and both + pre-barrier and post-barrier cache flushings are needed. + + Sequence: drain => preflush => barrier => postflush + +QUEUE_ORDERED_DRAIN_FUA + Requests are ordered by draining the request queue and + pre-barrier cache flushing is needed. By using FUA on barrier + request, post-barrier flushing can be skipped. + + Sequence: drain => preflush => barrier + +QUEUE_ORDERED_TAG + Requests are ordered by ordered tag and cache flushing isn't + needed. + + Sequence: barrier + +QUEUE_ORDERED_TAG_FLUSH + Requests are ordered by ordered tag and both pre-barrier and + post-barrier cache flushings are needed. + + Sequence: preflush -> barrier -> postflush + +QUEUE_ORDERED_TAG_FUA + Requests are ordered by ordered tag and pre-barrier cache + flushing is needed. By using FUA on barrier request, + post-barrier flushing can be skipped. + + Sequence: preflush -> barrier + + +Random notes/caveats +-------------------- + +* SCSI layer currently can't use TAG ordering even if the drive, +controller and driver support it. The problem is that SCSI midlayer +request dispatch function is not atomic. It releases queue lock and +switch to SCSI host lock during issue and it's possible and likely to +happen in time that requests change their relative positions. Once +this problem is solved, TAG ordering can be enabled. + +* Currently, no matter which ordered mode is used, there can be only +one barrier request in progress. All I/O barriers are held off by +block layer until the previous I/O barrier is complete. This doesn't +make any difference for DRAIN ordered devices, but, for TAG ordered +devices with very high command latency, passing multiple I/O barriers +to low level *might* be helpful if they are very frequent. Well, this +certainly is a non-issue. I'm writing this just to make clear that no +two I/O barrier is ever passed to low-level driver. + +* Completion order. Requests in ordered sequence are issued in order +but not required to finish in order. Barrier implementation can +handle out-of-order completion of ordered sequence. IOW, the requests +MUST be processed in order but the hardware/software completion paths +are allowed to reorder completion notifications - eg. current SCSI +midlayer doesn't preserve completion order during error handling. + +* Requeueing order. Low-level drivers are free to requeue any request +after they removed it from the request queue with +blkdev_dequeue_request(). As barrier sequence should be kept in order +when requeued, generic elevator code takes care of putting requests in +order around barrier. See blk_ordered_req_seq() and +ELEVATOR_INSERT_REQUEUE handling in __elv_add_request() for details. + +Note that block drivers must not requeue preceding requests while +completing latter requests in an ordered sequence. Currently, no +error checking is done against this. + +* Error handling. Currently, block layer will report error to upper +layer if any of requests in an ordered sequence fails. Unfortunately, +this doesn't seem to be enough. Look at the following request flow. +QUEUE_ORDERED_TAG_FLUSH is in use. + + [0] [1] [2] [3] [pre] [barrier] [post] < [4] [5] [6] ... > + still in elevator + +Let's say request [2], [3] are write requests to update file system +metadata (journal or whatever) and [barrier] is used to mark that +those updates are valid. Consider the following sequence. + + i. Requests [0] ~ [post] leaves the request queue and enters + low-level driver. + ii. After a while, unfortunately, something goes wrong and the + drive fails [2]. Note that any of [0], [1] and [3] could have + completed by this time, but [pre] couldn't have been finished + as the drive must process it in order and it failed before + processing that command. + iii. Error handling kicks in and determines that the error is + unrecoverable and fails [2], and resumes operation. + iv. [pre] [barrier] [post] gets processed. + v. *BOOM* power fails + +The problem here is that the barrier request is *supposed* to indicate +that filesystem update requests [2] and [3] made it safely to the +physical medium and, if the machine crashes after the barrier is +written, filesystem recovery code can depend on that. Sadly, that +isn't true in this case anymore. IOW, the success of a I/O barrier +should also be dependent on success of some of the preceding requests, +where only upper layer (filesystem) knows what 'some' is. + +This can be solved by implementing a way to tell the block layer which +requests affect the success of the following barrier request and +making lower lever drivers to resume operation on error only after +block layer tells it to do so. + +As the probability of this happening is very low and the drive should +be faulty, implementing the fix is probably an overkill. But, still, +it's there. + +* In previous drafts of barrier implementation, there was fallback +mechanism such that, if FUA or ordered TAG fails, less fancy ordered +mode can be selected and the failed barrier request is retried +automatically. The rationale for this feature was that as FUA is +pretty new in ATA world and ordered tag was never used widely, there +could be devices which report to support those features but choke when +actually given such requests. + + This was removed for two reasons 1. it's an overkill 2. it's +impossible to implement properly when TAG ordering is used as low +level drivers resume after an error automatically. If it's ever +needed adding it back and modifying low level drivers accordingly +shouldn't be difficult. -- GitLab From 752a3b79630a290cbbe4731e7c61b75d4fbebc5c Mon Sep 17 00:00:00 2001 From: Chuck Ebbert <76306.1226@compuserve.com> Date: Mon, 16 Jan 2006 09:47:37 +0100 Subject: [PATCH 343/465] [BLOCK] elevator: Make elevator=as work again for anticipatory Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Signed-off-by: Jens Axboe --- block/elevator.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/block/elevator.c b/block/elevator.c index 1d0759178e4..e8025b2ec54 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -149,6 +149,13 @@ static void elevator_setup_default(void) if (!chosen_elevator[0]) strcpy(chosen_elevator, CONFIG_DEFAULT_IOSCHED); + /* + * Be backwards-compatible with previous kernels, so users + * won't get the wrong elevator. + */ + if (!strcmp(chosen_elevator, "as")) + strcpy(chosen_elevator, "anticipatory"); + /* * If the given scheduler is not available, fall back to no-op. */ -- GitLab From b7bfcf7cbd58d2a64aa46f3b4bec921e346e604f Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 16 Jan 2006 09:48:58 +0100 Subject: [PATCH 344/465] [BLOCK] elevator: if specified scheduler is not found, fall back to default Signed-off-by: Jens Axboe --- block/elevator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/block/elevator.c b/block/elevator.c index e8025b2ec54..c9f424d5399 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -157,12 +157,12 @@ static void elevator_setup_default(void) strcpy(chosen_elevator, "anticipatory"); /* - * If the given scheduler is not available, fall back to no-op. + * If the given scheduler is not available, fall back to the default */ if ((e = elevator_find(chosen_elevator))) elevator_put(e); else - strcpy(chosen_elevator, "noop"); + strcpy(chosen_elevator, CONFIG_DEFAULT_IOSCHED); } static int __init elevator_setup(char *str) -- GitLab From 2244cbd8a9185c197ec5ba5de175aec288697223 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Mon, 16 Jan 2006 12:12:12 +0100 Subject: [PATCH 345/465] kbuild: create .kernelrelease at *config step To enable 'make kernelrelease' earlier now create .kernelrelease when one of the *config targets are used. Also introduce KERNELVERSION - only user is kconfig. KERNELVERSION was needed to display kernel version in menuconfig - KERNELRELEASE is not valid until configuration has completed. kconfig files modified to use KERNELVERSION. Bug reported by: Rene Rebe Signed-off-by: Sam Ravnborg --- Makefile | 19 ++++++++++--------- scripts/kconfig/confdata.c | 2 +- scripts/kconfig/gconf.c | 2 +- scripts/kconfig/mconf.c | 2 +- scripts/kconfig/symbol.c | 4 ++-- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index b3dd9dbdc29..22e322f1757 100644 --- a/Makefile +++ b/Makefile @@ -338,8 +338,9 @@ AFLAGS := -D__ASSEMBLY__ # Read KERNELRELEASE from .kernelrelease (if it exists) KERNELRELEASE = $(shell cat .kernelrelease 2> /dev/null) +KERNELVERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) -export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE \ +export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION \ ARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC \ CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE \ HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS @@ -434,6 +435,7 @@ export KBUILD_DEFCONFIG config %config: scripts_basic outputmakefile FORCE $(Q)mkdir -p include/linux $(Q)$(MAKE) $(build)=scripts/kconfig $@ + $(Q)$(MAKE) .kernelrelease else # =========================================================================== @@ -784,12 +786,10 @@ endif localver-full = $(localver)$(localver-auto) # Store (new) KERNELRELASE string in .kernelrelease -kernelrelease = \ - $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)$(localver-full) +kernelrelease = $(KERNELVERSION)$(localver-full) .kernelrelease: FORCE - $(Q)rm -f .kernelrelease - $(Q)echo $(kernelrelease) > .kernelrelease - $(Q)echo " Building kernel $(kernelrelease)" + $(Q)rm -f $@ + $(Q)echo $(kernelrelease) > $@ # Things we need to do before we recursively start building the kernel @@ -899,7 +899,7 @@ define filechk_version.h ) endef -include/linux/version.h: $(srctree)/Makefile FORCE +include/linux/version.h: $(srctree)/Makefile .config FORCE $(call filechk,version.h) # --------------------------------------------------------------------------- @@ -1302,9 +1302,10 @@ checkstack: $(PERL) $(src)/scripts/checkstack.pl $(ARCH) kernelrelease: - @echo $(KERNELRELEASE) + $(if $(wildcard .kernelrelease), $(Q)echo $(KERNELRELEASE), \ + $(error kernelrelease not valid - run 'make *config' to update it)) kernelversion: - @echo $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) + @echo $(KERNELVERSION) # FIXME Should go into a make.lib or something # =========================================================================== diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index ccd45130c48..b0cbbe2e41b 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -375,7 +375,7 @@ int conf_write(const char *name) if (!out_h) return 1; } - sym = sym_lookup("KERNELRELEASE", 0); + sym = sym_lookup("KERNELVERSION", 0); sym_calc_value(sym); time(&now); env = getenv("KCONFIG_NOTIMESTAMP"); diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c index 9f5aabd58fa..665bd5300a1 100644 --- a/scripts/kconfig/gconf.c +++ b/scripts/kconfig/gconf.c @@ -276,7 +276,7 @@ void init_main_window(const gchar * glade_file) NULL); sprintf(title, _("Linux Kernel v%s Configuration"), - getenv("KERNELRELEASE")); + getenv("KERNELVERSION")); gtk_window_set_title(GTK_WINDOW(main_wnd), title); gtk_widget_show(main_wnd); diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c index d63d7fb677e..7f973195e79 100644 --- a/scripts/kconfig/mconf.c +++ b/scripts/kconfig/mconf.c @@ -1051,7 +1051,7 @@ int main(int ac, char **av) conf_parse(av[1]); conf_read(NULL); - sym = sym_lookup("KERNELRELEASE", 0); + sym = sym_lookup("KERNELVERSION", 0); sym_calc_value(sym); sprintf(menu_backtitle, _("Linux Kernel v%s Configuration"), sym_get_string_value(sym)); diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c index 69c2549c0ba..3d7877afccd 100644 --- a/scripts/kconfig/symbol.c +++ b/scripts/kconfig/symbol.c @@ -61,10 +61,10 @@ void sym_init(void) if (p) sym_add_default(sym, p); - sym = sym_lookup("KERNELRELEASE", 0); + sym = sym_lookup("KERNELVERSION", 0); sym->type = S_STRING; sym->flags |= SYMBOL_AUTO; - p = getenv("KERNELRELEASE"); + p = getenv("KERNELVERSION"); if (p) sym_add_default(sym, p); -- GitLab From df9df036d356078679a60135fba65f79cd6153d0 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Mon, 16 Jan 2006 12:46:07 +0100 Subject: [PATCH 346/465] kbuild: fix 'make all install_modules install' The command 'make all modules_install install' would fail in a virgin tree - pointing at a non-existing directory under /lib/modules/xxx KERNELRELEASE is part of MODLIB and we need to create .kernelrelease before we can properly evaluate KERNELRELEASE, Changing MODLIB to the recursively expanded flavor let it pick up the correct KERNELRELEASE value. Reported by: "Hemmann, Volker Armin" Signed-off-by: Sam Ravnborg --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 22e322f1757..37a4b67653c 100644 --- a/Makefile +++ b/Makefile @@ -545,7 +545,7 @@ export INSTALL_PATH ?= /boot # makefile but the arguement can be passed to make if needed. # -MODLIB := $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE) +MODLIB = $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE) export MODLIB -- GitLab From 9179cb65780def28770a895a4bc8fa60e903ab80 Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Tue, 10 Jan 2006 03:10:43 -0800 Subject: [PATCH 347/465] [IA64] Perfmon for Montecito Add Montecito PMU description table for perfmon2 Signed-off-by: Stephane Eranian Signed-off-by: Tony Luck --- arch/ia64/kernel/perfmon.c | 2 + arch/ia64/kernel/perfmon_montecito.h | 269 +++++++++++++++++++++++++++ include/asm-ia64/processor.h | 4 +- 3 files changed, 273 insertions(+), 2 deletions(-) create mode 100644 arch/ia64/kernel/perfmon_montecito.h diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index bd87cb6b7a8..2ea4b39efff 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -628,9 +628,11 @@ static int pfm_write_ibr_dbr(int mode, pfm_context_t *ctx, void *arg, int count, #include "perfmon_itanium.h" #include "perfmon_mckinley.h" +#include "perfmon_montecito.h" #include "perfmon_generic.h" static pmu_config_t *pmu_confs[]={ + &pmu_conf_mont, &pmu_conf_mck, &pmu_conf_ita, &pmu_conf_gen, /* must be last */ diff --git a/arch/ia64/kernel/perfmon_montecito.h b/arch/ia64/kernel/perfmon_montecito.h new file mode 100644 index 00000000000..cd06ac6a686 --- /dev/null +++ b/arch/ia64/kernel/perfmon_montecito.h @@ -0,0 +1,269 @@ +/* + * This file contains the Montecito PMU register description tables + * and pmc checker used by perfmon.c. + * + * Copyright (c) 2005-2006 Hewlett-Packard Development Company, L.P. + * Contributed by Stephane Eranian + */ +static int pfm_mont_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnum, unsigned long *val, struct pt_regs *regs); + +#define RDEP_MONT_ETB (RDEP(38)|RDEP(39)|RDEP(48)|RDEP(49)|RDEP(50)|RDEP(51)|RDEP(52)|RDEP(53)|RDEP(54)|\ + RDEP(55)|RDEP(56)|RDEP(57)|RDEP(58)|RDEP(59)|RDEP(60)|RDEP(61)|RDEP(62)|RDEP(63)) +#define RDEP_MONT_DEAR (RDEP(32)|RDEP(33)|RDEP(36)) +#define RDEP_MONT_IEAR (RDEP(34)|RDEP(35)) + +static pfm_reg_desc_t pfm_mont_pmc_desc[PMU_MAX_PMCS]={ +/* pmc0 */ { PFM_REG_CONTROL , 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc1 */ { PFM_REG_CONTROL , 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc2 */ { PFM_REG_CONTROL , 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc3 */ { PFM_REG_CONTROL , 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc4 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(4),0, 0, 0}, {0,0, 0, 0}}, +/* pmc5 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(5),0, 0, 0}, {0,0, 0, 0}}, +/* pmc6 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(6),0, 0, 0}, {0,0, 0, 0}}, +/* pmc7 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(7),0, 0, 0}, {0,0, 0, 0}}, +/* pmc8 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(8),0, 0, 0}, {0,0, 0, 0}}, +/* pmc9 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(9),0, 0, 0}, {0,0, 0, 0}}, +/* pmc10 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(10),0, 0, 0}, {0,0, 0, 0}}, +/* pmc11 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(11),0, 0, 0}, {0,0, 0, 0}}, +/* pmc12 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(12),0, 0, 0}, {0,0, 0, 0}}, +/* pmc13 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(13),0, 0, 0}, {0,0, 0, 0}}, +/* pmc14 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(14),0, 0, 0}, {0,0, 0, 0}}, +/* pmc15 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(15),0, 0, 0}, {0,0, 0, 0}}, +/* pmc16 */ { PFM_REG_NOTIMPL, }, +/* pmc17 */ { PFM_REG_NOTIMPL, }, +/* pmc18 */ { PFM_REG_NOTIMPL, }, +/* pmc19 */ { PFM_REG_NOTIMPL, }, +/* pmc20 */ { PFM_REG_NOTIMPL, }, +/* pmc21 */ { PFM_REG_NOTIMPL, }, +/* pmc22 */ { PFM_REG_NOTIMPL, }, +/* pmc23 */ { PFM_REG_NOTIMPL, }, +/* pmc24 */ { PFM_REG_NOTIMPL, }, +/* pmc25 */ { PFM_REG_NOTIMPL, }, +/* pmc26 */ { PFM_REG_NOTIMPL, }, +/* pmc27 */ { PFM_REG_NOTIMPL, }, +/* pmc28 */ { PFM_REG_NOTIMPL, }, +/* pmc29 */ { PFM_REG_NOTIMPL, }, +/* pmc30 */ { PFM_REG_NOTIMPL, }, +/* pmc31 */ { PFM_REG_NOTIMPL, }, +/* pmc32 */ { PFM_REG_CONFIG, 0, 0x30f01ffffffffff, 0x30f01ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc33 */ { PFM_REG_CONFIG, 0, 0x0, 0x1ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc34 */ { PFM_REG_CONFIG, 0, 0xf01ffffffffff, 0xf01ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc35 */ { PFM_REG_CONFIG, 0, 0x0, 0x1ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc36 */ { PFM_REG_CONFIG, 0, 0xfffffff0, 0xf, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc37 */ { PFM_REG_MONITOR, 4, 0x0, 0x3fff, NULL, pfm_mont_pmc_check, {RDEP_MONT_IEAR, 0, 0, 0}, {0, 0, 0, 0}}, +/* pmc38 */ { PFM_REG_CONFIG, 0, 0xdb6, 0x2492, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc39 */ { PFM_REG_MONITOR, 6, 0x0, 0xffcf, NULL, pfm_mont_pmc_check, {RDEP_MONT_ETB,0, 0, 0}, {0,0, 0, 0}}, +/* pmc40 */ { PFM_REG_MONITOR, 6, 0x2000000, 0xf01cf, NULL, pfm_mont_pmc_check, {RDEP_MONT_DEAR,0, 0, 0}, {0,0, 0, 0}}, +/* pmc41 */ { PFM_REG_CONFIG, 0, 0x00002078fefefefe, 0x1e00018181818, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc42 */ { PFM_REG_MONITOR, 6, 0x0, 0x7ff4f, NULL, pfm_mont_pmc_check, {RDEP_MONT_ETB,0, 0, 0}, {0,0, 0, 0}}, + { PFM_REG_END , 0, 0x0, -1, NULL, NULL, {0,}, {0,}}, /* end marker */ +}; + +static pfm_reg_desc_t pfm_mont_pmd_desc[PMU_MAX_PMDS]={ +/* pmd0 */ { PFM_REG_NOTIMPL, }, +/* pmd1 */ { PFM_REG_NOTIMPL, }, +/* pmd2 */ { PFM_REG_NOTIMPL, }, +/* pmd3 */ { PFM_REG_NOTIMPL, }, +/* pmd4 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(4),0, 0, 0}}, +/* pmd5 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(5),0, 0, 0}}, +/* pmd6 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(6),0, 0, 0}}, +/* pmd7 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(7),0, 0, 0}}, +/* pmd8 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(8),0, 0, 0}}, +/* pmd9 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(9),0, 0, 0}}, +/* pmd10 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(10),0, 0, 0}}, +/* pmd11 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(11),0, 0, 0}}, +/* pmd12 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(12),0, 0, 0}}, +/* pmd13 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(13),0, 0, 0}}, +/* pmd14 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(14),0, 0, 0}}, +/* pmd15 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(15),0, 0, 0}}, +/* pmd16 */ { PFM_REG_NOTIMPL, }, +/* pmd17 */ { PFM_REG_NOTIMPL, }, +/* pmd18 */ { PFM_REG_NOTIMPL, }, +/* pmd19 */ { PFM_REG_NOTIMPL, }, +/* pmd20 */ { PFM_REG_NOTIMPL, }, +/* pmd21 */ { PFM_REG_NOTIMPL, }, +/* pmd22 */ { PFM_REG_NOTIMPL, }, +/* pmd23 */ { PFM_REG_NOTIMPL, }, +/* pmd24 */ { PFM_REG_NOTIMPL, }, +/* pmd25 */ { PFM_REG_NOTIMPL, }, +/* pmd26 */ { PFM_REG_NOTIMPL, }, +/* pmd27 */ { PFM_REG_NOTIMPL, }, +/* pmd28 */ { PFM_REG_NOTIMPL, }, +/* pmd29 */ { PFM_REG_NOTIMPL, }, +/* pmd30 */ { PFM_REG_NOTIMPL, }, +/* pmd31 */ { PFM_REG_NOTIMPL, }, +/* pmd32 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP(33)|RDEP(36),0, 0, 0}, {RDEP(40),0, 0, 0}}, +/* pmd33 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP(32)|RDEP(36),0, 0, 0}, {RDEP(40),0, 0, 0}}, +/* pmd34 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP(35),0, 0, 0}, {RDEP(37),0, 0, 0}}, +/* pmd35 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP(34),0, 0, 0}, {RDEP(37),0, 0, 0}}, +/* pmd36 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP(32)|RDEP(33),0, 0, 0}, {RDEP(40),0, 0, 0}}, +/* pmd37 */ { PFM_REG_NOTIMPL, }, +/* pmd38 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd39 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd40 */ { PFM_REG_NOTIMPL, }, +/* pmd41 */ { PFM_REG_NOTIMPL, }, +/* pmd42 */ { PFM_REG_NOTIMPL, }, +/* pmd43 */ { PFM_REG_NOTIMPL, }, +/* pmd44 */ { PFM_REG_NOTIMPL, }, +/* pmd45 */ { PFM_REG_NOTIMPL, }, +/* pmd46 */ { PFM_REG_NOTIMPL, }, +/* pmd47 */ { PFM_REG_NOTIMPL, }, +/* pmd48 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd49 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd50 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd51 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd52 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd53 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd54 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd55 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd56 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd57 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd58 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd59 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd60 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd61 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd62 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd63 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, + { PFM_REG_END , 0, 0x0, -1, NULL, NULL, {0,}, {0,}}, /* end marker */ +}; + +/* + * PMC reserved fields must have their power-up values preserved + */ +static int +pfm_mont_reserved(unsigned int cnum, unsigned long *val, struct pt_regs *regs) +{ + unsigned long tmp1, tmp2, ival = *val; + + /* remove reserved areas from user value */ + tmp1 = ival & PMC_RSVD_MASK(cnum); + + /* get reserved fields values */ + tmp2 = PMC_DFL_VAL(cnum) & ~PMC_RSVD_MASK(cnum); + + *val = tmp1 | tmp2; + + DPRINT(("pmc[%d]=0x%lx, mask=0x%lx, reset=0x%lx, val=0x%lx\n", + cnum, ival, PMC_RSVD_MASK(cnum), PMC_DFL_VAL(cnum), *val)); + return 0; +} + +/* + * task can be NULL if the context is unloaded + */ +static int +pfm_mont_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnum, unsigned long *val, struct pt_regs *regs) +{ + int ret = 0; + unsigned long val32 = 0, val38 = 0, val41 = 0; + unsigned long tmpval; + int check_case1 = 0; + int is_loaded; + + /* first preserve the reserved fields */ + pfm_mont_reserved(cnum, val, regs); + + tmpval = *val; + + /* sanity check */ + if (ctx == NULL) return -EINVAL; + + is_loaded = ctx->ctx_state == PFM_CTX_LOADED || ctx->ctx_state == PFM_CTX_MASKED; + + /* + * we must clear the debug registers if pmc41 has a value which enable + * memory pipeline event constraints. In this case we need to clear the + * the debug registers if they have not yet been accessed. This is required + * to avoid picking stale state. + * PMC41 is "active" if: + * one of the pmc41.cfg_dtagXX field is different from 0x3 + * AND + * at the corresponding pmc41.en_dbrpXX is set. + * AND + * ctx_fl_using_dbreg == 0 (i.e., dbr not yet used) + */ + DPRINT(("cnum=%u val=0x%lx, using_dbreg=%d loaded=%d\n", cnum, tmpval, ctx->ctx_fl_using_dbreg, is_loaded)); + + if (cnum == 41 && is_loaded + && (tmpval & 0x1e00000000000) && (tmpval & 0x18181818UL) != 0x18181818UL && ctx->ctx_fl_using_dbreg == 0) { + + DPRINT(("pmc[%d]=0x%lx has active pmc41 settings, clearing dbr\n", cnum, tmpval)); + + /* don't mix debug with perfmon */ + if (task && (task->thread.flags & IA64_THREAD_DBG_VALID) != 0) return -EINVAL; + + /* + * a count of 0 will mark the debug registers if: + * AND + */ + ret = pfm_write_ibr_dbr(PFM_DATA_RR, ctx, NULL, 0, regs); + if (ret) return ret; + } + /* + * we must clear the (instruction) debug registers if: + * pmc38.ig_ibrpX is 0 (enabled) + * AND + * ctx_fl_using_dbreg == 0 (i.e., dbr not yet used) + */ + if (cnum == 38 && is_loaded && ((tmpval & 0x492UL) != 0x492UL) && ctx->ctx_fl_using_dbreg == 0) { + + DPRINT(("pmc38=0x%lx has active pmc38 settings, clearing ibr\n", tmpval)); + + /* don't mix debug with perfmon */ + if (task && (task->thread.flags & IA64_THREAD_DBG_VALID) != 0) return -EINVAL; + + /* + * a count of 0 will mark the debug registers as in use and also + * ensure that they are properly cleared. + */ + ret = pfm_write_ibr_dbr(PFM_CODE_RR, ctx, NULL, 0, regs); + if (ret) return ret; + + } + switch(cnum) { + case 32: val32 = *val; + val38 = ctx->ctx_pmcs[38]; + val41 = ctx->ctx_pmcs[41]; + check_case1 = 1; + break; + case 38: val38 = *val; + val32 = ctx->ctx_pmcs[32]; + val41 = ctx->ctx_pmcs[41]; + check_case1 = 1; + break; + case 41: val41 = *val; + val32 = ctx->ctx_pmcs[32]; + val38 = ctx->ctx_pmcs[38]; + check_case1 = 1; + break; + } + /* check illegal configuration which can produce inconsistencies in tagging + * i-side events in L1D and L2 caches + */ + if (check_case1) { + ret = (((val41 >> 45) & 0xf) == 0 && ((val32>>57) & 0x1) == 0) + && ((((val38>>1) & 0x3) == 0x2 || ((val38>>1) & 0x3) == 0) + || (((val38>>4) & 0x3) == 0x2 || ((val38>>4) & 0x3) == 0)); + if (ret) { + DPRINT(("invalid config pmc38=0x%lx pmc41=0x%lx pmc32=0x%lx\n", val38, val41, val32)); + return -EINVAL; + } + } + *val = tmpval; + return 0; +} + +/* + * impl_pmcs, impl_pmds are computed at runtime to minimize errors! + */ +static pmu_config_t pmu_conf_mont={ + .pmu_name = "Montecito", + .pmu_family = 0x20, + .flags = PFM_PMU_IRQ_RESEND, + .ovfl_val = (1UL << 47) - 1, + .pmd_desc = pfm_mont_pmd_desc, + .pmc_desc = pfm_mont_pmc_desc, + .num_ibrs = 8, + .num_dbrs = 8, + .use_rr_dbregs = 1 /* debug register are use for range retrictions */ +}; diff --git a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h index 8c648bf72bb..09b99029ac1 100644 --- a/include/asm-ia64/processor.h +++ b/include/asm-ia64/processor.h @@ -25,8 +25,8 @@ * Limits for PMC and PMD are set to less than maximum architected values * but should be sufficient for a while */ -#define IA64_NUM_PMC_REGS 32 -#define IA64_NUM_PMD_REGS 32 +#define IA64_NUM_PMC_REGS 64 +#define IA64_NUM_PMD_REGS 64 #define DEFAULT_MAP_BASE __IA64_UL_CONST(0x2000000000000000) #define DEFAULT_TASK_SIZE __IA64_UL_CONST(0xa000000000000000) -- GitLab From aa41eb9915de74fc6935792973bac4bd777ce218 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 16 Jan 2006 01:56:36 +0100 Subject: [PATCH 348/465] [PATCH] x86_64: Mark powernow k8 init functions as __cpuinit cpufreq init can be called when a CPU is set online. Need to make powernow-k8's initialisation functions __cpuinit to prevents oopses when a CPU is off/onlined on a AMD system Cc: trenn@suse.de Cc: mark.langsdorf@amd.com Cc: davej@redhat.com Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds --- arch/i386/kernel/cpu/cpufreq/powernow-k8.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index 0fbbd4c1072..e11a09207ec 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -980,7 +980,7 @@ static int powernowk8_verify(struct cpufreq_policy *pol) } /* per CPU init entry point to the driver */ -static int __init powernowk8_cpu_init(struct cpufreq_policy *pol) +static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) { struct powernow_k8_data *data; cpumask_t oldmask = CPU_MASK_ALL; @@ -1141,7 +1141,7 @@ static struct cpufreq_driver cpufreq_amd64_driver = { }; /* driver entry point for init */ -static int __init powernowk8_init(void) +static int __cpuinit powernowk8_init(void) { unsigned int i, supported_cpus = 0; -- GitLab From 5f8efbb96f4b2679dcbd2c115380a47bd2089dcd Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 16 Jan 2006 01:56:39 +0100 Subject: [PATCH 349/465] [PATCH] x86_64: Allow nesting of int3 by default for kprobes This unbreaks recursive kprobes which didn't work anymore due to an earlier patch which converted the debug entry point to use an IST. This also allows nesting of the debug entry point too. Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds --- arch/x86_64/kernel/asm-offsets.c | 5 ++--- arch/x86_64/kernel/entry.S | 12 +++++------- include/asm-x86_64/page.h | 7 +++++++ include/asm-x86_64/processor.h | 7 ------- 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/arch/x86_64/kernel/asm-offsets.c b/arch/x86_64/kernel/asm-offsets.c index cfb4f9cebea..38834bbbae1 100644 --- a/arch/x86_64/kernel/asm-offsets.c +++ b/arch/x86_64/kernel/asm-offsets.c @@ -43,6 +43,7 @@ int main(void) ENTRY(irqcount); ENTRY(cpunumber); ENTRY(irqstackptr); + ENTRY(data_offset); BLANK(); #undef ENTRY #ifdef CONFIG_IA32_EMULATION @@ -66,8 +67,6 @@ int main(void) DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address)); DEFINE(pbe_next, offsetof(struct pbe, next)); BLANK(); -#if DEBUG_STKSZ > EXCEPTION_STKSZ - DEFINE(DEBUG_IST, DEBUG_STACK); -#endif + DEFINE(TSS_ist, offsetof(struct tss_struct, ist)); return 0; } diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S index 632fc0f59fc..dbdba56e8fa 100644 --- a/arch/x86_64/kernel/entry.S +++ b/arch/x86_64/kernel/entry.S @@ -41,6 +41,7 @@ #include #include #include +#include .code64 @@ -674,9 +675,6 @@ ENTRY(spurious_interrupt) /* error code is on the stack already */ /* handle NMI like exceptions that can happen everywhere */ -#ifndef DEBUG_IST -# define DEBUG_IST 0 -#endif .macro paranoidentry sym, ist=0 SAVE_ALL cld @@ -695,11 +693,11 @@ ENTRY(spurious_interrupt) movq ORIG_RAX(%rsp),%rsi movq $-1,ORIG_RAX(%rsp) .if \ist - subq $EXCEPTION_STACK_SIZE, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp) + subq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp) .endif call \sym .if \ist - addq $EXCEPTION_STACK_SIZE, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp) + addq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp) .endif cli .endm @@ -918,7 +916,7 @@ KPROBE_ENTRY(debug) INTR_FRAME pushq $0 CFI_ADJUST_CFA_OFFSET 8 - paranoidentry do_debug, DEBUG_IST + paranoidentry do_debug, DEBUG_STACK jmp paranoid_exit CFI_ENDPROC .previous .text @@ -976,7 +974,7 @@ KPROBE_ENTRY(int3) INTR_FRAME pushq $0 CFI_ADJUST_CFA_OFFSET 8 - paranoidentry do_int3, DEBUG_IST + paranoidentry do_int3, DEBUG_STACK jmp paranoid_exit CFI_ENDPROC .previous .text diff --git a/include/asm-x86_64/page.h b/include/asm-x86_64/page.h index dcbb4fcd9a1..615e3e49492 100644 --- a/include/asm-x86_64/page.h +++ b/include/asm-x86_64/page.h @@ -26,6 +26,13 @@ #define IRQSTACK_ORDER 2 #define IRQSTACKSIZE (PAGE_SIZE << IRQSTACK_ORDER) +#define STACKFAULT_STACK 1 +#define DOUBLEFAULT_STACK 2 +#define NMI_STACK 3 +#define DEBUG_STACK 4 +#define MCE_STACK 5 +#define N_EXCEPTION_STACKS 5 /* hw limit: 7 */ + #define LARGE_PAGE_MASK (~(LARGE_PAGE_SIZE-1)) #define LARGE_PAGE_SIZE (1UL << PMD_SHIFT) diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h index 87a282b1043..a1ba7c97465 100644 --- a/include/asm-x86_64/processor.h +++ b/include/asm-x86_64/processor.h @@ -273,13 +273,6 @@ struct thread_struct { #define INIT_MMAP \ { &init_mm, 0, 0, NULL, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL } -#define STACKFAULT_STACK 1 -#define DOUBLEFAULT_STACK 2 -#define NMI_STACK 3 -#define DEBUG_STACK 4 -#define MCE_STACK 5 -#define N_EXCEPTION_STACKS 5 /* hw limit: 7 */ - #define start_thread(regs,new_rip,new_rsp) do { \ asm volatile("movl %0,%%fs; movl %0,%%es; movl %0,%%ds": :"r" (0)); \ load_gs_index(0); \ -- GitLab From e25db98d9ae542f95d139e316a6d490ceddd141e Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 16 Jan 2006 01:56:42 +0100 Subject: [PATCH 350/465] [PATCH] x86_64: Only let user select PM timer support when EMBEDDED To avoid mistakes. I got a few reports where people got broken timing because they didn't have the PMTIMER fallback. Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds --- arch/x86_64/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 2efc4be2270..787feff0e8a 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -350,7 +350,7 @@ config HPET_TIMER . config X86_PM_TIMER - bool "PM timer" + bool "PM timer" if EMBEDDED depends on ACPI default y help -- GitLab From 5b74357328eb325c12ea76f043524e7924a021e4 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Mon, 16 Jan 2006 01:56:45 +0100 Subject: [PATCH 351/465] [PATCH] x86_64: lapic resume uses correct base address uses correct lapic base address. The set_fixmap appears useless. Signed-off-by: Shaohua Li Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds --- arch/x86_64/kernel/apic.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c index 8fdd089fd17..5d3c5b07b8d 100644 --- a/arch/x86_64/kernel/apic.c +++ b/arch/x86_64/kernel/apic.c @@ -499,13 +499,10 @@ static int lapic_resume(struct sys_device *dev) if (!apic_pm_state.active) return 0; - /* XXX: Pavel needs this for S3 resume, but can't explain why */ - set_fixmap_nocache(FIX_APIC_BASE, APIC_DEFAULT_PHYS_BASE); - local_irq_save(flags); rdmsr(MSR_IA32_APICBASE, l, h); l &= ~MSR_IA32_APICBASE_BASE; - l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE; + l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; wrmsr(MSR_IA32_APICBASE, l, h); apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED); apic_write(APIC_ID, apic_pm_state.apic_id); -- GitLab From 142a64a650fa5786c2ecea3de5ae3d5a2de72312 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 16 Jan 2006 01:56:48 +0100 Subject: [PATCH 352/465] [PATCH] x86_64: set do_not_nx as cpuinitdata 'check_efer' uses 'do_not_nx'. Hotpluged CPU could wrongly disable NX. Signed-off-by: Shaohua Li Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds --- arch/x86_64/kernel/setup64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c index 6eff51e9400..8ac4db09610 100644 --- a/arch/x86_64/kernel/setup64.c +++ b/arch/x86_64/kernel/setup64.c @@ -38,7 +38,7 @@ struct desc_ptr idt_descr = { 256 * 16, (unsigned long) idt_table }; char boot_cpu_stack[IRQSTACKSIZE] __attribute__((section(".bss.page_aligned"))); unsigned long __supported_pte_mask __read_mostly = ~0UL; -static int do_not_nx __initdata = 0; +static int do_not_nx __cpuinitdata = 0; /* noexec=on|off Control non executable mappings for 64bit processes. -- GitLab From ee408c79420b6a437332d6977fe33ab72c36dc97 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 16 Jan 2006 01:56:51 +0100 Subject: [PATCH 353/465] [PATCH] x86_64: Don't try to put kernel page tables beyond ZONE_DMA32. For not fully explained reasons it broke mem=... on several setups. Also minor cleanup. Cc: axboe@suse.de Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds --- arch/x86_64/mm/init.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c index eca60125efc..ef84106c150 100644 --- a/arch/x86_64/mm/init.c +++ b/arch/x86_64/mm/init.c @@ -262,19 +262,11 @@ static void __init find_early_table_space(unsigned long end) tables = round_up(puds * sizeof(pud_t), PAGE_SIZE) + round_up(pmds * sizeof(pmd_t), PAGE_SIZE); - /* Put page tables beyond the DMA zones if possible. - RED-PEN might be better to spread them out more over - memory to avoid hotspots */ - if (end > MAX_DMA32_PFN< MAX_DMA_PFN << PAGE_SHIFT) - start = MAX_DMA_PFN << PAGE_SHIFT; - else - start = 0x8000; - - table_start = find_e820_area(start, end, tables); - if (table_start == -1) - table_start = find_e820_area(0x8000, end, tables); + /* RED-PEN putting page tables only on node 0 could + cause a hotspot and fill up ZONE_DMA. The page tables + need roughly 0.5KB per GB. */ + start = 0x8000; + table_start = find_e820_area(start, end, tables); if (table_start == -1UL) panic("Cannot find space for the kernel page tables"); -- GitLab From 5580eceed2014135231acb3e6906accf97e10f3c Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 16 Jan 2006 01:56:54 +0100 Subject: [PATCH 354/465] [PATCH] x86_64: Increase NR_IRQ_VECTORS to 32 * NR_CPUS This prevents running out of GSIs on large Unisys ES7000 machines. Follows i386 Cc: "Protasevich, Natalie" Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds --- include/asm-x86_64/irq.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/asm-x86_64/irq.h b/include/asm-x86_64/irq.h index fb724ba37ae..9db5a1b4f7b 100644 --- a/include/asm-x86_64/irq.h +++ b/include/asm-x86_64/irq.h @@ -36,7 +36,7 @@ #define NR_IRQ_VECTORS NR_IRQS #else #define NR_IRQS 224 -#define NR_IRQ_VECTORS 1024 +#define NR_IRQ_VECTORS (32 * NR_CPUS) #endif static __inline__ int irq_canonicalize(int irq) -- GitLab From f74e6670c4a788c9a0c52ab2036d8ac6be12f1d8 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 16 Jan 2006 11:33:09 -0800 Subject: [PATCH 355/465] x86-64: fix initrd freeing The comparison of the initrd start address against "&_end" is unnecessary and incorrect. Make it match the x86 code that just compares the passed-in arguments. Signed-off-by: Linus Torvalds --- arch/x86_64/mm/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c index ef84106c150..307d1ac0ef3 100644 --- a/arch/x86_64/mm/init.c +++ b/arch/x86_64/mm/init.c @@ -531,7 +531,7 @@ void mark_rodata_ro(void) #ifdef CONFIG_BLK_DEV_INITRD void free_initrd_mem(unsigned long start, unsigned long end) { - if (start < (unsigned long)&_end) + if (start >= end) return; printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); for (; start < end; start += PAGE_SIZE) { -- GitLab From 1681b8e1588f9119899e422181f728b197b1fe34 Mon Sep 17 00:00:00 2001 From: Yasunori Goto Date: Sat, 7 Jan 2006 11:50:38 +0900 Subject: [PATCH 356/465] [IA64] Simple memory hot-add for ia64. First step to memory hotplug for ia64 (add only, all new memory is added to node 0, does not use ZONE_EASY_RECLAIM yet). Signed-off-by: Yasunori Goto Signed-off-by: Tony Luck --- arch/ia64/mm/init.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index e3215ba64ff..b38b6d213c1 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -635,3 +635,39 @@ mem_init (void) ia32_mem_init(); #endif } + +#ifdef CONFIG_MEMORY_HOTPLUG +void online_page(struct page *page) +{ + ClearPageReserved(page); + set_page_count(page, 1); + __free_page(page); + totalram_pages++; + num_physpages++; +} + +int add_memory(u64 start, u64 size) +{ + pg_data_t *pgdat; + struct zone *zone; + unsigned long start_pfn = start >> PAGE_SHIFT; + unsigned long nr_pages = size >> PAGE_SHIFT; + int ret; + + pgdat = NODE_DATA(0); + + zone = pgdat->node_zones + ZONE_NORMAL; + ret = __add_pages(zone, start_pfn, nr_pages); + + if (ret) + printk("%s: Problem encountered in __add_pages() as ret=%d\n", + __FUNCTION__, ret); + + return ret; +} + +int remove_memory(u64 start, u64 size) +{ + return -EINVAL; +} +#endif -- GitLab From 01ffe339e3a0ba5ecbeb2b3b5abac7b3ef90f374 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Tue, 17 Jan 2006 09:02:07 +1100 Subject: [PATCH 357/465] Make alloc_page_buffers() initialise buffer_heads using init_buffer(), like other routines here, to ensure buffers are correctly initialised with respect to b_private/b_end_io. Fixes an odd interaction between XFS and reiserfs. Signed-off-by: Nathan Scott --- fs/buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/buffer.c b/fs/buffer.c index 7cdf48a9a50..3dc712f29d2 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -1027,7 +1027,7 @@ try_again: /* Link the buffer to its page */ set_bh_page(bh, page, offset); - bh->b_end_io = NULL; + init_buffer(bh, NULL, NULL); } return head; /* -- GitLab From 7b9c8ba2d634a0467a8a36018a28624563f34f47 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Mon, 16 Jan 2006 13:45:23 +0900 Subject: [PATCH 358/465] [IA64] Stop multiple pci_claim_resource() call for the same resource This patch fixes the bug that pci_claim_resource() is called multiple times for the same P2P bridge's resource structures if P2P bridges require their own PCI I/O resources. Signed-off-by: Kenji Kaneshige Signed-off-by: Tony Luck --- arch/ia64/pci/pci.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 30dbc98bf0b..d27ecdcb6fc 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -454,14 +454,13 @@ static int __devinit is_valid_resource(struct pci_dev *dev, int idx) return 0; } -static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) +static void __devinit +pcibios_fixup_resources(struct pci_dev *dev, int start, int limit) { struct pci_bus_region region; int i; - int limit = (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) ? \ - PCI_BRIDGE_RESOURCES : PCI_NUM_RESOURCES; - for (i = 0; i < limit; i++) { + for (i = start; i < limit; i++) { if (!dev->resource[i].flags) continue; region.start = dev->resource[i].start; @@ -472,6 +471,16 @@ static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) } } +static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) +{ + pcibios_fixup_resources(dev, 0, PCI_BRIDGE_RESOURCES); +} + +static void __devinit pcibios_fixup_bridge_resources(struct pci_dev *dev) +{ + pcibios_fixup_resources(dev, PCI_BRIDGE_RESOURCES, PCI_NUM_RESOURCES); +} + /* * Called after each bus is probed, but before its children are examined. */ @@ -482,7 +491,7 @@ pcibios_fixup_bus (struct pci_bus *b) if (b->self) { pci_read_bridge_bases(b); - pcibios_fixup_device_resources(b->self); + pcibios_fixup_bridge_resources(b->self); } list_for_each_entry(dev, &b->devices, bus_list) pcibios_fixup_device_resources(dev); -- GitLab From f15ac5801fdc1b217c3b8b5dbc63a09371d2ee4d Mon Sep 17 00:00:00 2001 From: "Xu, Anthony" Date: Mon, 9 Jan 2006 10:36:35 +0800 Subject: [PATCH 359/465] [IA64] pal cache flush patch Because PAL spec has changed since 2002, you can goto http://developer.intel.com/design/itanium/manuals/iiasdmanual.htm to download new SDM, all PAL calls should be invoked with psr.ic=1, and it's caller's responsibility to handle possible tlb miss. Ia64_pal_cache_flush was written according to old spec, it is obsolete, and this patch has ia64_pal_cache_flush conform to new spec. Signed-off-by Anthony Xu Signed-off-by: Tony Luck --- include/asm-ia64/pal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/asm-ia64/pal.h b/include/asm-ia64/pal.h index e828377ad29..7708ec669a3 100644 --- a/include/asm-ia64/pal.h +++ b/include/asm-ia64/pal.h @@ -927,7 +927,7 @@ static inline s64 ia64_pal_cache_flush (u64 cache_type, u64 invalidate, u64 *progress, u64 *vector) { struct ia64_pal_retval iprv; - PAL_CALL_IC_OFF(iprv, PAL_CACHE_FLUSH, cache_type, invalidate, *progress); + PAL_CALL(iprv, PAL_CACHE_FLUSH, cache_type, invalidate, *progress); if (vector) *vector = iprv.v0; *progress = iprv.v1; -- GitLab From 506eecde44d54e838c61c2af38630e8ebb16363e Mon Sep 17 00:00:00 2001 From: Jody McIntyre Date: Mon, 16 Jan 2006 19:21:57 -0500 Subject: [PATCH 360/465] Actually remove amdtp.[ch], cmp.[ch]. The feature removal was done in 7301c8d3a05dc52d33598364da7c4eb6ab6357eb but these files were not removed for some reason. Signed-off-by: Jody McIntyre --- drivers/ieee1394/amdtp.c | 1297 -------------------------------------- drivers/ieee1394/amdtp.h | 84 --- drivers/ieee1394/cmp.c | 311 --------- drivers/ieee1394/cmp.h | 31 - 4 files changed, 1723 deletions(-) delete mode 100644 drivers/ieee1394/amdtp.c delete mode 100644 drivers/ieee1394/amdtp.h delete mode 100644 drivers/ieee1394/cmp.c delete mode 100644 drivers/ieee1394/cmp.h diff --git a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c deleted file mode 100644 index 17390d762cf..00000000000 --- a/drivers/ieee1394/amdtp.c +++ /dev/null @@ -1,1297 +0,0 @@ -/* -*- c-basic-offset: 8 -*- - * - * amdtp.c - Audio and Music Data Transmission Protocol Driver - * Copyright (C) 2001 Kristian Høgsberg - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* OVERVIEW - * -------- - * - * The AMDTP driver is designed to expose the IEEE1394 bus as a - * regular OSS soundcard, i.e. you can link /dev/dsp to /dev/amdtp and - * then your favourite MP3 player, game or whatever sound program will - * output to an IEEE1394 isochronous channel. The signal destination - * could be a set of IEEE1394 loudspeakers (if and when such things - * become available) or an amplifier with IEEE1394 input (like the - * Sony STR-LSA1). The driver only handles the actual streaming, some - * connection management is also required for this to actually work. - * That is outside the scope of this driver, and furthermore it is not - * really standardized yet. - * - * The Audio and Music Data Tranmission Protocol is available at - * - * http://www.1394ta.org/Download/Technology/Specifications/2001/AM20Final-jf2.pdf - * - * - * TODO - * ---- - * - * - We should be able to change input sample format between LE/BE, as - * we already shift the bytes around when we construct the iso - * packets. - * - * - Fix DMA stop after bus reset! - * - * - Clean up iso context handling in ohci1394. - * - * - * MAYBE TODO - * ---------- - * - * - Receive data for local playback or recording. Playback requires - * soft syncing with the sound card. - * - * - Signal processing, i.e. receive packets, do some processing, and - * transmit them again using the same packet structure and timestamps - * offset by processing time. - * - * - Maybe make an ALSA interface, that is, create a file_ops - * implementation that recognizes ALSA ioctls and uses defaults for - * things that can't be controlled through ALSA (iso channel). - * - * Changes: - * - * - Audit copy_from_user in amdtp_write. - * Daniele Bellucci - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hosts.h" -#include "highlevel.h" -#include "ieee1394.h" -#include "ieee1394_core.h" -#include "ohci1394.h" - -#include "amdtp.h" -#include "cmp.h" - -#define FMT_AMDTP 0x10 -#define FDF_AM824 0x00 -#define FDF_SFC_32KHZ 0x00 -#define FDF_SFC_44K1HZ 0x01 -#define FDF_SFC_48KHZ 0x02 -#define FDF_SFC_88K2HZ 0x03 -#define FDF_SFC_96KHZ 0x04 -#define FDF_SFC_176K4HZ 0x05 -#define FDF_SFC_192KHZ 0x06 - -struct descriptor_block { - struct output_more_immediate { - u32 control; - u32 pad0; - u32 skip; - u32 pad1; - u32 header[4]; - } header_desc; - - struct output_last { - u32 control; - u32 data_address; - u32 branch; - u32 status; - } payload_desc; -}; - -struct packet { - struct descriptor_block *db; - dma_addr_t db_bus; - struct iso_packet *payload; - dma_addr_t payload_bus; -}; - -#include - -#if defined __BIG_ENDIAN_BITFIELD - -struct iso_packet { - /* First quadlet */ - unsigned int dbs : 8; - unsigned int eoh0 : 2; - unsigned int sid : 6; - - unsigned int dbc : 8; - unsigned int fn : 2; - unsigned int qpc : 3; - unsigned int sph : 1; - unsigned int reserved : 2; - - /* Second quadlet */ - unsigned int fdf : 8; - unsigned int eoh1 : 2; - unsigned int fmt : 6; - - unsigned int syt : 16; - - quadlet_t data[0]; -}; - -#elif defined __LITTLE_ENDIAN_BITFIELD - -struct iso_packet { - /* First quadlet */ - unsigned int sid : 6; - unsigned int eoh0 : 2; - unsigned int dbs : 8; - - unsigned int reserved : 2; - unsigned int sph : 1; - unsigned int qpc : 3; - unsigned int fn : 2; - unsigned int dbc : 8; - - /* Second quadlet */ - unsigned int fmt : 6; - unsigned int eoh1 : 2; - unsigned int fdf : 8; - - unsigned int syt : 16; - - quadlet_t data[0]; -}; - -#else - -#error Unknown bitfield type - -#endif - -struct fraction { - int integer; - int numerator; - int denominator; -}; - -#define PACKET_LIST_SIZE 256 -#define MAX_PACKET_LISTS 4 - -struct packet_list { - struct list_head link; - int last_cycle_count; - struct packet packets[PACKET_LIST_SIZE]; -}; - -#define BUFFER_SIZE 128 - -/* This implements a circular buffer for incoming samples. */ - -struct buffer { - size_t head, tail, length, size; - unsigned char data[0]; -}; - -struct stream { - int iso_channel; - int format; - int rate; - int dimension; - int fdf; - int mode; - int sample_format; - struct cmp_pcr *opcr; - - /* Input samples are copied here. */ - struct buffer *input; - - /* ISO Packer state */ - unsigned char dbc; - struct packet_list *current_packet_list; - int current_packet; - struct fraction ready_samples, samples_per_cycle; - - /* We use these to generate control bits when we are packing - * iec958 data. - */ - int iec958_frame_count; - int iec958_rate_code; - - /* The cycle_count and cycle_offset fields are used for the - * synchronization timestamps (syt) in the cip header. They - * are incremented by at least a cycle every time we put a - * time stamp in a packet. As we don't time stamp all - * packages, cycle_count isn't updated in every cycle, and - * sometimes it's incremented by 2. Thus, we have - * cycle_count2, which is simply incremented by one with each - * packet, so we can compare it to the transmission time - * written back in the dma programs. - */ - atomic_t cycle_count, cycle_count2; - struct fraction cycle_offset, ticks_per_syt_offset; - int syt_interval; - int stale_count; - - /* Theses fields control the sample output to the DMA engine. - * The dma_packet_lists list holds packet lists currently - * queued for dma; the head of the list is currently being - * processed. The last program in a packet list generates an - * interrupt, which removes the head from dma_packet_lists and - * puts it back on the free list. - */ - struct list_head dma_packet_lists; - struct list_head free_packet_lists; - wait_queue_head_t packet_list_wait; - spinlock_t packet_list_lock; - struct ohci1394_iso_tasklet iso_tasklet; - struct pci_pool *descriptor_pool, *packet_pool; - - /* Streams at a host controller are chained through this field. */ - struct list_head link; - struct amdtp_host *host; -}; - -struct amdtp_host { - struct hpsb_host *host; - struct ti_ohci *ohci; - struct list_head stream_list; - spinlock_t stream_list_lock; -}; - -static struct hpsb_highlevel amdtp_highlevel; - - -/* FIXME: This doesn't belong here... */ - -#define OHCI1394_CONTEXT_CYCLE_MATCH 0x80000000 -#define OHCI1394_CONTEXT_RUN 0x00008000 -#define OHCI1394_CONTEXT_WAKE 0x00001000 -#define OHCI1394_CONTEXT_DEAD 0x00000800 -#define OHCI1394_CONTEXT_ACTIVE 0x00000400 - -static void ohci1394_start_it_ctx(struct ti_ohci *ohci, int ctx, - dma_addr_t first_cmd, int z, int cycle_match) -{ - reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1 << ctx); - reg_write(ohci, OHCI1394_IsoXmitCommandPtr + ctx * 16, first_cmd | z); - reg_write(ohci, OHCI1394_IsoXmitContextControlClear + ctx * 16, ~0); - wmb(); - reg_write(ohci, OHCI1394_IsoXmitContextControlSet + ctx * 16, - OHCI1394_CONTEXT_CYCLE_MATCH | (cycle_match << 16) | - OHCI1394_CONTEXT_RUN); -} - -static void ohci1394_wake_it_ctx(struct ti_ohci *ohci, int ctx) -{ - reg_write(ohci, OHCI1394_IsoXmitContextControlSet + ctx * 16, - OHCI1394_CONTEXT_WAKE); -} - -static void ohci1394_stop_it_ctx(struct ti_ohci *ohci, int ctx, int synchronous) -{ - u32 control; - int wait; - - reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 1 << ctx); - reg_write(ohci, OHCI1394_IsoXmitContextControlClear + ctx * 16, - OHCI1394_CONTEXT_RUN); - wmb(); - - if (synchronous) { - for (wait = 0; wait < 5; wait++) { - control = reg_read(ohci, OHCI1394_IsoXmitContextControlSet + ctx * 16); - if ((control & OHCI1394_CONTEXT_ACTIVE) == 0) - break; - - schedule_timeout_interruptible(1); - } - } -} - -/* Note: we can test if free_packet_lists is empty without aquiring - * the packet_list_lock. The interrupt handler only adds to the free - * list, there is no race condition between testing the list non-empty - * and acquiring the lock. - */ - -static struct packet_list *stream_get_free_packet_list(struct stream *s) -{ - struct packet_list *pl; - unsigned long flags; - - if (list_empty(&s->free_packet_lists)) - return NULL; - - spin_lock_irqsave(&s->packet_list_lock, flags); - pl = list_entry(s->free_packet_lists.next, struct packet_list, link); - list_del(&pl->link); - spin_unlock_irqrestore(&s->packet_list_lock, flags); - - return pl; -} - -static void stream_start_dma(struct stream *s, struct packet_list *pl) -{ - u32 syt_cycle, cycle_count, start_cycle; - - cycle_count = reg_read(s->host->ohci, - OHCI1394_IsochronousCycleTimer) >> 12; - syt_cycle = (pl->last_cycle_count - PACKET_LIST_SIZE + 1) & 0x0f; - - /* We program the DMA controller to start transmission at - * least 17 cycles from now - this happens when the lower four - * bits of cycle_count is 0x0f and syt_cycle is 0, in this - * case the start cycle is cycle_count - 15 + 32. */ - start_cycle = (cycle_count & ~0x0f) + 32 + syt_cycle; - if ((start_cycle & 0x1fff) >= 8000) - start_cycle = start_cycle - 8000 + 0x2000; - - ohci1394_start_it_ctx(s->host->ohci, s->iso_tasklet.context, - pl->packets[0].db_bus, 3, - start_cycle & 0x7fff); -} - -static void stream_put_dma_packet_list(struct stream *s, - struct packet_list *pl) -{ - unsigned long flags; - struct packet_list *prev; - - /* Remember the cycle_count used for timestamping the last packet. */ - pl->last_cycle_count = atomic_read(&s->cycle_count2) - 1; - pl->packets[PACKET_LIST_SIZE - 1].db->payload_desc.branch = 0; - - spin_lock_irqsave(&s->packet_list_lock, flags); - list_add_tail(&pl->link, &s->dma_packet_lists); - spin_unlock_irqrestore(&s->packet_list_lock, flags); - - prev = list_entry(pl->link.prev, struct packet_list, link); - if (pl->link.prev != &s->dma_packet_lists) { - struct packet *last = &prev->packets[PACKET_LIST_SIZE - 1]; - last->db->payload_desc.branch = pl->packets[0].db_bus | 3; - last->db->header_desc.skip = pl->packets[0].db_bus | 3; - ohci1394_wake_it_ctx(s->host->ohci, s->iso_tasklet.context); - } - else - stream_start_dma(s, pl); -} - -static void stream_shift_packet_lists(unsigned long l) -{ - struct stream *s = (struct stream *) l; - struct packet_list *pl; - struct packet *last; - int diff; - - if (list_empty(&s->dma_packet_lists)) { - HPSB_ERR("empty dma_packet_lists in %s", __FUNCTION__); - return; - } - - /* Now that we know the list is non-empty, we can get the head - * of the list without locking, because the process context - * only adds to the tail. - */ - pl = list_entry(s->dma_packet_lists.next, struct packet_list, link); - last = &pl->packets[PACKET_LIST_SIZE - 1]; - - /* This is weird... if we stop dma processing in the middle of - * a packet list, the dma context immediately generates an - * interrupt if we enable it again later. This only happens - * when amdtp_release is interrupted while waiting for dma to - * complete, though. Anyway, we detect this by seeing that - * the status of the dma descriptor that we expected an - * interrupt from is still 0. - */ - if (last->db->payload_desc.status == 0) { - HPSB_INFO("weird interrupt..."); - return; - } - - /* If the last descriptor block does not specify a branch - * address, we have a sample underflow. - */ - if (last->db->payload_desc.branch == 0) - HPSB_INFO("FIXME: sample underflow..."); - - /* Here we check when (which cycle) the last packet was sent - * and compare it to what the iso packer was using at the - * time. If there is a mismatch, we adjust the cycle count in - * the iso packer. However, there are still up to - * MAX_PACKET_LISTS packet lists queued with bad time stamps, - * so we disable time stamp monitoring for the next - * MAX_PACKET_LISTS packet lists. - */ - diff = (last->db->payload_desc.status - pl->last_cycle_count) & 0xf; - if (diff > 0 && s->stale_count == 0) { - atomic_add(diff, &s->cycle_count); - atomic_add(diff, &s->cycle_count2); - s->stale_count = MAX_PACKET_LISTS; - } - - if (s->stale_count > 0) - s->stale_count--; - - /* Finally, we move the packet list that was just processed - * back to the free list, and notify any waiters. - */ - spin_lock(&s->packet_list_lock); - list_del(&pl->link); - list_add_tail(&pl->link, &s->free_packet_lists); - spin_unlock(&s->packet_list_lock); - - wake_up_interruptible(&s->packet_list_wait); -} - -static struct packet *stream_current_packet(struct stream *s) -{ - if (s->current_packet_list == NULL && - (s->current_packet_list = stream_get_free_packet_list(s)) == NULL) - return NULL; - - return &s->current_packet_list->packets[s->current_packet]; -} - -static void stream_queue_packet(struct stream *s) -{ - s->current_packet++; - if (s->current_packet == PACKET_LIST_SIZE) { - stream_put_dma_packet_list(s, s->current_packet_list); - s->current_packet_list = NULL; - s->current_packet = 0; - } -} - -/* Integer fractional math. When we transmit a 44k1Hz signal we must - * send 5 41/80 samples per isochronous cycle, as these occur 8000 - * times a second. Of course, we must send an integral number of - * samples in a packet, so we use the integer math to alternate - * between sending 5 and 6 samples per packet. - */ - -static void fraction_init(struct fraction *f, int numerator, int denominator) -{ - f->integer = numerator / denominator; - f->numerator = numerator % denominator; - f->denominator = denominator; -} - -static __inline__ void fraction_add(struct fraction *dst, - struct fraction *src1, - struct fraction *src2) -{ - /* assert: src1->denominator == src2->denominator */ - - int sum, denom; - - /* We use these two local variables to allow gcc to optimize - * the division and the modulo into only one division. */ - - sum = src1->numerator + src2->numerator; - denom = src1->denominator; - dst->integer = src1->integer + src2->integer + sum / denom; - dst->numerator = sum % denom; - dst->denominator = denom; -} - -static __inline__ void fraction_sub_int(struct fraction *dst, - struct fraction *src, int integer) -{ - dst->integer = src->integer - integer; - dst->numerator = src->numerator; - dst->denominator = src->denominator; -} - -static __inline__ int fraction_floor(struct fraction *frac) -{ - return frac->integer; -} - -static __inline__ int fraction_ceil(struct fraction *frac) -{ - return frac->integer + (frac->numerator > 0 ? 1 : 0); -} - -static void packet_initialize(struct packet *p, struct packet *next) -{ - /* Here we initialize the dma descriptor block for - * transferring one iso packet. We use two descriptors per - * packet: an OUTPUT_MORE_IMMMEDIATE descriptor for the - * IEEE1394 iso packet header and an OUTPUT_LAST descriptor - * for the payload. - */ - - p->db->header_desc.control = - DMA_CTL_OUTPUT_MORE | DMA_CTL_IMMEDIATE | 8; - - if (next) { - p->db->payload_desc.control = - DMA_CTL_OUTPUT_LAST | DMA_CTL_BRANCH; - p->db->payload_desc.branch = next->db_bus | 3; - p->db->header_desc.skip = next->db_bus | 3; - } - else { - p->db->payload_desc.control = - DMA_CTL_OUTPUT_LAST | DMA_CTL_BRANCH | - DMA_CTL_UPDATE | DMA_CTL_IRQ; - p->db->payload_desc.branch = 0; - p->db->header_desc.skip = 0; - } - p->db->payload_desc.data_address = p->payload_bus; - p->db->payload_desc.status = 0; -} - -static struct packet_list *packet_list_alloc(struct stream *s) -{ - int i; - struct packet_list *pl; - struct packet *next; - - pl = kmalloc(sizeof *pl, SLAB_KERNEL); - if (pl == NULL) - return NULL; - - for (i = 0; i < PACKET_LIST_SIZE; i++) { - struct packet *p = &pl->packets[i]; - p->db = pci_pool_alloc(s->descriptor_pool, SLAB_KERNEL, - &p->db_bus); - p->payload = pci_pool_alloc(s->packet_pool, SLAB_KERNEL, - &p->payload_bus); - } - - for (i = 0; i < PACKET_LIST_SIZE; i++) { - if (i < PACKET_LIST_SIZE - 1) - next = &pl->packets[i + 1]; - else - next = NULL; - packet_initialize(&pl->packets[i], next); - } - - return pl; -} - -static void packet_list_free(struct packet_list *pl, struct stream *s) -{ - int i; - - for (i = 0; i < PACKET_LIST_SIZE; i++) { - struct packet *p = &pl->packets[i]; - pci_pool_free(s->descriptor_pool, p->db, p->db_bus); - pci_pool_free(s->packet_pool, p->payload, p->payload_bus); - } - kfree(pl); -} - -static struct buffer *buffer_alloc(int size) -{ - struct buffer *b; - - b = kmalloc(sizeof *b + size, SLAB_KERNEL); - if (b == NULL) - return NULL; - b->head = 0; - b->tail = 0; - b->length = 0; - b->size = size; - - return b; -} - -static unsigned char *buffer_get_bytes(struct buffer *buffer, int size) -{ - unsigned char *p; - - if (buffer->head + size > buffer->size) - BUG(); - - p = &buffer->data[buffer->head]; - buffer->head += size; - if (buffer->head == buffer->size) - buffer->head = 0; - buffer->length -= size; - - return p; -} - -static unsigned char *buffer_put_bytes(struct buffer *buffer, - size_t max, size_t *actual) -{ - size_t length; - unsigned char *p; - - p = &buffer->data[buffer->tail]; - length = min(buffer->size - buffer->length, max); - if (buffer->tail + length < buffer->size) { - *actual = length; - buffer->tail += length; - } - else { - *actual = buffer->size - buffer->tail; - buffer->tail = 0; - } - - buffer->length += *actual; - return p; -} - -static u32 get_iec958_header_bits(struct stream *s, int sub_frame, u32 sample) -{ - int csi, parity, shift; - int block_start; - u32 bits; - - switch (s->iec958_frame_count) { - case 1: - csi = s->format == AMDTP_FORMAT_IEC958_AC3; - break; - case 2: - case 9: - csi = 1; - break; - case 24 ... 27: - csi = (s->iec958_rate_code >> (27 - s->iec958_frame_count)) & 0x01; - break; - default: - csi = 0; - break; - } - - block_start = (s->iec958_frame_count == 0 && sub_frame == 0); - - /* The parity bit is the xor of the sample bits and the - * channel status info bit. */ - for (shift = 16, parity = sample ^ csi; shift > 0; shift >>= 1) - parity ^= (parity >> shift); - - bits = (block_start << 5) | /* Block start bit */ - ((sub_frame == 0) << 4) | /* Subframe bit */ - ((parity & 1) << 3) | /* Parity bit */ - (csi << 2); /* Channel status info bit */ - - return bits; -} - -static u32 get_header_bits(struct stream *s, int sub_frame, u32 sample) -{ - switch (s->format) { - case AMDTP_FORMAT_IEC958_PCM: - case AMDTP_FORMAT_IEC958_AC3: - return get_iec958_header_bits(s, sub_frame, sample); - - case AMDTP_FORMAT_RAW: - return 0x40; - - default: - return 0; - } -} - -static void fill_payload_le16(struct stream *s, quadlet_t *data, int nevents) -{ - quadlet_t *event, sample, bits; - unsigned char *p; - int i, j; - - for (i = 0, event = data; i < nevents; i++) { - - for (j = 0; j < s->dimension; j++) { - p = buffer_get_bytes(s->input, 2); - sample = (p[1] << 16) | (p[0] << 8); - bits = get_header_bits(s, j, sample); - event[j] = cpu_to_be32((bits << 24) | sample); - } - - event += s->dimension; - if (++s->iec958_frame_count == 192) - s->iec958_frame_count = 0; - } -} - -static void fill_packet(struct stream *s, struct packet *packet, int nevents) -{ - int syt_index, syt, size; - u32 control; - - size = (nevents * s->dimension + 2) * sizeof(quadlet_t); - - /* Update DMA descriptors */ - packet->db->payload_desc.status = 0; - control = packet->db->payload_desc.control & 0xffff0000; - packet->db->payload_desc.control = control | size; - - /* Fill IEEE1394 headers */ - packet->db->header_desc.header[0] = - (IEEE1394_SPEED_100 << 16) | (0x01 << 14) | - (s->iso_channel << 8) | (TCODE_ISO_DATA << 4); - packet->db->header_desc.header[1] = size << 16; - - /* Calculate synchronization timestamp (syt). First we - * determine syt_index, that is, the index in the packet of - * the sample for which the timestamp is valid. */ - syt_index = (s->syt_interval - s->dbc) & (s->syt_interval - 1); - if (syt_index < nevents) { - syt = ((atomic_read(&s->cycle_count) << 12) | - s->cycle_offset.integer) & 0xffff; - fraction_add(&s->cycle_offset, - &s->cycle_offset, &s->ticks_per_syt_offset); - - /* This next addition should be modulo 8000 (0x1f40), - * but we only use the lower 4 bits of cycle_count, so - * we don't need the modulo. */ - atomic_add(s->cycle_offset.integer / 3072, &s->cycle_count); - s->cycle_offset.integer %= 3072; - } - else - syt = 0xffff; - - atomic_inc(&s->cycle_count2); - - /* Fill cip header */ - packet->payload->eoh0 = 0; - packet->payload->sid = s->host->host->node_id & 0x3f; - packet->payload->dbs = s->dimension; - packet->payload->fn = 0; - packet->payload->qpc = 0; - packet->payload->sph = 0; - packet->payload->reserved = 0; - packet->payload->dbc = s->dbc; - packet->payload->eoh1 = 2; - packet->payload->fmt = FMT_AMDTP; - packet->payload->fdf = s->fdf; - packet->payload->syt = cpu_to_be16(syt); - - switch (s->sample_format) { - case AMDTP_INPUT_LE16: - fill_payload_le16(s, packet->payload->data, nevents); - break; - } - - s->dbc += nevents; -} - -static void stream_flush(struct stream *s) -{ - struct packet *p; - int nevents; - struct fraction next; - - /* The AMDTP specifies two transmission modes: blocking and - * non-blocking. In blocking mode you always transfer - * syt_interval or zero samples, whereas in non-blocking mode - * you send as many samples as you have available at transfer - * time. - * - * The fraction samples_per_cycle specifies the number of - * samples that become available per cycle. We add this to - * the fraction ready_samples, which specifies the number of - * leftover samples from the previous transmission. The sum, - * stored in the fraction next, specifies the number of - * samples available for transmission, and from this we - * determine the number of samples to actually transmit. - */ - - while (1) { - fraction_add(&next, &s->ready_samples, &s->samples_per_cycle); - if (s->mode == AMDTP_MODE_BLOCKING) { - if (fraction_floor(&next) >= s->syt_interval) - nevents = s->syt_interval; - else - nevents = 0; - } - else - nevents = fraction_floor(&next); - - p = stream_current_packet(s); - if (s->input->length < nevents * s->dimension * 2 || p == NULL) - break; - - fill_packet(s, p, nevents); - stream_queue_packet(s); - - /* Now that we have successfully queued the packet for - * transmission, we update the fraction ready_samples. */ - fraction_sub_int(&s->ready_samples, &next, nevents); - } -} - -static int stream_alloc_packet_lists(struct stream *s) -{ - int max_nevents, max_packet_size, i; - - if (s->mode == AMDTP_MODE_BLOCKING) - max_nevents = s->syt_interval; - else - max_nevents = fraction_ceil(&s->samples_per_cycle); - - max_packet_size = max_nevents * s->dimension * 4 + 8; - s->packet_pool = pci_pool_create("packet pool", s->host->ohci->dev, - max_packet_size, 0, 0); - - if (s->packet_pool == NULL) - return -1; - - INIT_LIST_HEAD(&s->free_packet_lists); - INIT_LIST_HEAD(&s->dma_packet_lists); - for (i = 0; i < MAX_PACKET_LISTS; i++) { - struct packet_list *pl = packet_list_alloc(s); - if (pl == NULL) - break; - list_add_tail(&pl->link, &s->free_packet_lists); - } - - return i < MAX_PACKET_LISTS ? -1 : 0; -} - -static void stream_free_packet_lists(struct stream *s) -{ - struct packet_list *packet_l, *packet_l_next; - - if (s->current_packet_list != NULL) - packet_list_free(s->current_packet_list, s); - list_for_each_entry_safe(packet_l, packet_l_next, &s->dma_packet_lists, link) - packet_list_free(packet_l, s); - list_for_each_entry_safe(packet_l, packet_l_next, &s->free_packet_lists, link) - packet_list_free(packet_l, s); - if (s->packet_pool != NULL) - pci_pool_destroy(s->packet_pool); - - s->current_packet_list = NULL; - INIT_LIST_HEAD(&s->free_packet_lists); - INIT_LIST_HEAD(&s->dma_packet_lists); - s->packet_pool = NULL; -} - -static void plug_update(struct cmp_pcr *plug, void *data) -{ - struct stream *s = data; - - HPSB_INFO("plug update: p2p_count=%d, channel=%d", - plug->p2p_count, plug->channel); - s->iso_channel = plug->channel; - if (plug->p2p_count > 0) { - struct packet_list *pl; - - pl = list_entry(s->dma_packet_lists.next, struct packet_list, link); - stream_start_dma(s, pl); - } - else { - ohci1394_stop_it_ctx(s->host->ohci, s->iso_tasklet.context, 0); - } -} - -static int stream_configure(struct stream *s, int cmd, struct amdtp_ioctl *cfg) -{ - const int transfer_delay = 9000; - - if (cfg->format <= AMDTP_FORMAT_IEC958_AC3) - s->format = cfg->format; - else - return -EINVAL; - - switch (cfg->rate) { - case 32000: - s->syt_interval = 8; - s->fdf = FDF_SFC_32KHZ; - s->iec958_rate_code = 0x0c; - break; - case 44100: - s->syt_interval = 8; - s->fdf = FDF_SFC_44K1HZ; - s->iec958_rate_code = 0x00; - break; - case 48000: - s->syt_interval = 8; - s->fdf = FDF_SFC_48KHZ; - s->iec958_rate_code = 0x04; - break; - case 88200: - s->syt_interval = 16; - s->fdf = FDF_SFC_88K2HZ; - s->iec958_rate_code = 0x00; - break; - case 96000: - s->syt_interval = 16; - s->fdf = FDF_SFC_96KHZ; - s->iec958_rate_code = 0x00; - break; - case 176400: - s->syt_interval = 32; - s->fdf = FDF_SFC_176K4HZ; - s->iec958_rate_code = 0x00; - break; - case 192000: - s->syt_interval = 32; - s->fdf = FDF_SFC_192KHZ; - s->iec958_rate_code = 0x00; - break; - - default: - return -EINVAL; - } - - s->rate = cfg->rate; - fraction_init(&s->samples_per_cycle, s->rate, 8000); - fraction_init(&s->ready_samples, 0, 8000); - - /* The ticks_per_syt_offset is initialized to the number of - * ticks between syt_interval events. The number of ticks per - * second is 24.576e6, so the number of ticks between - * syt_interval events is 24.576e6 * syt_interval / rate. - */ - fraction_init(&s->ticks_per_syt_offset, - 24576000 * s->syt_interval, s->rate); - fraction_init(&s->cycle_offset, (transfer_delay % 3072) * s->rate, s->rate); - atomic_set(&s->cycle_count, transfer_delay / 3072); - atomic_set(&s->cycle_count2, 0); - - s->mode = cfg->mode; - s->sample_format = AMDTP_INPUT_LE16; - - /* When using the AM824 raw subformat we can stream signals of - * any dimension. The IEC958 subformat, however, only - * supports 2 channels. - */ - if (s->format == AMDTP_FORMAT_RAW || cfg->dimension == 2) - s->dimension = cfg->dimension; - else - return -EINVAL; - - if (s->opcr != NULL) { - cmp_unregister_opcr(s->host->host, s->opcr); - s->opcr = NULL; - } - - switch(cmd) { - case AMDTP_IOC_PLUG: - s->opcr = cmp_register_opcr(s->host->host, cfg->u.plug, - /*payload*/ 12, plug_update, s); - if (s->opcr == NULL) - return -EINVAL; - s->iso_channel = s->opcr->channel; - break; - - case AMDTP_IOC_CHANNEL: - if (cfg->u.channel >= 0 && cfg->u.channel < 64) - s->iso_channel = cfg->u.channel; - else - return -EINVAL; - break; - } - - /* The ioctl settings were all valid, so we realloc the packet - * lists to make sure the packet size is big enough. - */ - if (s->packet_pool != NULL) - stream_free_packet_lists(s); - - if (stream_alloc_packet_lists(s) < 0) { - stream_free_packet_lists(s); - return -ENOMEM; - } - - return 0; -} - -static struct stream *stream_alloc(struct amdtp_host *host) -{ - struct stream *s; - unsigned long flags; - - s = kmalloc(sizeof(struct stream), SLAB_KERNEL); - if (s == NULL) - return NULL; - - memset(s, 0, sizeof(struct stream)); - s->host = host; - - s->input = buffer_alloc(BUFFER_SIZE); - if (s->input == NULL) { - kfree(s); - return NULL; - } - - s->descriptor_pool = pci_pool_create("descriptor pool", host->ohci->dev, - sizeof(struct descriptor_block), - 16, 0); - - if (s->descriptor_pool == NULL) { - kfree(s->input); - kfree(s); - return NULL; - } - - INIT_LIST_HEAD(&s->free_packet_lists); - INIT_LIST_HEAD(&s->dma_packet_lists); - - init_waitqueue_head(&s->packet_list_wait); - spin_lock_init(&s->packet_list_lock); - - ohci1394_init_iso_tasklet(&s->iso_tasklet, OHCI_ISO_TRANSMIT, - stream_shift_packet_lists, - (unsigned long) s); - - if (ohci1394_register_iso_tasklet(host->ohci, &s->iso_tasklet) < 0) { - pci_pool_destroy(s->descriptor_pool); - kfree(s->input); - kfree(s); - return NULL; - } - - spin_lock_irqsave(&host->stream_list_lock, flags); - list_add_tail(&s->link, &host->stream_list); - spin_unlock_irqrestore(&host->stream_list_lock, flags); - - return s; -} - -static void stream_free(struct stream *s) -{ - unsigned long flags; - - /* Stop the DMA. We wait for the dma packet list to become - * empty and let the dma controller run out of programs. This - * seems to be more reliable than stopping it directly, since - * that sometimes generates an it transmit interrupt if we - * later re-enable the context. - */ - wait_event_interruptible(s->packet_list_wait, - list_empty(&s->dma_packet_lists)); - - ohci1394_stop_it_ctx(s->host->ohci, s->iso_tasklet.context, 1); - ohci1394_unregister_iso_tasklet(s->host->ohci, &s->iso_tasklet); - - if (s->opcr != NULL) - cmp_unregister_opcr(s->host->host, s->opcr); - - spin_lock_irqsave(&s->host->stream_list_lock, flags); - list_del(&s->link); - spin_unlock_irqrestore(&s->host->stream_list_lock, flags); - - kfree(s->input); - - stream_free_packet_lists(s); - pci_pool_destroy(s->descriptor_pool); - - kfree(s); -} - -/* File operations */ - -static ssize_t amdtp_write(struct file *file, const char __user *buffer, size_t count, - loff_t *offset_is_ignored) -{ - struct stream *s = file->private_data; - unsigned char *p; - int i; - size_t length; - - if (s->packet_pool == NULL) - return -EBADFD; - - /* Fill the circular buffer from the input buffer and call the - * iso packer when the buffer is full. The iso packer may - * leave bytes in the buffer for two reasons: either the - * remaining bytes wasn't enough to build a new packet, or - * there were no free packet lists. In the first case we - * re-fill the buffer and call the iso packer again or return - * if we used all the data from userspace. In the second - * case, the wait_event_interruptible will block until the irq - * handler frees a packet list. - */ - - for (i = 0; i < count; i += length) { - p = buffer_put_bytes(s->input, count - i, &length); - if (copy_from_user(p, buffer + i, length)) - return -EFAULT; - if (s->input->length < s->input->size) - continue; - - stream_flush(s); - - if (s->current_packet_list != NULL) - continue; - - if (file->f_flags & O_NONBLOCK) - return i + length > 0 ? i + length : -EAGAIN; - - if (wait_event_interruptible(s->packet_list_wait, - !list_empty(&s->free_packet_lists))) - return -EINTR; - } - - return count; -} - -static long amdtp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct stream *s = file->private_data; - struct amdtp_ioctl cfg; - int err; - lock_kernel(); - switch(cmd) - { - case AMDTP_IOC_PLUG: - case AMDTP_IOC_CHANNEL: - if (copy_from_user(&cfg, (struct amdtp_ioctl __user *) arg, sizeof cfg)) - err = -EFAULT; - else - err = stream_configure(s, cmd, &cfg); - break; - - default: - err = -EINVAL; - break; - } - unlock_kernel(); - return err; -} - -static unsigned int amdtp_poll(struct file *file, poll_table *pt) -{ - struct stream *s = file->private_data; - - poll_wait(file, &s->packet_list_wait, pt); - - if (!list_empty(&s->free_packet_lists)) - return POLLOUT | POLLWRNORM; - else - return 0; -} - -static int amdtp_open(struct inode *inode, struct file *file) -{ - struct amdtp_host *host; - int i = ieee1394_file_to_instance(file); - - host = hpsb_get_hostinfo_bykey(&amdtp_highlevel, i); - if (host == NULL) - return -ENODEV; - - file->private_data = stream_alloc(host); - if (file->private_data == NULL) - return -ENOMEM; - - return 0; -} - -static int amdtp_release(struct inode *inode, struct file *file) -{ - struct stream *s = file->private_data; - - stream_free(s); - - return 0; -} - -static struct cdev amdtp_cdev; -static struct file_operations amdtp_fops = -{ - .owner = THIS_MODULE, - .write = amdtp_write, - .poll = amdtp_poll, - .unlocked_ioctl = amdtp_ioctl, - .compat_ioctl = amdtp_ioctl, /* All amdtp ioctls are compatible */ - .open = amdtp_open, - .release = amdtp_release -}; - -/* IEEE1394 Subsystem functions */ - -static void amdtp_add_host(struct hpsb_host *host) -{ - struct amdtp_host *ah; - int minor; - - if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME) != 0) - return; - - ah = hpsb_create_hostinfo(&amdtp_highlevel, host, sizeof(*ah)); - if (!ah) { - HPSB_ERR("amdtp: Unable able to alloc hostinfo"); - return; - } - - ah->host = host; - ah->ohci = host->hostdata; - - hpsb_set_hostinfo_key(&amdtp_highlevel, host, ah->host->id); - - minor = IEEE1394_MINOR_BLOCK_AMDTP * 16 + ah->host->id; - - INIT_LIST_HEAD(&ah->stream_list); - spin_lock_init(&ah->stream_list_lock); - - devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor), - S_IFCHR|S_IRUSR|S_IWUSR, "amdtp/%d", ah->host->id); -} - -static void amdtp_remove_host(struct hpsb_host *host) -{ - struct amdtp_host *ah = hpsb_get_hostinfo(&amdtp_highlevel, host); - - if (ah) - devfs_remove("amdtp/%d", ah->host->id); - - return; -} - -static struct hpsb_highlevel amdtp_highlevel = { - .name = "amdtp", - .add_host = amdtp_add_host, - .remove_host = amdtp_remove_host, -}; - -/* Module interface */ - -MODULE_AUTHOR("Kristian Hogsberg "); -MODULE_DESCRIPTION("Driver for Audio & Music Data Transmission Protocol " - "on OHCI boards."); -MODULE_SUPPORTED_DEVICE("amdtp"); -MODULE_LICENSE("GPL"); - -static int __init amdtp_init_module (void) -{ - cdev_init(&amdtp_cdev, &amdtp_fops); - amdtp_cdev.owner = THIS_MODULE; - kobject_set_name(&amdtp_cdev.kobj, "amdtp"); - if (cdev_add(&amdtp_cdev, IEEE1394_AMDTP_DEV, 16)) { - HPSB_ERR("amdtp: unable to add char device"); - return -EIO; - } - - devfs_mk_dir("amdtp"); - - hpsb_register_highlevel(&amdtp_highlevel); - - HPSB_INFO("Loaded AMDTP driver"); - - return 0; -} - -static void __exit amdtp_exit_module (void) -{ - hpsb_unregister_highlevel(&amdtp_highlevel); - devfs_remove("amdtp"); - cdev_del(&amdtp_cdev); - - HPSB_INFO("Unloaded AMDTP driver"); -} - -module_init(amdtp_init_module); -module_exit(amdtp_exit_module); diff --git a/drivers/ieee1394/amdtp.h b/drivers/ieee1394/amdtp.h deleted file mode 100644 index 531f28e3ab5..00000000000 --- a/drivers/ieee1394/amdtp.h +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- c-basic-offset: 8 -*- */ - -#ifndef __AMDTP_H -#define __AMDTP_H - -#include -#include "ieee1394-ioctl.h" - -/* The userspace interface for the Audio & Music Data Transmission - * Protocol driver is really simple. First, open /dev/amdtp, use the - * ioctl to configure format, rate, dimension and either plug or - * channel, then start writing samples. - * - * The formats supported by the driver are listed below. - * AMDTP_FORMAT_RAW corresponds to the AM824 raw format, which can - * carry any number of channels, so use this if you're streaming - * multichannel audio. The AMDTP_FORMAT_IEC958_PCM corresponds to the - * AM824 IEC958 encapsulation without the IEC958 data bit set, using - * AMDTP_FORMAT_IEC958_AC3 will transmit the samples with the data bit - * set, suitable for transmitting compressed AC-3 audio. - * - * The rate field specifies the transmission rate; supported values - * are 32000, 44100, 48000, 88200, 96000, 176400 and 192000. - * - * The dimension field specifies the dimension of the signal, that is, - * the number of audio channels. Only AMDTP_FORMAT_RAW supports - * settings greater than 2. - * - * The mode field specifies which transmission mode to use. The AMDTP - * specifies two different transmission modes: blocking and - * non-blocking. The blocking transmission mode always send a fixed - * number of samples, typically 8, 16 or 32. To exactly match the - * transmission rate, the driver alternates between sending empty and - * non-empty packets. In non-blocking mode, the driver transmits as - * small packets as possible. For example, for a transmission rate of - * 44100Hz, the driver should send 5 41/80 samples in every cycle, but - * this is not possible so instead the driver alternates between - * sending 5 and 6 samples. - * - * The last thing to specify is either the isochronous channel to use - * or the output plug to connect to. If you know what channel the - * destination device will listen on, you can specify the channel - * directly and use the AMDTP_IOC_CHANNEL ioctl. However, if the - * destination device chooses the channel and uses the IEC61883-1 plug - * mechanism, you can specify an output plug to connect to. The - * driver will pick up the channel number from the plug once the - * destination device locks the output plug control register. In this - * case set the plug field and use the AMDTP_IOC_PLUG ioctl. - * - * Having configured the interface, the driver now accepts writes of - * regular 16 bit signed little endian samples, with the channels - * interleaved. For example, 4 channels would look like: - * - * | sample 0 | sample 1 ... - * | ch. 0 | ch. 1 | ch. 2 | ch. 3 | ch. 0 | ... - * | lsb | msb | lsb | msb | lsb | msb | lsb | msb | lsb | msb | ... - * - */ - -enum { - AMDTP_FORMAT_RAW, - AMDTP_FORMAT_IEC958_PCM, - AMDTP_FORMAT_IEC958_AC3 -}; - -enum { - AMDTP_MODE_BLOCKING, - AMDTP_MODE_NON_BLOCKING, -}; - -enum { - AMDTP_INPUT_LE16, - AMDTP_INPUT_BE16, -}; - -struct amdtp_ioctl { - __u32 format; - __u32 rate; - __u32 dimension; - __u32 mode; - union { __u32 channel; __u32 plug; } u; -}; - -#endif /* __AMDTP_H */ diff --git a/drivers/ieee1394/cmp.c b/drivers/ieee1394/cmp.c deleted file mode 100644 index 69aed26e83a..00000000000 --- a/drivers/ieee1394/cmp.c +++ /dev/null @@ -1,311 +0,0 @@ -/* -*- c-basic-offset: 8 -*- - * - * cmp.c - Connection Management Procedures - * Copyright (C) 2001 Kristian Høgsberg - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* TODO - * ---- - * - * - Implement IEC61883-1 output plugs and connection management. - * This should probably be part of the general subsystem, as it could - * be shared with dv1394. - * - * - Add IEC61883 unit directory when loading this module. This - * requires a run-time changeable config rom. - */ - -#include -#include -#include -#include -#include -#include - -#include "hosts.h" -#include "highlevel.h" -#include "ieee1394.h" -#include "ieee1394_core.h" -#include "cmp.h" - -struct plug { - union { - struct cmp_pcr pcr; - quadlet_t quadlet; - } u; - void (*update)(struct cmp_pcr *plug, void *data); - void *data; -}; - -struct cmp_host { - struct hpsb_host *host; - - union { - struct cmp_mpr ompr; - quadlet_t ompr_quadlet; - } u; - struct plug opcr[2]; - - union { - struct cmp_mpr impr; - quadlet_t impr_quadlet; - } v; - struct plug ipcr[2]; -}; - -enum { - CMP_P2P_CONNECTION, - CMP_BC_CONNECTION -}; - -#define CSR_PCR_MAP 0x900 -#define CSR_PCR_MAP_END 0x9fc - -static struct hpsb_highlevel cmp_highlevel; - -static void cmp_add_host(struct hpsb_host *host); -static void cmp_host_reset(struct hpsb_host *host); -static int pcr_read(struct hpsb_host *host, int nodeid, quadlet_t *buf, - u64 addr, size_t length, u16 flags); -static int pcr_lock(struct hpsb_host *host, int nodeid, quadlet_t *store, - u64 addr, quadlet_t data, quadlet_t arg, int extcode, u16 flags); - -static struct hpsb_highlevel cmp_highlevel = { - .name = "cmp", - .add_host = cmp_add_host, - .host_reset = cmp_host_reset, -}; - -static struct hpsb_address_ops pcr_ops = { - .read = pcr_read, - .lock = pcr_lock, -}; - - -struct cmp_pcr * -cmp_register_opcr(struct hpsb_host *host, int opcr_number, int payload, - void (*update)(struct cmp_pcr *pcr, void *data), - void *data) -{ - struct cmp_host *ch; - struct plug *plug; - - ch = hpsb_get_hostinfo(&cmp_highlevel, host); - - if (opcr_number >= ch->u.ompr.nplugs || - ch->opcr[opcr_number].update != NULL) - return NULL; - - plug = &ch->opcr[opcr_number]; - plug->u.pcr.online = 1; - plug->u.pcr.bcast_count = 0; - plug->u.pcr.p2p_count = 0; - plug->u.pcr.overhead = 0; - plug->u.pcr.payload = payload; - plug->update = update; - plug->data = data; - - return &plug->u.pcr; -} - -void cmp_unregister_opcr(struct hpsb_host *host, struct cmp_pcr *opcr) -{ - struct cmp_host *ch; - struct plug *plug; - - ch = hpsb_get_hostinfo(&cmp_highlevel, host); - plug = (struct plug *)opcr; - if (plug - ch->opcr >= ch->u.ompr.nplugs) BUG(); - - plug->u.pcr.online = 0; - plug->update = NULL; -} - -static void reset_plugs(struct cmp_host *ch) -{ - int i; - - ch->u.ompr.non_persistent_ext = 0xff; - for (i = 0; i < ch->u.ompr.nplugs; i++) { - ch->opcr[i].u.pcr.bcast_count = 0; - ch->opcr[i].u.pcr.p2p_count = 0; - ch->opcr[i].u.pcr.overhead = 0; - } -} - -static void cmp_add_host(struct hpsb_host *host) -{ - struct cmp_host *ch = hpsb_create_hostinfo(&cmp_highlevel, host, sizeof (*ch)); - - if (ch == NULL) { - HPSB_ERR("Failed to allocate cmp_host"); - return; - } - - hpsb_register_addrspace(&cmp_highlevel, host, &pcr_ops, - CSR_REGISTER_BASE + CSR_PCR_MAP, - CSR_REGISTER_BASE + CSR_PCR_MAP_END); - - ch->host = host; - ch->u.ompr.rate = IEEE1394_SPEED_100; - ch->u.ompr.bcast_channel_base = 63; - ch->u.ompr.nplugs = 2; - - reset_plugs(ch); -} - -static void cmp_host_reset(struct hpsb_host *host) -{ - struct cmp_host *ch; - - ch = hpsb_get_hostinfo(&cmp_highlevel, host); - if (ch == NULL) { - HPSB_ERR("cmp: Tried to reset unknown host"); - return; - } - - reset_plugs(ch); -} - -static int pcr_read(struct hpsb_host *host, int nodeid, quadlet_t *buf, - u64 addr, size_t length, u16 flags) -{ - int csraddr = addr - CSR_REGISTER_BASE; - int plug; - struct cmp_host *ch; - - if (length != 4) - return RCODE_TYPE_ERROR; - - ch = hpsb_get_hostinfo(&cmp_highlevel, host); - if (csraddr == 0x900) { - *buf = cpu_to_be32(ch->u.ompr_quadlet); - return RCODE_COMPLETE; - } - else if (csraddr < 0x904 + ch->u.ompr.nplugs * 4) { - plug = (csraddr - 0x904) / 4; - *buf = cpu_to_be32(ch->opcr[plug].u.quadlet); - return RCODE_COMPLETE; - } - else if (csraddr < 0x980) { - return RCODE_ADDRESS_ERROR; - } - else if (csraddr == 0x980) { - *buf = cpu_to_be32(ch->v.impr_quadlet); - return RCODE_COMPLETE; - } - else if (csraddr < 0x984 + ch->v.impr.nplugs * 4) { - plug = (csraddr - 0x984) / 4; - *buf = cpu_to_be32(ch->ipcr[plug].u.quadlet); - return RCODE_COMPLETE; - } - else - return RCODE_ADDRESS_ERROR; -} - -static int pcr_lock(struct hpsb_host *host, int nodeid, quadlet_t *store, - u64 addr, quadlet_t data, quadlet_t arg, int extcode, u16 flags) -{ - int csraddr = addr - CSR_REGISTER_BASE; - int plug; - struct cmp_host *ch; - - ch = hpsb_get_hostinfo(&cmp_highlevel, host); - - if (extcode != EXTCODE_COMPARE_SWAP) - return RCODE_TYPE_ERROR; - - if (csraddr == 0x900) { - /* FIXME: Ignore writes to bits 30-31 and 0-7 */ - *store = cpu_to_be32(ch->u.ompr_quadlet); - if (arg == cpu_to_be32(ch->u.ompr_quadlet)) - ch->u.ompr_quadlet = be32_to_cpu(data); - - return RCODE_COMPLETE; - } - if (csraddr < 0x904 + ch->u.ompr.nplugs * 4) { - plug = (csraddr - 0x904) / 4; - *store = cpu_to_be32(ch->opcr[plug].u.quadlet); - - if (arg == *store) - ch->opcr[plug].u.quadlet = be32_to_cpu(data); - - if (be32_to_cpu(*store) != ch->opcr[plug].u.quadlet && - ch->opcr[plug].update != NULL) - ch->opcr[plug].update(&ch->opcr[plug].u.pcr, - ch->opcr[plug].data); - - return RCODE_COMPLETE; - } - else if (csraddr < 0x980) { - return RCODE_ADDRESS_ERROR; - } - else if (csraddr == 0x980) { - /* FIXME: Ignore writes to bits 24-31 and 0-7 */ - *store = cpu_to_be32(ch->u.ompr_quadlet); - if (arg == cpu_to_be32(ch->u.ompr_quadlet)) - ch->u.ompr_quadlet = be32_to_cpu(data); - - return RCODE_COMPLETE; - } - else if (csraddr < 0x984 + ch->v.impr.nplugs * 4) { - plug = (csraddr - 0x984) / 4; - *store = cpu_to_be32(ch->ipcr[plug].u.quadlet); - - if (arg == *store) - ch->ipcr[plug].u.quadlet = be32_to_cpu(data); - - if (be32_to_cpu(*store) != ch->ipcr[plug].u.quadlet && - ch->ipcr[plug].update != NULL) - ch->ipcr[plug].update(&ch->ipcr[plug].u.pcr, - ch->ipcr[plug].data); - - return RCODE_COMPLETE; - } - else - return RCODE_ADDRESS_ERROR; -} - - -/* Module interface */ - -MODULE_AUTHOR("Kristian Hogsberg "); -MODULE_DESCRIPTION("Connection Management Procedures (CMP)"); -MODULE_SUPPORTED_DEVICE("cmp"); -MODULE_LICENSE("GPL"); - -EXPORT_SYMBOL(cmp_register_opcr); -EXPORT_SYMBOL(cmp_unregister_opcr); - -static int __init cmp_init_module (void) -{ - hpsb_register_highlevel (&cmp_highlevel); - - HPSB_INFO("Loaded CMP driver"); - - return 0; -} - -static void __exit cmp_exit_module (void) -{ - hpsb_unregister_highlevel(&cmp_highlevel); - - HPSB_INFO("Unloaded CMP driver"); -} - -module_init(cmp_init_module); -module_exit(cmp_exit_module); diff --git a/drivers/ieee1394/cmp.h b/drivers/ieee1394/cmp.h deleted file mode 100644 index f9288bfcd49..00000000000 --- a/drivers/ieee1394/cmp.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef __CMP_H -#define __CMP_H - -struct cmp_mpr { - u32 nplugs:5; - u32 reserved:3; - u32 persistent_ext:8; - u32 non_persistent_ext:8; - u32 bcast_channel_base:6; - u32 rate:2; -} __attribute__((packed)); - -struct cmp_pcr { - u32 payload:10; - u32 overhead:4; - u32 speed:2; - u32 channel:6; - u32 reserved:2; - u32 p2p_count:6; - u32 bcast_count:1; - u32 online:1; -} __attribute__((packed)); - -struct cmp_pcr *cmp_register_opcr(struct hpsb_host *host, int plug, - int payload, - void (*update)(struct cmp_pcr *plug, - void *data), - void *data); -void cmp_unregister_opcr(struct hpsb_host *host, struct cmp_pcr *plug); - -#endif /* __CMP_H */ -- GitLab From 53493dcf6e9e27cc9379cbf8962642986927aea9 Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Mon, 16 Jan 2006 19:54:40 -0800 Subject: [PATCH 361/465] [IA64] Cleanup of arch/ia64/sn and include/asm-ia64/sn Replace uintX_t declarations with uX declarations. Replace intX_t declarations with sX declarations. Signed-off-by: Prarit Bhargava Signed-off-by: Tony Luck --- arch/ia64/sn/include/xtalk/hubdev.h | 10 +- arch/ia64/sn/include/xtalk/xbow.h | 206 +-- arch/ia64/sn/include/xtalk/xwidgetdev.h | 46 +- arch/ia64/sn/kernel/io_init.c | 10 +- arch/ia64/sn/kernel/irq.c | 10 +- arch/ia64/sn/kernel/tiocx.c | 18 +- arch/ia64/sn/pci/pcibr/pcibr_ate.c | 16 +- arch/ia64/sn/pci/pcibr/pcibr_dma.c | 44 +- arch/ia64/sn/pci/pcibr/pcibr_provider.c | 12 +- arch/ia64/sn/pci/pcibr/pcibr_reg.c | 28 +- arch/ia64/sn/pci/tioca_provider.c | 36 +- arch/ia64/sn/pci/tioce_provider.c | 68 +- include/asm-ia64/sn/intr.h | 2 +- include/asm-ia64/sn/pcibr_provider.h | 48 +- include/asm-ia64/sn/pcibus_provider_defs.h | 14 +- include/asm-ia64/sn/pcidev.h | 4 +- include/asm-ia64/sn/pic.h | 204 +-- include/asm-ia64/sn/shubio.h | 1620 ++++++++++---------- include/asm-ia64/sn/sn_sal.h | 12 +- include/asm-ia64/sn/tioca.h | 82 +- include/asm-ia64/sn/tioca_provider.h | 56 +- include/asm-ia64/sn/tioce.h | 662 ++++---- include/asm-ia64/sn/tioce_provider.h | 30 +- include/asm-ia64/sn/tiocp.h | 254 +-- include/asm-ia64/sn/tiocx.h | 14 +- 25 files changed, 1758 insertions(+), 1748 deletions(-) diff --git a/arch/ia64/sn/include/xtalk/hubdev.h b/arch/ia64/sn/include/xtalk/hubdev.h index 4d417c30120..7c88e9a5851 100644 --- a/arch/ia64/sn/include/xtalk/hubdev.h +++ b/arch/ia64/sn/include/xtalk/hubdev.h @@ -40,8 +40,8 @@ struct sn_flush_device_common { unsigned long sfdl_force_int_addr; unsigned long sfdl_flush_value; volatile unsigned long *sfdl_flush_addr; - uint32_t sfdl_persistent_busnum; - uint32_t sfdl_persistent_segment; + u32 sfdl_persistent_busnum; + u32 sfdl_persistent_segment; struct pcibus_info *sfdl_pcibus_info; }; @@ -56,7 +56,7 @@ struct sn_flush_device_kernel { */ struct sn_flush_nasid_entry { struct sn_flush_device_kernel **widget_p; // Used as an array of wid_num - uint64_t iio_itte[8]; + u64 iio_itte[8]; }; struct hubdev_info { @@ -70,8 +70,8 @@ struct hubdev_info { void *hdi_nodepda; void *hdi_node_vertex; - uint32_t max_segment_number; - uint32_t max_pcibus_number; + u32 max_segment_number; + u32 max_pcibus_number; }; extern void hubdev_init_node(nodepda_t *, cnodeid_t); diff --git a/arch/ia64/sn/include/xtalk/xbow.h b/arch/ia64/sn/include/xtalk/xbow.h index ec56b3432f1..90f37a4133d 100644 --- a/arch/ia64/sn/include/xtalk/xbow.h +++ b/arch/ia64/sn/include/xtalk/xbow.h @@ -3,7 +3,8 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992-1997,2000-2004 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (C) 1992-1997,2000-2006 Silicon Graphics, Inc. All Rights + * Reserved. */ #ifndef _ASM_IA64_SN_XTALK_XBOW_H #define _ASM_IA64_SN_XTALK_XBOW_H @@ -21,94 +22,94 @@ /* Register set for each xbow link */ typedef volatile struct xb_linkregs_s { -/* +/* * we access these through synergy unswizzled space, so the address * gets twiddled (i.e. references to 0x4 actually go to 0x0 and vv.) * That's why we put the register first and filler second. */ - uint32_t link_ibf; - uint32_t filler0; /* filler for proper alignment */ - uint32_t link_control; - uint32_t filler1; - uint32_t link_status; - uint32_t filler2; - uint32_t link_arb_upper; - uint32_t filler3; - uint32_t link_arb_lower; - uint32_t filler4; - uint32_t link_status_clr; - uint32_t filler5; - uint32_t link_reset; - uint32_t filler6; - uint32_t link_aux_status; - uint32_t filler7; + u32 link_ibf; + u32 filler0; /* filler for proper alignment */ + u32 link_control; + u32 filler1; + u32 link_status; + u32 filler2; + u32 link_arb_upper; + u32 filler3; + u32 link_arb_lower; + u32 filler4; + u32 link_status_clr; + u32 filler5; + u32 link_reset; + u32 filler6; + u32 link_aux_status; + u32 filler7; } xb_linkregs_t; typedef volatile struct xbow_s { - /* standard widget configuration 0x000000-0x000057 */ - struct widget_cfg xb_widget; /* 0x000000 */ - - /* helper fieldnames for accessing bridge widget */ - -#define xb_wid_id xb_widget.w_id -#define xb_wid_stat xb_widget.w_status -#define xb_wid_err_upper xb_widget.w_err_upper_addr -#define xb_wid_err_lower xb_widget.w_err_lower_addr -#define xb_wid_control xb_widget.w_control -#define xb_wid_req_timeout xb_widget.w_req_timeout -#define xb_wid_int_upper xb_widget.w_intdest_upper_addr -#define xb_wid_int_lower xb_widget.w_intdest_lower_addr -#define xb_wid_err_cmdword xb_widget.w_err_cmd_word -#define xb_wid_llp xb_widget.w_llp_cfg -#define xb_wid_stat_clr xb_widget.w_tflush - -/* + /* standard widget configuration 0x000000-0x000057 */ + struct widget_cfg xb_widget; /* 0x000000 */ + + /* helper fieldnames for accessing bridge widget */ + +#define xb_wid_id xb_widget.w_id +#define xb_wid_stat xb_widget.w_status +#define xb_wid_err_upper xb_widget.w_err_upper_addr +#define xb_wid_err_lower xb_widget.w_err_lower_addr +#define xb_wid_control xb_widget.w_control +#define xb_wid_req_timeout xb_widget.w_req_timeout +#define xb_wid_int_upper xb_widget.w_intdest_upper_addr +#define xb_wid_int_lower xb_widget.w_intdest_lower_addr +#define xb_wid_err_cmdword xb_widget.w_err_cmd_word +#define xb_wid_llp xb_widget.w_llp_cfg +#define xb_wid_stat_clr xb_widget.w_tflush + +/* * we access these through synergy unswizzled space, so the address * gets twiddled (i.e. references to 0x4 actually go to 0x0 and vv.) * That's why we put the register first and filler second. */ - /* xbow-specific widget configuration 0x000058-0x0000FF */ - uint32_t xb_wid_arb_reload; /* 0x00005C */ - uint32_t _pad_000058; - uint32_t xb_perf_ctr_a; /* 0x000064 */ - uint32_t _pad_000060; - uint32_t xb_perf_ctr_b; /* 0x00006c */ - uint32_t _pad_000068; - uint32_t xb_nic; /* 0x000074 */ - uint32_t _pad_000070; - - /* Xbridge only */ - uint32_t xb_w0_rst_fnc; /* 0x00007C */ - uint32_t _pad_000078; - uint32_t xb_l8_rst_fnc; /* 0x000084 */ - uint32_t _pad_000080; - uint32_t xb_l9_rst_fnc; /* 0x00008c */ - uint32_t _pad_000088; - uint32_t xb_la_rst_fnc; /* 0x000094 */ - uint32_t _pad_000090; - uint32_t xb_lb_rst_fnc; /* 0x00009c */ - uint32_t _pad_000098; - uint32_t xb_lc_rst_fnc; /* 0x0000a4 */ - uint32_t _pad_0000a0; - uint32_t xb_ld_rst_fnc; /* 0x0000ac */ - uint32_t _pad_0000a8; - uint32_t xb_le_rst_fnc; /* 0x0000b4 */ - uint32_t _pad_0000b0; - uint32_t xb_lf_rst_fnc; /* 0x0000bc */ - uint32_t _pad_0000b8; - uint32_t xb_lock; /* 0x0000c4 */ - uint32_t _pad_0000c0; - uint32_t xb_lock_clr; /* 0x0000cc */ - uint32_t _pad_0000c8; - /* end of Xbridge only */ - uint32_t _pad_0000d0[12]; - - /* Link Specific Registers, port 8..15 0x000100-0x000300 */ - xb_linkregs_t xb_link_raw[MAX_XBOW_PORTS]; -#define xb_link(p) xb_link_raw[(p) & (MAX_XBOW_PORTS - 1)] - + /* xbow-specific widget configuration 0x000058-0x0000FF */ + u32 xb_wid_arb_reload; /* 0x00005C */ + u32 _pad_000058; + u32 xb_perf_ctr_a; /* 0x000064 */ + u32 _pad_000060; + u32 xb_perf_ctr_b; /* 0x00006c */ + u32 _pad_000068; + u32 xb_nic; /* 0x000074 */ + u32 _pad_000070; + + /* Xbridge only */ + u32 xb_w0_rst_fnc; /* 0x00007C */ + u32 _pad_000078; + u32 xb_l8_rst_fnc; /* 0x000084 */ + u32 _pad_000080; + u32 xb_l9_rst_fnc; /* 0x00008c */ + u32 _pad_000088; + u32 xb_la_rst_fnc; /* 0x000094 */ + u32 _pad_000090; + u32 xb_lb_rst_fnc; /* 0x00009c */ + u32 _pad_000098; + u32 xb_lc_rst_fnc; /* 0x0000a4 */ + u32 _pad_0000a0; + u32 xb_ld_rst_fnc; /* 0x0000ac */ + u32 _pad_0000a8; + u32 xb_le_rst_fnc; /* 0x0000b4 */ + u32 _pad_0000b0; + u32 xb_lf_rst_fnc; /* 0x0000bc */ + u32 _pad_0000b8; + u32 xb_lock; /* 0x0000c4 */ + u32 _pad_0000c0; + u32 xb_lock_clr; /* 0x0000cc */ + u32 _pad_0000c8; + /* end of Xbridge only */ + u32 _pad_0000d0[12]; + + /* Link Specific Registers, port 8..15 0x000100-0x000300 */ + xb_linkregs_t xb_link_raw[MAX_XBOW_PORTS]; } xbow_t; +#define xb_link(p) xb_link_raw[(p) & (MAX_XBOW_PORTS - 1)] + #define XB_FLAGS_EXISTS 0x1 /* device exists */ #define XB_FLAGS_MASTER 0x2 #define XB_FLAGS_SLAVE 0x0 @@ -160,7 +161,7 @@ typedef volatile struct xbow_s { /* End of Xbridge only */ /* used only in ide, but defined here within the reserved portion */ -/* of the widget0 address space (before 0xf4) */ +/* of the widget0 address space (before 0xf4) */ #define XBOW_WID_UNDEF 0xe4 /* xbow link register set base, legal value for x is 0x8..0xf */ @@ -179,29 +180,37 @@ typedef volatile struct xbow_s { /* link_control(x) */ #define XB_CTRL_LINKALIVE_IE 0x80000000 /* link comes alive */ - /* reserved: 0x40000000 */ +/* reserved: 0x40000000 */ #define XB_CTRL_PERF_CTR_MODE_MSK 0x30000000 /* perf counter mode */ -#define XB_CTRL_IBUF_LEVEL_MSK 0x0e000000 /* input packet buffer level */ -#define XB_CTRL_8BIT_MODE 0x01000000 /* force link into 8 bit mode */ -#define XB_CTRL_BAD_LLP_PKT 0x00800000 /* force bad LLP packet */ -#define XB_CTRL_WIDGET_CR_MSK 0x007c0000 /* LLP widget credit mask */ -#define XB_CTRL_WIDGET_CR_SHFT 18 /* LLP widget credit shift */ -#define XB_CTRL_ILLEGAL_DST_IE 0x00020000 /* illegal destination */ -#define XB_CTRL_OALLOC_IBUF_IE 0x00010000 /* overallocated input buffer */ - /* reserved: 0x0000fe00 */ +#define XB_CTRL_IBUF_LEVEL_MSK 0x0e000000 /* input packet buffer + level */ +#define XB_CTRL_8BIT_MODE 0x01000000 /* force link into 8 + bit mode */ +#define XB_CTRL_BAD_LLP_PKT 0x00800000 /* force bad LLP + packet */ +#define XB_CTRL_WIDGET_CR_MSK 0x007c0000 /* LLP widget credit + mask */ +#define XB_CTRL_WIDGET_CR_SHFT 18 /* LLP widget credit + shift */ +#define XB_CTRL_ILLEGAL_DST_IE 0x00020000 /* illegal destination + */ +#define XB_CTRL_OALLOC_IBUF_IE 0x00010000 /* overallocated input + buffer */ +/* reserved: 0x0000fe00 */ #define XB_CTRL_BNDWDTH_ALLOC_IE 0x00000100 /* bandwidth alloc */ #define XB_CTRL_RCV_CNT_OFLOW_IE 0x00000080 /* rcv retry overflow */ #define XB_CTRL_XMT_CNT_OFLOW_IE 0x00000040 /* xmt retry overflow */ #define XB_CTRL_XMT_MAX_RTRY_IE 0x00000020 /* max transmit retry */ #define XB_CTRL_RCV_IE 0x00000010 /* receive */ #define XB_CTRL_XMT_RTRY_IE 0x00000008 /* transmit retry */ - /* reserved: 0x00000004 */ -#define XB_CTRL_MAXREQ_TOUT_IE 0x00000002 /* maximum request timeout */ +/* reserved: 0x00000004 */ +#define XB_CTRL_MAXREQ_TOUT_IE 0x00000002 /* maximum request + timeout */ #define XB_CTRL_SRC_TOUT_IE 0x00000001 /* source timeout */ /* link_status(x) */ #define XB_STAT_LINKALIVE XB_CTRL_LINKALIVE_IE - /* reserved: 0x7ff80000 */ +/* reserved: 0x7ff80000 */ #define XB_STAT_MULTI_ERR 0x00040000 /* multi error */ #define XB_STAT_ILLEGAL_DST_ERR XB_CTRL_ILLEGAL_DST_IE #define XB_STAT_OALLOC_IBUF_ERR XB_CTRL_OALLOC_IBUF_IE @@ -211,7 +220,7 @@ typedef volatile struct xbow_s { #define XB_STAT_XMT_MAX_RTRY_ERR XB_CTRL_XMT_MAX_RTRY_IE #define XB_STAT_RCV_ERR XB_CTRL_RCV_IE #define XB_STAT_XMT_RTRY_ERR XB_CTRL_XMT_RTRY_IE - /* reserved: 0x00000004 */ +/* reserved: 0x00000004 */ #define XB_STAT_MAXREQ_TOUT_ERR XB_CTRL_MAXREQ_TOUT_IE #define XB_STAT_SRC_TOUT_ERR XB_CTRL_SRC_TOUT_IE @@ -222,7 +231,7 @@ typedef volatile struct xbow_s { #define XB_AUX_LINKFAIL_RST_BAD 0x00000040 #define XB_AUX_STAT_PRESENT 0x00000020 #define XB_AUX_STAT_PORT_WIDTH 0x00000010 - /* reserved: 0x0000000f */ +/* reserved: 0x0000000f */ /* * link_arb_upper/link_arb_lower(x), (reg) should be the link_arb_upper @@ -238,7 +247,8 @@ typedef volatile struct xbow_s { /* XBOW_WID_STAT */ #define XB_WID_STAT_LINK_INTR_SHFT (24) #define XB_WID_STAT_LINK_INTR_MASK (0xFF << XB_WID_STAT_LINK_INTR_SHFT) -#define XB_WID_STAT_LINK_INTR(x) (0x1 << (((x)&7) + XB_WID_STAT_LINK_INTR_SHFT)) +#define XB_WID_STAT_LINK_INTR(x) \ + (0x1 << (((x)&7) + XB_WID_STAT_LINK_INTR_SHFT)) #define XB_WID_STAT_WIDGET0_INTR 0x00800000 #define XB_WID_STAT_SRCID_MASK 0x000003c0 /* Xbridge only */ #define XB_WID_STAT_REG_ACC_ERR 0x00000020 @@ -264,7 +274,7 @@ typedef volatile struct xbow_s { #define XXBOW_WIDGET_PART_NUM 0xd000 /* Xbridge */ #define XBOW_WIDGET_MFGR_NUM 0x0 #define XXBOW_WIDGET_MFGR_NUM 0x0 -#define PXBOW_WIDGET_PART_NUM 0xd100 /* PIC */ +#define PXBOW_WIDGET_PART_NUM 0xd100 /* PIC */ #define XBOW_REV_1_0 0x1 /* xbow rev 1.0 is "1" */ #define XBOW_REV_1_1 0x2 /* xbow rev 1.1 is "2" */ @@ -279,13 +289,13 @@ typedef volatile struct xbow_s { #define XBOW_WID_ARB_RELOAD_INT 0x3f /* GBR reload interval */ #define IS_XBRIDGE_XBOW(wid) \ - (XWIDGET_PART_NUM(wid) == XXBOW_WIDGET_PART_NUM && \ - XWIDGET_MFG_NUM(wid) == XXBOW_WIDGET_MFGR_NUM) + (XWIDGET_PART_NUM(wid) == XXBOW_WIDGET_PART_NUM && \ + XWIDGET_MFG_NUM(wid) == XXBOW_WIDGET_MFGR_NUM) #define IS_PIC_XBOW(wid) \ - (XWIDGET_PART_NUM(wid) == PXBOW_WIDGET_PART_NUM && \ - XWIDGET_MFG_NUM(wid) == XXBOW_WIDGET_MFGR_NUM) + (XWIDGET_PART_NUM(wid) == PXBOW_WIDGET_PART_NUM && \ + XWIDGET_MFG_NUM(wid) == XXBOW_WIDGET_MFGR_NUM) #define XBOW_WAR_ENABLED(pv, widid) ((1 << XWIDGET_REV_NUM(widid)) & pv) -#endif /* _ASM_IA64_SN_XTALK_XBOW_H */ +#endif /* _ASM_IA64_SN_XTALK_XBOW_H */ diff --git a/arch/ia64/sn/include/xtalk/xwidgetdev.h b/arch/ia64/sn/include/xtalk/xwidgetdev.h index c5f4bc5cc03..2800eda0fd6 100644 --- a/arch/ia64/sn/include/xtalk/xwidgetdev.h +++ b/arch/ia64/sn/include/xtalk/xwidgetdev.h @@ -25,28 +25,28 @@ /* widget configuration registers */ struct widget_cfg{ - uint32_t w_id; /* 0x04 */ - uint32_t w_pad_0; /* 0x00 */ - uint32_t w_status; /* 0x0c */ - uint32_t w_pad_1; /* 0x08 */ - uint32_t w_err_upper_addr; /* 0x14 */ - uint32_t w_pad_2; /* 0x10 */ - uint32_t w_err_lower_addr; /* 0x1c */ - uint32_t w_pad_3; /* 0x18 */ - uint32_t w_control; /* 0x24 */ - uint32_t w_pad_4; /* 0x20 */ - uint32_t w_req_timeout; /* 0x2c */ - uint32_t w_pad_5; /* 0x28 */ - uint32_t w_intdest_upper_addr; /* 0x34 */ - uint32_t w_pad_6; /* 0x30 */ - uint32_t w_intdest_lower_addr; /* 0x3c */ - uint32_t w_pad_7; /* 0x38 */ - uint32_t w_err_cmd_word; /* 0x44 */ - uint32_t w_pad_8; /* 0x40 */ - uint32_t w_llp_cfg; /* 0x4c */ - uint32_t w_pad_9; /* 0x48 */ - uint32_t w_tflush; /* 0x54 */ - uint32_t w_pad_10; /* 0x50 */ + u32 w_id; /* 0x04 */ + u32 w_pad_0; /* 0x00 */ + u32 w_status; /* 0x0c */ + u32 w_pad_1; /* 0x08 */ + u32 w_err_upper_addr; /* 0x14 */ + u32 w_pad_2; /* 0x10 */ + u32 w_err_lower_addr; /* 0x1c */ + u32 w_pad_3; /* 0x18 */ + u32 w_control; /* 0x24 */ + u32 w_pad_4; /* 0x20 */ + u32 w_req_timeout; /* 0x2c */ + u32 w_pad_5; /* 0x28 */ + u32 w_intdest_upper_addr; /* 0x34 */ + u32 w_pad_6; /* 0x30 */ + u32 w_intdest_lower_addr; /* 0x3c */ + u32 w_pad_7; /* 0x38 */ + u32 w_err_cmd_word; /* 0x44 */ + u32 w_pad_8; /* 0x40 */ + u32 w_llp_cfg; /* 0x4c */ + u32 w_pad_9; /* 0x48 */ + u32 w_tflush; /* 0x54 */ + u32 w_pad_10; /* 0x50 */ }; /* @@ -63,7 +63,7 @@ struct xwidget_info{ struct xwidget_hwid xwi_hwid; /* Widget Identification */ char xwi_masterxid; /* Hub's Widget Port Number */ void *xwi_hubinfo; /* Hub's provider private info */ - uint64_t *xwi_hub_provider; /* prom provider functions */ + u64 *xwi_hub_provider; /* prom provider functions */ void *xwi_vertex; }; diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index 258d9d7aff9..233d55115d3 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c @@ -132,8 +132,8 @@ static inline u64 sal_get_pcibus_info(u64 segment, u64 busnum, u64 address) * Retrieve the pci device information given the bus and device|function number. */ static inline u64 -sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev, - u64 sn_irq_info) +sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev, + u64 sn_irq_info) { struct ia64_sal_retval ret_stuff; ret_stuff.status = 0; @@ -141,7 +141,7 @@ sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev, SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_GET_PCIDEV_INFO, - (u64) segment, (u64) bus_number, (u64) devfn, + (u64) segment, (u64) bus_number, (u64) devfn, (u64) pci_dev, sn_irq_info, 0, 0); return ret_stuff.v0; @@ -268,7 +268,7 @@ static void sn_fixup_ionodes(void) */ static void sn_pci_window_fixup(struct pci_dev *dev, unsigned int count, - int64_t * pci_addrs) + s64 * pci_addrs) { struct pci_controller *controller = PCI_CONTROLLER(dev->bus); unsigned int i; @@ -328,7 +328,7 @@ void sn_pci_fixup_slot(struct pci_dev *dev) struct pci_bus *host_pci_bus; struct pci_dev *host_pci_dev; struct pcidev_info *pcidev_info; - int64_t pci_addrs[PCI_ROM_RESOURCE + 1]; + s64 pci_addrs[PCI_ROM_RESOURCE + 1]; struct sn_irq_info *sn_irq_info; unsigned long size; unsigned int bus_no, devfn; diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c index 01d18b7b5bb..ec37084bdc1 100644 --- a/arch/ia64/sn/kernel/irq.c +++ b/arch/ia64/sn/kernel/irq.c @@ -28,7 +28,7 @@ extern int sn_ioif_inited; static struct list_head **sn_irq_lh; static spinlock_t sn_irq_info_lock = SPIN_LOCK_UNLOCKED; /* non-IRQ lock */ -static inline uint64_t sn_intr_alloc(nasid_t local_nasid, int local_widget, +static inline u64 sn_intr_alloc(nasid_t local_nasid, int local_widget, u64 sn_irq_info, int req_irq, nasid_t req_nasid, int req_slice) @@ -123,7 +123,7 @@ static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask) list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe, sn_irq_lh[irq], list) { - uint64_t bridge; + u64 bridge; int local_widget, status; nasid_t local_nasid; struct sn_irq_info *new_irq_info; @@ -134,7 +134,7 @@ static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask) break; memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info)); - bridge = (uint64_t) new_irq_info->irq_bridge; + bridge = (u64) new_irq_info->irq_bridge; if (!bridge) { kfree(new_irq_info); break; /* irq is not a device interrupt */ @@ -349,10 +349,10 @@ static void force_interrupt(int irq) */ static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info) { - uint64_t regval; + u64 regval; int irr_reg_num; int irr_bit; - uint64_t irr_reg; + u64 irr_reg; struct pcidev_info *pcidev_info; struct pcibus_info *pcibus_info; diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c index 6a7939b16a1..d263d3e8fbb 100644 --- a/arch/ia64/sn/kernel/tiocx.c +++ b/arch/ia64/sn/kernel/tiocx.c @@ -245,7 +245,7 @@ static int cx_device_reload(struct cx_dev *cx_dev) cx_dev->bt); } -static inline uint64_t tiocx_intr_alloc(nasid_t nasid, int widget, +static inline u64 tiocx_intr_alloc(nasid_t nasid, int widget, u64 sn_irq_info, int req_irq, nasid_t req_nasid, int req_slice) @@ -302,7 +302,7 @@ struct sn_irq_info *tiocx_irq_alloc(nasid_t nasid, int widget, int irq, void tiocx_irq_free(struct sn_irq_info *sn_irq_info) { - uint64_t bridge = (uint64_t) sn_irq_info->irq_bridge; + u64 bridge = (u64) sn_irq_info->irq_bridge; nasid_t nasid = NASID_GET(bridge); int widget; @@ -313,12 +313,12 @@ void tiocx_irq_free(struct sn_irq_info *sn_irq_info) } } -uint64_t tiocx_dma_addr(uint64_t addr) +u64 tiocx_dma_addr(u64 addr) { return PHYS_TO_TIODMA(addr); } -uint64_t tiocx_swin_base(int nasid) +u64 tiocx_swin_base(int nasid) { return TIO_SWIN_BASE(nasid, TIOCX_CORELET); } @@ -335,8 +335,8 @@ EXPORT_SYMBOL(tiocx_swin_base); static void tio_conveyor_set(nasid_t nasid, int enable_flag) { - uint64_t ice_frz; - uint64_t disable_cb = (1ull << 61); + u64 ice_frz; + u64 disable_cb = (1ull << 61); if (!(nasid & 1)) return; @@ -388,7 +388,7 @@ static int is_fpga_tio(int nasid, int *bt) static int bitstream_loaded(nasid_t nasid) { - uint64_t cx_credits; + u64 cx_credits; cx_credits = REMOTE_HUB_L(nasid, TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3); cx_credits &= TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3_CREDIT_CNT_MASK; @@ -404,14 +404,14 @@ static int tiocx_reload(struct cx_dev *cx_dev) nasid_t nasid = cx_dev->cx_id.nasid; if (bitstream_loaded(nasid)) { - uint64_t cx_id; + u64 cx_id; int rv; rv = ia64_sn_sysctl_tio_clock_reset(nasid); if (rv) { printk(KERN_ALERT "CX port JTAG reset failed.\n"); } else { - cx_id = *(volatile uint64_t *) + cx_id = *(volatile u64 *) (TIO_SWIN_BASE(nasid, TIOCX_CORELET) + WIDGET_ID); part_num = XWIDGET_PART_NUM(cx_id); diff --git a/arch/ia64/sn/pci/pcibr/pcibr_ate.c b/arch/ia64/sn/pci/pcibr/pcibr_ate.c index d1647b863e6..aa3fa5152a3 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_ate.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_ate.c @@ -18,10 +18,10 @@ int pcibr_invalidate_ate = 0; /* by default don't invalidate ATE on free */ * mark_ate: Mark the ate as either free or inuse. */ static void mark_ate(struct ate_resource *ate_resource, int start, int number, - uint64_t value) + u64 value) { - uint64_t *ate = ate_resource->ate; + u64 *ate = ate_resource->ate; int index; int length = 0; @@ -38,7 +38,7 @@ static int find_free_ate(struct ate_resource *ate_resource, int start, int count) { - uint64_t *ate = ate_resource->ate; + u64 *ate = ate_resource->ate; int index; int start_free; @@ -119,7 +119,7 @@ static inline int alloc_ate_resource(struct ate_resource *ate_resource, int pcibr_ate_alloc(struct pcibus_info *pcibus_info, int count) { int status = 0; - uint64_t flag; + u64 flag; flag = pcibr_lock(pcibus_info); status = alloc_ate_resource(&pcibus_info->pbi_int_ate_resource, count); @@ -139,7 +139,7 @@ int pcibr_ate_alloc(struct pcibus_info *pcibus_info, int count) * Setup an Address Translation Entry as specified. Use either the Bridge * internal maps or the external map RAM, as appropriate. */ -static inline uint64_t *pcibr_ate_addr(struct pcibus_info *pcibus_info, +static inline u64 *pcibr_ate_addr(struct pcibus_info *pcibus_info, int ate_index) { if (ate_index < pcibus_info->pbi_int_ate_size) { @@ -153,7 +153,7 @@ static inline uint64_t *pcibr_ate_addr(struct pcibus_info *pcibus_info, */ void inline ate_write(struct pcibus_info *pcibus_info, int ate_index, int count, - volatile uint64_t ate) + volatile u64 ate) { while (count-- > 0) { if (ate_index < pcibus_info->pbi_int_ate_size) { @@ -171,9 +171,9 @@ ate_write(struct pcibus_info *pcibus_info, int ate_index, int count, void pcibr_ate_free(struct pcibus_info *pcibus_info, int index) { - volatile uint64_t ate; + volatile u64 ate; int count; - uint64_t flags; + u64 flags; if (pcibr_invalidate_ate) { /* For debugging purposes, clear the valid bit in the ATE */ diff --git a/arch/ia64/sn/pci/pcibr/pcibr_dma.c b/arch/ia64/sn/pci/pcibr/pcibr_dma.c index e68332d9317..54ce5b7ceed 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_dma.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_dma.c @@ -41,21 +41,21 @@ extern int sn_ioif_inited; static dma_addr_t pcibr_dmamap_ate32(struct pcidev_info *info, - uint64_t paddr, size_t req_size, uint64_t flags) + u64 paddr, size_t req_size, u64 flags) { struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info; struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info-> pdi_pcibus_info; - uint8_t internal_device = (PCI_SLOT(pcidev_info->pdi_host_pcidev_info-> + u8 internal_device = (PCI_SLOT(pcidev_info->pdi_host_pcidev_info-> pdi_linux_pcidev->devfn)) - 1; int ate_count; int ate_index; - uint64_t ate_flags = flags | PCI32_ATE_V; - uint64_t ate; - uint64_t pci_addr; - uint64_t xio_addr; - uint64_t offset; + u64 ate_flags = flags | PCI32_ATE_V; + u64 ate; + u64 pci_addr; + u64 xio_addr; + u64 offset; /* PIC in PCI-X mode does not supports 32bit PageMap mode */ if (IS_PIC_SOFT(pcibus_info) && IS_PCIX(pcibus_info)) { @@ -109,12 +109,12 @@ pcibr_dmamap_ate32(struct pcidev_info *info, } static dma_addr_t -pcibr_dmatrans_direct64(struct pcidev_info * info, uint64_t paddr, - uint64_t dma_attributes) +pcibr_dmatrans_direct64(struct pcidev_info * info, u64 paddr, + u64 dma_attributes) { struct pcibus_info *pcibus_info = (struct pcibus_info *) ((info->pdi_host_pcidev_info)->pdi_pcibus_info); - uint64_t pci_addr; + u64 pci_addr; /* Translate to Crosstalk View of Physical Address */ pci_addr = (IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) : @@ -127,7 +127,7 @@ pcibr_dmatrans_direct64(struct pcidev_info * info, uint64_t paddr, /* Handle Bridge Chipset differences */ if (IS_PIC_SOFT(pcibus_info)) { pci_addr |= - ((uint64_t) pcibus_info-> + ((u64) pcibus_info-> pbi_hub_xid << PIC_PCI64_ATTR_TARG_SHFT); } else pci_addr |= TIOCP_PCI64_CMDTYPE_MEM; @@ -142,17 +142,17 @@ pcibr_dmatrans_direct64(struct pcidev_info * info, uint64_t paddr, static dma_addr_t pcibr_dmatrans_direct32(struct pcidev_info * info, - uint64_t paddr, size_t req_size, uint64_t flags) + u64 paddr, size_t req_size, u64 flags) { struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info; struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info-> pdi_pcibus_info; - uint64_t xio_addr; + u64 xio_addr; - uint64_t xio_base; - uint64_t offset; - uint64_t endoff; + u64 xio_base; + u64 offset; + u64 endoff; if (IS_PCIX(pcibus_info)) { return 0; @@ -209,14 +209,14 @@ pcibr_dma_unmap(struct pci_dev *hwdev, dma_addr_t dma_handle, int direction) * unlike the PIC Device(x) Write Request Buffer Flush register. */ -void sn_dma_flush(uint64_t addr) +void sn_dma_flush(u64 addr) { nasid_t nasid; int is_tio; int wid_num; int i, j; - uint64_t flags; - uint64_t itte; + u64 flags; + u64 itte; struct hubdev_info *hubinfo; volatile struct sn_flush_device_kernel *p; volatile struct sn_flush_device_common *common; @@ -299,8 +299,8 @@ void sn_dma_flush(uint64_t addr) * If CE ever needs the sn_dma_flush mechanism, we will have * to account for that here and in tioce_bus_fixup(). */ - uint32_t tio_id = HUB_L(TIO_IOSPACE_ADDR(nasid, TIO_NODE_ID)); - uint32_t revnum = XWIDGET_PART_REV_NUM(tio_id); + u32 tio_id = HUB_L(TIO_IOSPACE_ADDR(nasid, TIO_NODE_ID)); + u32 revnum = XWIDGET_PART_REV_NUM(tio_id); /* TIOCP BRINGUP WAR (PV907516): Don't write buffer flush reg */ if ((1 << XWIDGET_PART_REV_NUM_REV(revnum)) & PV907516) { @@ -315,7 +315,7 @@ void sn_dma_flush(uint64_t addr) *common->sfdl_flush_addr = 0; /* force an interrupt. */ - *(volatile uint32_t *)(common->sfdl_force_int_addr) = 1; + *(volatile u32 *)(common->sfdl_force_int_addr) = 1; /* wait for the interrupt to come back. */ while (*(common->sfdl_flush_addr) != 0x10f) diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c index e328e948175..77a1262751d 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c @@ -23,7 +23,7 @@ int sal_pcibr_slot_enable(struct pcibus_info *soft, int device, void *resp) { struct ia64_sal_retval ret_stuff; - uint64_t busnum; + u64 busnum; ret_stuff.status = 0; ret_stuff.v0 = 0; @@ -40,7 +40,7 @@ sal_pcibr_slot_disable(struct pcibus_info *soft, int device, int action, void *resp) { struct ia64_sal_retval ret_stuff; - uint64_t busnum; + u64 busnum; ret_stuff.status = 0; ret_stuff.v0 = 0; @@ -56,7 +56,7 @@ sal_pcibr_slot_disable(struct pcibus_info *soft, int device, int action, static int sal_pcibr_error_interrupt(struct pcibus_info *soft) { struct ia64_sal_retval ret_stuff; - uint64_t busnum; + u64 busnum; int segment; ret_stuff.status = 0; ret_stuff.v0 = 0; @@ -159,9 +159,9 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont /* Setup the PMU ATE map */ soft->pbi_int_ate_resource.lowest_free_index = 0; soft->pbi_int_ate_resource.ate = - kmalloc(soft->pbi_int_ate_size * sizeof(uint64_t), GFP_KERNEL); + kmalloc(soft->pbi_int_ate_size * sizeof(u64), GFP_KERNEL); memset(soft->pbi_int_ate_resource.ate, 0, - (soft->pbi_int_ate_size * sizeof(uint64_t))); + (soft->pbi_int_ate_size * sizeof(u64))); if (prom_bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP) { /* TIO PCI Bridge: find nearest node with CPUs */ @@ -203,7 +203,7 @@ void pcibr_target_interrupt(struct sn_irq_info *sn_irq_info) struct pcidev_info *pcidev_info; struct pcibus_info *pcibus_info; int bit = sn_irq_info->irq_int_bit; - uint64_t xtalk_addr = sn_irq_info->irq_xtalkaddr; + u64 xtalk_addr = sn_irq_info->irq_xtalkaddr; pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; if (pcidev_info) { diff --git a/arch/ia64/sn/pci/pcibr/pcibr_reg.c b/arch/ia64/sn/pci/pcibr/pcibr_reg.c index 79fdb91d725..8b8bbd51d43 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_reg.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_reg.c @@ -23,7 +23,7 @@ union br_ptr { /* * Control Register Access -- Read/Write 0000_0020 */ -void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits) +void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, u64 bits) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; @@ -43,7 +43,7 @@ void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits) } } -void pcireg_control_bit_set(struct pcibus_info *pcibus_info, uint64_t bits) +void pcireg_control_bit_set(struct pcibus_info *pcibus_info, u64 bits) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; @@ -66,10 +66,10 @@ void pcireg_control_bit_set(struct pcibus_info *pcibus_info, uint64_t bits) /* * PCI/PCIX Target Flush Register Access -- Read Only 0000_0050 */ -uint64_t pcireg_tflush_get(struct pcibus_info *pcibus_info) +u64 pcireg_tflush_get(struct pcibus_info *pcibus_info) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; - uint64_t ret = 0; + u64 ret = 0; if (pcibus_info) { switch (pcibus_info->pbi_bridge_type) { @@ -96,10 +96,10 @@ uint64_t pcireg_tflush_get(struct pcibus_info *pcibus_info) /* * Interrupt Status Register Access -- Read Only 0000_0100 */ -uint64_t pcireg_intr_status_get(struct pcibus_info * pcibus_info) +u64 pcireg_intr_status_get(struct pcibus_info * pcibus_info) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; - uint64_t ret = 0; + u64 ret = 0; if (pcibus_info) { switch (pcibus_info->pbi_bridge_type) { @@ -121,7 +121,7 @@ uint64_t pcireg_intr_status_get(struct pcibus_info * pcibus_info) /* * Interrupt Enable Register Access -- Read/Write 0000_0108 */ -void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits) +void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, u64 bits) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; @@ -141,7 +141,7 @@ void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits) } } -void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, uint64_t bits) +void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, u64 bits) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; @@ -165,7 +165,7 @@ void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, uint64_t bits) * Intr Host Address Register (int_addr) -- Read/Write 0000_0130 - 0000_0168 */ void pcireg_intr_addr_addr_set(struct pcibus_info *pcibus_info, int int_n, - uint64_t addr) + u64 addr) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; @@ -217,10 +217,10 @@ void pcireg_force_intr_set(struct pcibus_info *pcibus_info, int int_n) /* * Device(x) Write Buffer Flush Reg Access -- Read Only 0000_0240 - 0000_0258 */ -uint64_t pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device) +u64 pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; - uint64_t ret = 0; + u64 ret = 0; if (pcibus_info) { switch (pcibus_info->pbi_bridge_type) { @@ -242,7 +242,7 @@ uint64_t pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device) } void pcireg_int_ate_set(struct pcibus_info *pcibus_info, int ate_index, - uint64_t val) + u64 val) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; @@ -262,10 +262,10 @@ void pcireg_int_ate_set(struct pcibus_info *pcibus_info, int ate_index, } } -uint64_t __iomem *pcireg_int_ate_addr(struct pcibus_info *pcibus_info, int ate_index) +u64 __iomem *pcireg_int_ate_addr(struct pcibus_info *pcibus_info, int ate_index) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; - uint64_t __iomem *ret = NULL; + u64 __iomem *ret = NULL; if (pcibus_info) { switch (pcibus_info->pbi_bridge_type) { diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c index 27aa1842dac..7571a402552 100644 --- a/arch/ia64/sn/pci/tioca_provider.c +++ b/arch/ia64/sn/pci/tioca_provider.c @@ -16,7 +16,7 @@ #include #include -uint32_t tioca_gart_found; +u32 tioca_gart_found; EXPORT_SYMBOL(tioca_gart_found); /* used by agp-sgi */ LIST_HEAD(tioca_list); @@ -34,8 +34,8 @@ static int tioca_gart_init(struct tioca_kernel *); static int tioca_gart_init(struct tioca_kernel *tioca_kern) { - uint64_t ap_reg; - uint64_t offset; + u64 ap_reg; + u64 offset; struct page *tmp; struct tioca_common *tioca_common; struct tioca __iomem *ca_base; @@ -214,7 +214,7 @@ void tioca_fastwrite_enable(struct tioca_kernel *tioca_kern) { int cap_ptr; - uint32_t reg; + u32 reg; struct tioca __iomem *tioca_base; struct pci_dev *pdev; struct tioca_common *common; @@ -276,7 +276,7 @@ EXPORT_SYMBOL(tioca_fastwrite_enable); /* used by agp-sgi */ * We will always use 0x1 * 55:55 - Swap bytes Currently unused */ -static uint64_t +static u64 tioca_dma_d64(unsigned long paddr) { dma_addr_t bus_addr; @@ -318,15 +318,15 @@ tioca_dma_d64(unsigned long paddr) * and so a given CA can only directly target nodes in the range * xxx - xxx+255. */ -static uint64_t -tioca_dma_d48(struct pci_dev *pdev, uint64_t paddr) +static u64 +tioca_dma_d48(struct pci_dev *pdev, u64 paddr) { struct tioca_common *tioca_common; struct tioca __iomem *ca_base; - uint64_t ct_addr; + u64 ct_addr; dma_addr_t bus_addr; - uint32_t node_upper; - uint64_t agp_dma_extn; + u32 node_upper; + u64 agp_dma_extn; struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev); tioca_common = (struct tioca_common *)pcidev_info->pdi_pcibus_info; @@ -367,10 +367,10 @@ tioca_dma_d48(struct pci_dev *pdev, uint64_t paddr) * dma_addr_t is guarenteed to be contiguous in CA bus space. */ static dma_addr_t -tioca_dma_mapped(struct pci_dev *pdev, uint64_t paddr, size_t req_size) +tioca_dma_mapped(struct pci_dev *pdev, u64 paddr, size_t req_size) { int i, ps, ps_shift, entry, entries, mapsize, last_entry; - uint64_t xio_addr, end_xio_addr; + u64 xio_addr, end_xio_addr; struct tioca_common *tioca_common; struct tioca_kernel *tioca_kern; dma_addr_t bus_addr = 0; @@ -514,10 +514,10 @@ tioca_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir) * The mapping mode used is based on the devices dma_mask. As a last resort * use the GART mapped mode. */ -static uint64_t -tioca_dma_map(struct pci_dev *pdev, uint64_t paddr, size_t byte_count) +static u64 +tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count) { - uint64_t mapaddr; + u64 mapaddr; /* * If card is 64 or 48 bit addresable, use a direct mapping. 32 @@ -554,8 +554,8 @@ tioca_error_intr_handler(int irq, void *arg, struct pt_regs *pt) { struct tioca_common *soft = arg; struct ia64_sal_retval ret_stuff; - uint64_t segment; - uint64_t busnum; + u64 segment; + u64 busnum; ret_stuff.status = 0; ret_stuff.v0 = 0; @@ -620,7 +620,7 @@ tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont INIT_LIST_HEAD(&tioca_kern->ca_dmamaps); tioca_kern->ca_closest_node = nasid_to_cnodeid(tioca_common->ca_closest_nasid); - tioca_common->ca_kernel_private = (uint64_t) tioca_kern; + tioca_common->ca_kernel_private = (u64) tioca_kern; bus = pci_find_bus(tioca_common->ca_common.bs_persist_segment, tioca_common->ca_common.bs_persist_busnum); diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c index dda196c9e32..e52831ed93e 100644 --- a/arch/ia64/sn/pci/tioce_provider.c +++ b/arch/ia64/sn/pci/tioce_provider.c @@ -81,10 +81,10 @@ * 61 - 0 since this is not an MSI transaction * 60:54 - reserved, MBZ */ -static uint64_t +static u64 tioce_dma_d64(unsigned long ct_addr) { - uint64_t bus_addr; + u64 bus_addr; bus_addr = ct_addr | (1UL << 63); @@ -141,9 +141,9 @@ pcidev_to_tioce(struct pci_dev *pdev, struct tioce **base, * length, and if enough resources exist, fill in the ATE's and construct a * tioce_dmamap struct to track the mapping. */ -static uint64_t +static u64 tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, - uint64_t ct_addr, int len) + u64 ct_addr, int len) { int i; int j; @@ -152,11 +152,11 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, int entries; int nates; int pagesize; - uint64_t *ate_shadow; - uint64_t *ate_reg; - uint64_t addr; + u64 *ate_shadow; + u64 *ate_reg; + u64 addr; struct tioce *ce_mmr; - uint64_t bus_base; + u64 bus_base; struct tioce_dmamap *map; ce_mmr = (struct tioce *)ce_kern->ce_common->ce_pcibus.bs_base; @@ -224,7 +224,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, addr = ct_addr; for (j = 0; j < nates; j++) { - uint64_t ate; + u64 ate; ate = ATE_MAKE(addr, pagesize); ate_shadow[i + j] = ate; @@ -252,15 +252,15 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, * * Map @paddr into 32-bit bus space of the CE associated with @pcidev_info. */ -static uint64_t -tioce_dma_d32(struct pci_dev *pdev, uint64_t ct_addr) +static u64 +tioce_dma_d32(struct pci_dev *pdev, u64 ct_addr) { int dma_ok; int port; struct tioce *ce_mmr; struct tioce_kernel *ce_kern; - uint64_t ct_upper; - uint64_t ct_lower; + u64 ct_upper; + u64 ct_lower; dma_addr_t bus_addr; ct_upper = ct_addr & ~0x3fffffffUL; @@ -269,7 +269,7 @@ tioce_dma_d32(struct pci_dev *pdev, uint64_t ct_addr) pcidev_to_tioce(pdev, &ce_mmr, &ce_kern, &port); if (ce_kern->ce_port[port].dirmap_refcnt == 0) { - uint64_t tmp; + u64 tmp; ce_kern->ce_port[port].dirmap_shadow = ct_upper; writeq(ct_upper, &ce_mmr->ce_ure_dir_map[port]); @@ -295,10 +295,10 @@ tioce_dma_d32(struct pci_dev *pdev, uint64_t ct_addr) * Given a TIOCE bus address, set the appropriate bit to indicate barrier * attributes. */ -static uint64_t -tioce_dma_barrier(uint64_t bus_addr, int on) +static u64 +tioce_dma_barrier(u64 bus_addr, int on) { - uint64_t barrier_bit; + u64 barrier_bit; /* barrier not supported in M40/M40S mode */ if (TIOCE_M40_ADDR(bus_addr) || TIOCE_M40S_ADDR(bus_addr)) @@ -351,7 +351,7 @@ tioce_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir) list_for_each_entry(map, &ce_kern->ce_dmamap_list, ce_dmamap_list) { - uint64_t last; + u64 last; last = map->pci_start + map->nbytes - 1; if (bus_addr >= map->pci_start && bus_addr <= last) @@ -385,17 +385,17 @@ tioce_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir) * This is the main wrapper for mapping host physical pages to CE PCI space. * The mapping mode used is based on the device's dma_mask. */ -static uint64_t -tioce_do_dma_map(struct pci_dev *pdev, uint64_t paddr, size_t byte_count, +static u64 +tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, int barrier) { unsigned long flags; - uint64_t ct_addr; - uint64_t mapaddr = 0; + u64 ct_addr; + u64 mapaddr = 0; struct tioce_kernel *ce_kern; struct tioce_dmamap *map; int port; - uint64_t dma_mask; + u64 dma_mask; dma_mask = (barrier) ? pdev->dev.coherent_dma_mask : pdev->dma_mask; @@ -425,7 +425,7 @@ tioce_do_dma_map(struct pci_dev *pdev, uint64_t paddr, size_t byte_count, * address bits than this device can support. */ list_for_each_entry(map, &ce_kern->ce_dmamap_list, ce_dmamap_list) { - uint64_t last; + u64 last; last = map->ct_start + map->nbytes - 1; if (ct_addr >= map->ct_start && @@ -501,8 +501,8 @@ dma_map_done: * Simply call tioce_do_dma_map() to create a map with the barrier bit clear * in the address. */ -static uint64_t -tioce_dma(struct pci_dev *pdev, uint64_t paddr, size_t byte_count) +static u64 +tioce_dma(struct pci_dev *pdev, u64 paddr, size_t byte_count) { return tioce_do_dma_map(pdev, paddr, byte_count, 0); } @@ -515,8 +515,8 @@ tioce_dma(struct pci_dev *pdev, uint64_t paddr, size_t byte_count) * * Simply call tioce_do_dma_map() to create a map with the barrier bit set * in the address. - */ static uint64_t -tioce_dma_consistent(struct pci_dev *pdev, uint64_t paddr, size_t byte_count) + */ static u64 +tioce_dma_consistent(struct pci_dev *pdev, u64 paddr, size_t byte_count) { return tioce_do_dma_map(pdev, paddr, byte_count, 1); } @@ -551,7 +551,7 @@ tioce_error_intr_handler(int irq, void *arg, struct pt_regs *pt) tioce_kern_init(struct tioce_common *tioce_common) { int i; - uint32_t tmp; + u32 tmp; struct tioce *tioce_mmr; struct tioce_kernel *tioce_kern; @@ -563,7 +563,7 @@ tioce_kern_init(struct tioce_common *tioce_common) tioce_kern->ce_common = tioce_common; spin_lock_init(&tioce_kern->ce_lock); INIT_LIST_HEAD(&tioce_kern->ce_dmamap_list); - tioce_common->ce_kernel_private = (uint64_t) tioce_kern; + tioce_common->ce_kernel_private = (u64) tioce_kern; /* * Determine the secondary bus number of the port2 logical PPB. @@ -575,7 +575,7 @@ tioce_kern_init(struct tioce_common *tioce_common) raw_pci_ops->read(tioce_common->ce_pcibus.bs_persist_segment, tioce_common->ce_pcibus.bs_persist_busnum, PCI_DEVFN(2, 0), PCI_SECONDARY_BUS, 1, &tmp); - tioce_kern->ce_port1_secondary = (uint8_t) tmp; + tioce_kern->ce_port1_secondary = (u8) tmp; /* * Set PMU pagesize to the largest size available, and zero out @@ -615,7 +615,7 @@ tioce_force_interrupt(struct sn_irq_info *sn_irq_info) struct pcidev_info *pcidev_info; struct tioce_common *ce_common; struct tioce *ce_mmr; - uint64_t force_int_val; + u64 force_int_val; if (!sn_irq_info->irq_bridge) return; @@ -687,7 +687,7 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info) struct tioce_common *ce_common; struct tioce *ce_mmr; int bit; - uint64_t vector; + u64 vector; pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; if (!pcidev_info) @@ -699,7 +699,7 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info) bit = sn_irq_info->irq_int_bit; __sn_setq_relaxed(&ce_mmr->ce_adm_int_mask, (1UL << bit)); - vector = (uint64_t)sn_irq_info->irq_irq << INTR_VECTOR_SHFT; + vector = (u64)sn_irq_info->irq_irq << INTR_VECTOR_SHFT; vector |= sn_irq_info->irq_xtalkaddr; writeq(vector, &ce_mmr->ce_adm_int_dest[bit]); __sn_clrq_relaxed(&ce_mmr->ce_adm_int_mask, (1UL << bit)); diff --git a/include/asm-ia64/sn/intr.h b/include/asm-ia64/sn/intr.h index e35074f526d..a3431372c6e 100644 --- a/include/asm-ia64/sn/intr.h +++ b/include/asm-ia64/sn/intr.h @@ -40,7 +40,7 @@ struct sn_irq_info { int irq_cpuid; /* kernel logical cpuid */ int irq_irq; /* the IRQ number */ int irq_int_bit; /* Bridge interrupt pin */ - uint64_t irq_xtalkaddr; /* xtalkaddr IRQ is sent to */ + u64 irq_xtalkaddr; /* xtalkaddr IRQ is sent to */ int irq_bridge_type;/* pciio asic type (pciio.h) */ void *irq_bridge; /* bridge generating irq */ void *irq_pciioinfo; /* associated pciio_info_t */ diff --git a/include/asm-ia64/sn/pcibr_provider.h b/include/asm-ia64/sn/pcibr_provider.h index 2b42d9ece26..9334078b089 100644 --- a/include/asm-ia64/sn/pcibr_provider.h +++ b/include/asm-ia64/sn/pcibr_provider.h @@ -44,9 +44,9 @@ #define PCI32_MAPPED_BASE 0x40000000 #define PCI32_DIRECT_BASE 0x80000000 -#define IS_PCI32_MAPPED(x) ((uint64_t)(x) < PCI32_DIRECT_BASE && \ - (uint64_t)(x) >= PCI32_MAPPED_BASE) -#define IS_PCI32_DIRECT(x) ((uint64_t)(x) >= PCI32_MAPPED_BASE) +#define IS_PCI32_MAPPED(x) ((u64)(x) < PCI32_DIRECT_BASE && \ + (u64)(x) >= PCI32_MAPPED_BASE) +#define IS_PCI32_DIRECT(x) ((u64)(x) >= PCI32_MAPPED_BASE) /* @@ -63,7 +63,7 @@ (IOPG(IOPGOFF(addr) + (size) - 1) == IOPG((size) - 1)) #define MINIMAL_ATE_FLAG(addr, size) \ - (MINIMAL_ATES_REQUIRED((uint64_t)addr, size) ? 1 : 0) + (MINIMAL_ATES_REQUIRED((u64)addr, size) ? 1 : 0) /* bit 29 of the pci address is the SWAP bit */ #define ATE_SWAPSHIFT 29 @@ -90,27 +90,27 @@ * PMU resources. */ struct ate_resource{ - uint64_t *ate; - uint64_t num_ate; - uint64_t lowest_free_index; + u64 *ate; + u64 num_ate; + u64 lowest_free_index; }; struct pcibus_info { struct pcibus_bussoft pbi_buscommon; /* common header */ - uint32_t pbi_moduleid; + u32 pbi_moduleid; short pbi_bridge_type; short pbi_bridge_mode; struct ate_resource pbi_int_ate_resource; - uint64_t pbi_int_ate_size; + u64 pbi_int_ate_size; - uint64_t pbi_dir_xbase; + u64 pbi_dir_xbase; char pbi_hub_xid; - uint64_t pbi_devreg[8]; + u64 pbi_devreg[8]; - uint32_t pbi_valid_devices; - uint32_t pbi_enabled_devices; + u32 pbi_valid_devices; + u32 pbi_enabled_devices; spinlock_t pbi_lock; }; @@ -136,22 +136,22 @@ extern void pcibr_dma_unmap(struct pci_dev *, dma_addr_t, int); /* * prototypes for the bridge asic register access routines in pcibr_reg.c */ -extern void pcireg_control_bit_clr(struct pcibus_info *, uint64_t); -extern void pcireg_control_bit_set(struct pcibus_info *, uint64_t); -extern uint64_t pcireg_tflush_get(struct pcibus_info *); -extern uint64_t pcireg_intr_status_get(struct pcibus_info *); -extern void pcireg_intr_enable_bit_clr(struct pcibus_info *, uint64_t); -extern void pcireg_intr_enable_bit_set(struct pcibus_info *, uint64_t); -extern void pcireg_intr_addr_addr_set(struct pcibus_info *, int, uint64_t); +extern void pcireg_control_bit_clr(struct pcibus_info *, u64); +extern void pcireg_control_bit_set(struct pcibus_info *, u64); +extern u64 pcireg_tflush_get(struct pcibus_info *); +extern u64 pcireg_intr_status_get(struct pcibus_info *); +extern void pcireg_intr_enable_bit_clr(struct pcibus_info *, u64); +extern void pcireg_intr_enable_bit_set(struct pcibus_info *, u64); +extern void pcireg_intr_addr_addr_set(struct pcibus_info *, int, u64); extern void pcireg_force_intr_set(struct pcibus_info *, int); -extern uint64_t pcireg_wrb_flush_get(struct pcibus_info *, int); -extern void pcireg_int_ate_set(struct pcibus_info *, int, uint64_t); -extern uint64_t * pcireg_int_ate_addr(struct pcibus_info *, int); +extern u64 pcireg_wrb_flush_get(struct pcibus_info *, int); +extern void pcireg_int_ate_set(struct pcibus_info *, int, u64); +extern u64 * pcireg_int_ate_addr(struct pcibus_info *, int); extern void pcibr_force_interrupt(struct sn_irq_info *sn_irq_info); extern void pcibr_change_devices_irq(struct sn_irq_info *sn_irq_info); extern int pcibr_ate_alloc(struct pcibus_info *, int); extern void pcibr_ate_free(struct pcibus_info *, int); -extern void ate_write(struct pcibus_info *, int, int, uint64_t); +extern void ate_write(struct pcibus_info *, int, int, u64); extern int sal_pcibr_slot_enable(struct pcibus_info *soft, int device, void *resp); extern int sal_pcibr_slot_disable(struct pcibus_info *soft, int device, diff --git a/include/asm-ia64/sn/pcibus_provider_defs.h b/include/asm-ia64/sn/pcibus_provider_defs.h index ad0e8e8ae53..ce3f6c32824 100644 --- a/include/asm-ia64/sn/pcibus_provider_defs.h +++ b/include/asm-ia64/sn/pcibus_provider_defs.h @@ -29,13 +29,13 @@ */ struct pcibus_bussoft { - uint32_t bs_asic_type; /* chipset type */ - uint32_t bs_xid; /* xwidget id */ - uint32_t bs_persist_busnum; /* Persistent Bus Number */ - uint32_t bs_persist_segment; /* Segment Number */ - uint64_t bs_legacy_io; /* legacy io pio addr */ - uint64_t bs_legacy_mem; /* legacy mem pio addr */ - uint64_t bs_base; /* widget base */ + u32 bs_asic_type; /* chipset type */ + u32 bs_xid; /* xwidget id */ + u32 bs_persist_busnum; /* Persistent Bus Number */ + u32 bs_persist_segment; /* Segment Number */ + u64 bs_legacy_io; /* legacy io pio addr */ + u64 bs_legacy_mem; /* legacy mem pio addr */ + u64 bs_base; /* widget base */ struct xwidget_info *bs_xwidget_info; }; diff --git a/include/asm-ia64/sn/pcidev.h b/include/asm-ia64/sn/pcidev.h index f65d222ca5e..38cdffbc4c7 100644 --- a/include/asm-ia64/sn/pcidev.h +++ b/include/asm-ia64/sn/pcidev.h @@ -55,8 +55,8 @@ struct sn_pci_controller { #define PCIIO_VENDOR_ID_NONE (-1) struct pcidev_info { - uint64_t pdi_pio_mapped_addr[7]; /* 6 BARs PLUS 1 ROM */ - uint64_t pdi_slot_host_handle; /* Bus and devfn Host pci_dev */ + u64 pdi_pio_mapped_addr[7]; /* 6 BARs PLUS 1 ROM */ + u64 pdi_slot_host_handle; /* Bus and devfn Host pci_dev */ struct pcibus_bussoft *pdi_pcibus_info; /* Kernel common bus soft */ struct pcidev_info *pdi_host_pcidev_info; /* Kernel Host pci_dev */ diff --git a/include/asm-ia64/sn/pic.h b/include/asm-ia64/sn/pic.h index 0de82e6b089..5f9da5fd6e5 100644 --- a/include/asm-ia64/sn/pic.h +++ b/include/asm-ia64/sn/pic.h @@ -74,120 +74,120 @@ struct pic { /* 0x000000-0x00FFFF -- Local Registers */ /* 0x000000-0x000057 -- Standard Widget Configuration */ - uint64_t p_wid_id; /* 0x000000 */ - uint64_t p_wid_stat; /* 0x000008 */ - uint64_t p_wid_err_upper; /* 0x000010 */ - uint64_t p_wid_err_lower; /* 0x000018 */ + u64 p_wid_id; /* 0x000000 */ + u64 p_wid_stat; /* 0x000008 */ + u64 p_wid_err_upper; /* 0x000010 */ + u64 p_wid_err_lower; /* 0x000018 */ #define p_wid_err p_wid_err_lower - uint64_t p_wid_control; /* 0x000020 */ - uint64_t p_wid_req_timeout; /* 0x000028 */ - uint64_t p_wid_int_upper; /* 0x000030 */ - uint64_t p_wid_int_lower; /* 0x000038 */ + u64 p_wid_control; /* 0x000020 */ + u64 p_wid_req_timeout; /* 0x000028 */ + u64 p_wid_int_upper; /* 0x000030 */ + u64 p_wid_int_lower; /* 0x000038 */ #define p_wid_int p_wid_int_lower - uint64_t p_wid_err_cmdword; /* 0x000040 */ - uint64_t p_wid_llp; /* 0x000048 */ - uint64_t p_wid_tflush; /* 0x000050 */ + u64 p_wid_err_cmdword; /* 0x000040 */ + u64 p_wid_llp; /* 0x000048 */ + u64 p_wid_tflush; /* 0x000050 */ /* 0x000058-0x00007F -- Bridge-specific Widget Configuration */ - uint64_t p_wid_aux_err; /* 0x000058 */ - uint64_t p_wid_resp_upper; /* 0x000060 */ - uint64_t p_wid_resp_lower; /* 0x000068 */ + u64 p_wid_aux_err; /* 0x000058 */ + u64 p_wid_resp_upper; /* 0x000060 */ + u64 p_wid_resp_lower; /* 0x000068 */ #define p_wid_resp p_wid_resp_lower - uint64_t p_wid_tst_pin_ctrl; /* 0x000070 */ - uint64_t p_wid_addr_lkerr; /* 0x000078 */ + u64 p_wid_tst_pin_ctrl; /* 0x000070 */ + u64 p_wid_addr_lkerr; /* 0x000078 */ /* 0x000080-0x00008F -- PMU & MAP */ - uint64_t p_dir_map; /* 0x000080 */ - uint64_t _pad_000088; /* 0x000088 */ + u64 p_dir_map; /* 0x000080 */ + u64 _pad_000088; /* 0x000088 */ /* 0x000090-0x00009F -- SSRAM */ - uint64_t p_map_fault; /* 0x000090 */ - uint64_t _pad_000098; /* 0x000098 */ + u64 p_map_fault; /* 0x000090 */ + u64 _pad_000098; /* 0x000098 */ /* 0x0000A0-0x0000AF -- Arbitration */ - uint64_t p_arb; /* 0x0000A0 */ - uint64_t _pad_0000A8; /* 0x0000A8 */ + u64 p_arb; /* 0x0000A0 */ + u64 _pad_0000A8; /* 0x0000A8 */ /* 0x0000B0-0x0000BF -- Number In A Can or ATE Parity Error */ - uint64_t p_ate_parity_err; /* 0x0000B0 */ - uint64_t _pad_0000B8; /* 0x0000B8 */ + u64 p_ate_parity_err; /* 0x0000B0 */ + u64 _pad_0000B8; /* 0x0000B8 */ /* 0x0000C0-0x0000FF -- PCI/GIO */ - uint64_t p_bus_timeout; /* 0x0000C0 */ - uint64_t p_pci_cfg; /* 0x0000C8 */ - uint64_t p_pci_err_upper; /* 0x0000D0 */ - uint64_t p_pci_err_lower; /* 0x0000D8 */ + u64 p_bus_timeout; /* 0x0000C0 */ + u64 p_pci_cfg; /* 0x0000C8 */ + u64 p_pci_err_upper; /* 0x0000D0 */ + u64 p_pci_err_lower; /* 0x0000D8 */ #define p_pci_err p_pci_err_lower - uint64_t _pad_0000E0[4]; /* 0x0000{E0..F8} */ + u64 _pad_0000E0[4]; /* 0x0000{E0..F8} */ /* 0x000100-0x0001FF -- Interrupt */ - uint64_t p_int_status; /* 0x000100 */ - uint64_t p_int_enable; /* 0x000108 */ - uint64_t p_int_rst_stat; /* 0x000110 */ - uint64_t p_int_mode; /* 0x000118 */ - uint64_t p_int_device; /* 0x000120 */ - uint64_t p_int_host_err; /* 0x000128 */ - uint64_t p_int_addr[8]; /* 0x0001{30,,,68} */ - uint64_t p_err_int_view; /* 0x000170 */ - uint64_t p_mult_int; /* 0x000178 */ - uint64_t p_force_always[8]; /* 0x0001{80,,,B8} */ - uint64_t p_force_pin[8]; /* 0x0001{C0,,,F8} */ + u64 p_int_status; /* 0x000100 */ + u64 p_int_enable; /* 0x000108 */ + u64 p_int_rst_stat; /* 0x000110 */ + u64 p_int_mode; /* 0x000118 */ + u64 p_int_device; /* 0x000120 */ + u64 p_int_host_err; /* 0x000128 */ + u64 p_int_addr[8]; /* 0x0001{30,,,68} */ + u64 p_err_int_view; /* 0x000170 */ + u64 p_mult_int; /* 0x000178 */ + u64 p_force_always[8]; /* 0x0001{80,,,B8} */ + u64 p_force_pin[8]; /* 0x0001{C0,,,F8} */ /* 0x000200-0x000298 -- Device */ - uint64_t p_device[4]; /* 0x0002{00,,,18} */ - uint64_t _pad_000220[4]; /* 0x0002{20,,,38} */ - uint64_t p_wr_req_buf[4]; /* 0x0002{40,,,58} */ - uint64_t _pad_000260[4]; /* 0x0002{60,,,78} */ - uint64_t p_rrb_map[2]; /* 0x0002{80,,,88} */ + u64 p_device[4]; /* 0x0002{00,,,18} */ + u64 _pad_000220[4]; /* 0x0002{20,,,38} */ + u64 p_wr_req_buf[4]; /* 0x0002{40,,,58} */ + u64 _pad_000260[4]; /* 0x0002{60,,,78} */ + u64 p_rrb_map[2]; /* 0x0002{80,,,88} */ #define p_even_resp p_rrb_map[0] /* 0x000280 */ #define p_odd_resp p_rrb_map[1] /* 0x000288 */ - uint64_t p_resp_status; /* 0x000290 */ - uint64_t p_resp_clear; /* 0x000298 */ + u64 p_resp_status; /* 0x000290 */ + u64 p_resp_clear; /* 0x000298 */ - uint64_t _pad_0002A0[12]; /* 0x0002{A0..F8} */ + u64 _pad_0002A0[12]; /* 0x0002{A0..F8} */ /* 0x000300-0x0003F8 -- Buffer Address Match Registers */ struct { - uint64_t upper; /* 0x0003{00,,,F0} */ - uint64_t lower; /* 0x0003{08,,,F8} */ + u64 upper; /* 0x0003{00,,,F0} */ + u64 lower; /* 0x0003{08,,,F8} */ } p_buf_addr_match[16]; /* 0x000400-0x0005FF -- Performance Monitor Registers (even only) */ struct { - uint64_t flush_w_touch; /* 0x000{400,,,5C0} */ - uint64_t flush_wo_touch; /* 0x000{408,,,5C8} */ - uint64_t inflight; /* 0x000{410,,,5D0} */ - uint64_t prefetch; /* 0x000{418,,,5D8} */ - uint64_t total_pci_retry; /* 0x000{420,,,5E0} */ - uint64_t max_pci_retry; /* 0x000{428,,,5E8} */ - uint64_t max_latency; /* 0x000{430,,,5F0} */ - uint64_t clear_all; /* 0x000{438,,,5F8} */ + u64 flush_w_touch; /* 0x000{400,,,5C0} */ + u64 flush_wo_touch; /* 0x000{408,,,5C8} */ + u64 inflight; /* 0x000{410,,,5D0} */ + u64 prefetch; /* 0x000{418,,,5D8} */ + u64 total_pci_retry; /* 0x000{420,,,5E0} */ + u64 max_pci_retry; /* 0x000{428,,,5E8} */ + u64 max_latency; /* 0x000{430,,,5F0} */ + u64 clear_all; /* 0x000{438,,,5F8} */ } p_buf_count[8]; /* 0x000600-0x0009FF -- PCI/X registers */ - uint64_t p_pcix_bus_err_addr; /* 0x000600 */ - uint64_t p_pcix_bus_err_attr; /* 0x000608 */ - uint64_t p_pcix_bus_err_data; /* 0x000610 */ - uint64_t p_pcix_pio_split_addr; /* 0x000618 */ - uint64_t p_pcix_pio_split_attr; /* 0x000620 */ - uint64_t p_pcix_dma_req_err_attr; /* 0x000628 */ - uint64_t p_pcix_dma_req_err_addr; /* 0x000630 */ - uint64_t p_pcix_timeout; /* 0x000638 */ + u64 p_pcix_bus_err_addr; /* 0x000600 */ + u64 p_pcix_bus_err_attr; /* 0x000608 */ + u64 p_pcix_bus_err_data; /* 0x000610 */ + u64 p_pcix_pio_split_addr; /* 0x000618 */ + u64 p_pcix_pio_split_attr; /* 0x000620 */ + u64 p_pcix_dma_req_err_attr; /* 0x000628 */ + u64 p_pcix_dma_req_err_addr; /* 0x000630 */ + u64 p_pcix_timeout; /* 0x000638 */ - uint64_t _pad_000640[120]; /* 0x000{640,,,9F8} */ + u64 _pad_000640[120]; /* 0x000{640,,,9F8} */ /* 0x000A00-0x000BFF -- PCI/X Read&Write Buffer */ struct { - uint64_t p_buf_addr; /* 0x000{A00,,,AF0} */ - uint64_t p_buf_attr; /* 0X000{A08,,,AF8} */ + u64 p_buf_addr; /* 0x000{A00,,,AF0} */ + u64 p_buf_attr; /* 0X000{A08,,,AF8} */ } p_pcix_read_buf_64[16]; struct { - uint64_t p_buf_addr; /* 0x000{B00,,,BE0} */ - uint64_t p_buf_attr; /* 0x000{B08,,,BE8} */ - uint64_t p_buf_valid; /* 0x000{B10,,,BF0} */ - uint64_t __pad1; /* 0x000{B18,,,BF8} */ + u64 p_buf_addr; /* 0x000{B00,,,BE0} */ + u64 p_buf_attr; /* 0x000{B08,,,BE8} */ + u64 p_buf_valid; /* 0x000{B10,,,BF0} */ + u64 __pad1; /* 0x000{B18,,,BF8} */ } p_pcix_write_buf_64[8]; /* End of Local Registers -- Start of Address Map space */ @@ -195,45 +195,45 @@ struct pic { char _pad_000c00[0x010000 - 0x000c00]; /* 0x010000-0x011fff -- Internal ATE RAM (Auto Parity Generation) */ - uint64_t p_int_ate_ram[1024]; /* 0x010000-0x011fff */ + u64 p_int_ate_ram[1024]; /* 0x010000-0x011fff */ /* 0x012000-0x013fff -- Internal ATE RAM (Manual Parity Generation) */ - uint64_t p_int_ate_ram_mp[1024]; /* 0x012000-0x013fff */ + u64 p_int_ate_ram_mp[1024]; /* 0x012000-0x013fff */ char _pad_014000[0x18000 - 0x014000]; /* 0x18000-0x197F8 -- PIC Write Request Ram */ - uint64_t p_wr_req_lower[256]; /* 0x18000 - 0x187F8 */ - uint64_t p_wr_req_upper[256]; /* 0x18800 - 0x18FF8 */ - uint64_t p_wr_req_parity[256]; /* 0x19000 - 0x197F8 */ + u64 p_wr_req_lower[256]; /* 0x18000 - 0x187F8 */ + u64 p_wr_req_upper[256]; /* 0x18800 - 0x18FF8 */ + u64 p_wr_req_parity[256]; /* 0x19000 - 0x197F8 */ char _pad_019800[0x20000 - 0x019800]; /* 0x020000-0x027FFF -- PCI Device Configuration Spaces */ union { - uint8_t c[0x1000 / 1]; /* 0x02{0000,,,7FFF} */ - uint16_t s[0x1000 / 2]; /* 0x02{0000,,,7FFF} */ - uint32_t l[0x1000 / 4]; /* 0x02{0000,,,7FFF} */ - uint64_t d[0x1000 / 8]; /* 0x02{0000,,,7FFF} */ + u8 c[0x1000 / 1]; /* 0x02{0000,,,7FFF} */ + u16 s[0x1000 / 2]; /* 0x02{0000,,,7FFF} */ + u32 l[0x1000 / 4]; /* 0x02{0000,,,7FFF} */ + u64 d[0x1000 / 8]; /* 0x02{0000,,,7FFF} */ union { - uint8_t c[0x100 / 1]; - uint16_t s[0x100 / 2]; - uint32_t l[0x100 / 4]; - uint64_t d[0x100 / 8]; + u8 c[0x100 / 1]; + u16 s[0x100 / 2]; + u32 l[0x100 / 4]; + u64 d[0x100 / 8]; } f[8]; } p_type0_cfg_dev[8]; /* 0x02{0000,,,7FFF} */ /* 0x028000-0x028FFF -- PCI Type 1 Configuration Space */ union { - uint8_t c[0x1000 / 1]; /* 0x028000-0x029000 */ - uint16_t s[0x1000 / 2]; /* 0x028000-0x029000 */ - uint32_t l[0x1000 / 4]; /* 0x028000-0x029000 */ - uint64_t d[0x1000 / 8]; /* 0x028000-0x029000 */ + u8 c[0x1000 / 1]; /* 0x028000-0x029000 */ + u16 s[0x1000 / 2]; /* 0x028000-0x029000 */ + u32 l[0x1000 / 4]; /* 0x028000-0x029000 */ + u64 d[0x1000 / 8]; /* 0x028000-0x029000 */ union { - uint8_t c[0x100 / 1]; - uint16_t s[0x100 / 2]; - uint32_t l[0x100 / 4]; - uint64_t d[0x100 / 8]; + u8 c[0x100 / 1]; + u16 s[0x100 / 2]; + u32 l[0x100 / 4]; + u64 d[0x100 / 8]; } f[8]; } p_type1_cfg; /* 0x028000-0x029000 */ @@ -241,20 +241,20 @@ struct pic { /* 0x030000-0x030007 -- PCI Interrupt Acknowledge Cycle */ union { - uint8_t c[8 / 1]; - uint16_t s[8 / 2]; - uint32_t l[8 / 4]; - uint64_t d[8 / 8]; + u8 c[8 / 1]; + u16 s[8 / 2]; + u32 l[8 / 4]; + u64 d[8 / 8]; } p_pci_iack; /* 0x030000-0x030007 */ char _pad_030007[0x040000-0x030008]; /* 0x040000-0x030007 -- PCIX Special Cycle */ union { - uint8_t c[8 / 1]; - uint16_t s[8 / 2]; - uint32_t l[8 / 4]; - uint64_t d[8 / 8]; + u8 c[8 / 1]; + u16 s[8 / 2]; + u32 l[8 / 4]; + u64 d[8 / 8]; } p_pcix_cycle; /* 0x040000-0x040007 */ }; diff --git a/include/asm-ia64/sn/shubio.h b/include/asm-ia64/sn/shubio.h index 831b72111fd..22a6f18a531 100644 --- a/include/asm-ia64/sn/shubio.h +++ b/include/asm-ia64/sn/shubio.h @@ -227,13 +227,13 @@ ************************************************************************/ typedef union ii_wid_u { - uint64_t ii_wid_regval; + u64 ii_wid_regval; struct { - uint64_t w_rsvd_1:1; - uint64_t w_mfg_num:11; - uint64_t w_part_num:16; - uint64_t w_rev_num:4; - uint64_t w_rsvd:32; + u64 w_rsvd_1:1; + u64 w_mfg_num:11; + u64 w_part_num:16; + u64 w_rev_num:4; + u64 w_rsvd:32; } ii_wid_fld_s; } ii_wid_u_t; @@ -246,18 +246,18 @@ typedef union ii_wid_u { ************************************************************************/ typedef union ii_wstat_u { - uint64_t ii_wstat_regval; - struct { - uint64_t w_pending:4; - uint64_t w_xt_crd_to:1; - uint64_t w_xt_tail_to:1; - uint64_t w_rsvd_3:3; - uint64_t w_tx_mx_rty:1; - uint64_t w_rsvd_2:6; - uint64_t w_llp_tx_cnt:8; - uint64_t w_rsvd_1:8; - uint64_t w_crazy:1; - uint64_t w_rsvd:31; + u64 ii_wstat_regval; + struct { + u64 w_pending:4; + u64 w_xt_crd_to:1; + u64 w_xt_tail_to:1; + u64 w_rsvd_3:3; + u64 w_tx_mx_rty:1; + u64 w_rsvd_2:6; + u64 w_llp_tx_cnt:8; + u64 w_rsvd_1:8; + u64 w_crazy:1; + u64 w_rsvd:31; } ii_wstat_fld_s; } ii_wstat_u_t; @@ -269,16 +269,16 @@ typedef union ii_wstat_u { ************************************************************************/ typedef union ii_wcr_u { - uint64_t ii_wcr_regval; - struct { - uint64_t w_wid:4; - uint64_t w_tag:1; - uint64_t w_rsvd_1:8; - uint64_t w_dst_crd:3; - uint64_t w_f_bad_pkt:1; - uint64_t w_dir_con:1; - uint64_t w_e_thresh:5; - uint64_t w_rsvd:41; + u64 ii_wcr_regval; + struct { + u64 w_wid:4; + u64 w_tag:1; + u64 w_rsvd_1:8; + u64 w_dst_crd:3; + u64 w_f_bad_pkt:1; + u64 w_dir_con:1; + u64 w_e_thresh:5; + u64 w_rsvd:41; } ii_wcr_fld_s; } ii_wcr_u_t; @@ -310,9 +310,9 @@ typedef union ii_wcr_u { ************************************************************************/ typedef union ii_ilapr_u { - uint64_t ii_ilapr_regval; + u64 ii_ilapr_regval; struct { - uint64_t i_region:64; + u64 i_region:64; } ii_ilapr_fld_s; } ii_ilapr_u_t; @@ -330,9 +330,9 @@ typedef union ii_ilapr_u { ************************************************************************/ typedef union ii_ilapo_u { - uint64_t ii_ilapo_regval; + u64 ii_ilapo_regval; struct { - uint64_t i_io_ovrride:64; + u64 i_io_ovrride:64; } ii_ilapo_fld_s; } ii_ilapo_u_t; @@ -344,12 +344,12 @@ typedef union ii_ilapo_u { ************************************************************************/ typedef union ii_iowa_u { - uint64_t ii_iowa_regval; + u64 ii_iowa_regval; struct { - uint64_t i_w0_oac:1; - uint64_t i_rsvd_1:7; - uint64_t i_wx_oac:8; - uint64_t i_rsvd:48; + u64 i_w0_oac:1; + u64 i_rsvd_1:7; + u64 i_wx_oac:8; + u64 i_rsvd:48; } ii_iowa_fld_s; } ii_iowa_u_t; @@ -363,12 +363,12 @@ typedef union ii_iowa_u { ************************************************************************/ typedef union ii_iiwa_u { - uint64_t ii_iiwa_regval; + u64 ii_iiwa_regval; struct { - uint64_t i_w0_iac:1; - uint64_t i_rsvd_1:7; - uint64_t i_wx_iac:8; - uint64_t i_rsvd:48; + u64 i_w0_iac:1; + u64 i_rsvd_1:7; + u64 i_wx_iac:8; + u64 i_rsvd:48; } ii_iiwa_fld_s; } ii_iiwa_u_t; @@ -392,16 +392,16 @@ typedef union ii_iiwa_u { ************************************************************************/ typedef union ii_iidem_u { - uint64_t ii_iidem_regval; - struct { - uint64_t i_w8_dxs:8; - uint64_t i_w9_dxs:8; - uint64_t i_wa_dxs:8; - uint64_t i_wb_dxs:8; - uint64_t i_wc_dxs:8; - uint64_t i_wd_dxs:8; - uint64_t i_we_dxs:8; - uint64_t i_wf_dxs:8; + u64 ii_iidem_regval; + struct { + u64 i_w8_dxs:8; + u64 i_w9_dxs:8; + u64 i_wa_dxs:8; + u64 i_wb_dxs:8; + u64 i_wc_dxs:8; + u64 i_wd_dxs:8; + u64 i_we_dxs:8; + u64 i_wf_dxs:8; } ii_iidem_fld_s; } ii_iidem_u_t; @@ -413,22 +413,22 @@ typedef union ii_iidem_u { ************************************************************************/ typedef union ii_ilcsr_u { - uint64_t ii_ilcsr_regval; - struct { - uint64_t i_nullto:6; - uint64_t i_rsvd_4:2; - uint64_t i_wrmrst:1; - uint64_t i_rsvd_3:1; - uint64_t i_llp_en:1; - uint64_t i_bm8:1; - uint64_t i_llp_stat:2; - uint64_t i_remote_power:1; - uint64_t i_rsvd_2:1; - uint64_t i_maxrtry:10; - uint64_t i_d_avail_sel:2; - uint64_t i_rsvd_1:4; - uint64_t i_maxbrst:10; - uint64_t i_rsvd:22; + u64 ii_ilcsr_regval; + struct { + u64 i_nullto:6; + u64 i_rsvd_4:2; + u64 i_wrmrst:1; + u64 i_rsvd_3:1; + u64 i_llp_en:1; + u64 i_bm8:1; + u64 i_llp_stat:2; + u64 i_remote_power:1; + u64 i_rsvd_2:1; + u64 i_maxrtry:10; + u64 i_d_avail_sel:2; + u64 i_rsvd_1:4; + u64 i_maxbrst:10; + u64 i_rsvd:22; } ii_ilcsr_fld_s; } ii_ilcsr_u_t; @@ -441,11 +441,11 @@ typedef union ii_ilcsr_u { ************************************************************************/ typedef union ii_illr_u { - uint64_t ii_illr_regval; + u64 ii_illr_regval; struct { - uint64_t i_sn_cnt:16; - uint64_t i_cb_cnt:16; - uint64_t i_rsvd:32; + u64 i_sn_cnt:16; + u64 i_cb_cnt:16; + u64 i_rsvd:32; } ii_illr_fld_s; } ii_illr_u_t; @@ -464,19 +464,19 @@ typedef union ii_illr_u { ************************************************************************/ typedef union ii_iidsr_u { - uint64_t ii_iidsr_regval; - struct { - uint64_t i_level:8; - uint64_t i_pi_id:1; - uint64_t i_node:11; - uint64_t i_rsvd_3:4; - uint64_t i_enable:1; - uint64_t i_rsvd_2:3; - uint64_t i_int_sent:2; - uint64_t i_rsvd_1:2; - uint64_t i_pi0_forward_int:1; - uint64_t i_pi1_forward_int:1; - uint64_t i_rsvd:30; + u64 ii_iidsr_regval; + struct { + u64 i_level:8; + u64 i_pi_id:1; + u64 i_node:11; + u64 i_rsvd_3:4; + u64 i_enable:1; + u64 i_rsvd_2:3; + u64 i_int_sent:2; + u64 i_rsvd_1:2; + u64 i_pi0_forward_int:1; + u64 i_pi1_forward_int:1; + u64 i_rsvd:30; } ii_iidsr_fld_s; } ii_iidsr_u_t; @@ -492,13 +492,13 @@ typedef union ii_iidsr_u { ************************************************************************/ typedef union ii_igfx0_u { - uint64_t ii_igfx0_regval; + u64 ii_igfx0_regval; struct { - uint64_t i_w_num:4; - uint64_t i_pi_id:1; - uint64_t i_n_num:12; - uint64_t i_p_num:1; - uint64_t i_rsvd:46; + u64 i_w_num:4; + u64 i_pi_id:1; + u64 i_n_num:12; + u64 i_p_num:1; + u64 i_rsvd:46; } ii_igfx0_fld_s; } ii_igfx0_u_t; @@ -514,13 +514,13 @@ typedef union ii_igfx0_u { ************************************************************************/ typedef union ii_igfx1_u { - uint64_t ii_igfx1_regval; + u64 ii_igfx1_regval; struct { - uint64_t i_w_num:4; - uint64_t i_pi_id:1; - uint64_t i_n_num:12; - uint64_t i_p_num:1; - uint64_t i_rsvd:46; + u64 i_w_num:4; + u64 i_pi_id:1; + u64 i_n_num:12; + u64 i_p_num:1; + u64 i_rsvd:46; } ii_igfx1_fld_s; } ii_igfx1_u_t; @@ -532,9 +532,9 @@ typedef union ii_igfx1_u { ************************************************************************/ typedef union ii_iscr0_u { - uint64_t ii_iscr0_regval; + u64 ii_iscr0_regval; struct { - uint64_t i_scratch:64; + u64 i_scratch:64; } ii_iscr0_fld_s; } ii_iscr0_u_t; @@ -546,9 +546,9 @@ typedef union ii_iscr0_u { ************************************************************************/ typedef union ii_iscr1_u { - uint64_t ii_iscr1_regval; + u64 ii_iscr1_regval; struct { - uint64_t i_scratch:64; + u64 i_scratch:64; } ii_iscr1_fld_s; } ii_iscr1_u_t; @@ -580,13 +580,13 @@ typedef union ii_iscr1_u { ************************************************************************/ typedef union ii_itte1_u { - uint64_t ii_itte1_regval; + u64 ii_itte1_regval; struct { - uint64_t i_offset:5; - uint64_t i_rsvd_1:3; - uint64_t i_w_num:4; - uint64_t i_iosp:1; - uint64_t i_rsvd:51; + u64 i_offset:5; + u64 i_rsvd_1:3; + u64 i_w_num:4; + u64 i_iosp:1; + u64 i_rsvd:51; } ii_itte1_fld_s; } ii_itte1_u_t; @@ -618,13 +618,13 @@ typedef union ii_itte1_u { ************************************************************************/ typedef union ii_itte2_u { - uint64_t ii_itte2_regval; + u64 ii_itte2_regval; struct { - uint64_t i_offset:5; - uint64_t i_rsvd_1:3; - uint64_t i_w_num:4; - uint64_t i_iosp:1; - uint64_t i_rsvd:51; + u64 i_offset:5; + u64 i_rsvd_1:3; + u64 i_w_num:4; + u64 i_iosp:1; + u64 i_rsvd:51; } ii_itte2_fld_s; } ii_itte2_u_t; @@ -656,13 +656,13 @@ typedef union ii_itte2_u { ************************************************************************/ typedef union ii_itte3_u { - uint64_t ii_itte3_regval; + u64 ii_itte3_regval; struct { - uint64_t i_offset:5; - uint64_t i_rsvd_1:3; - uint64_t i_w_num:4; - uint64_t i_iosp:1; - uint64_t i_rsvd:51; + u64 i_offset:5; + u64 i_rsvd_1:3; + u64 i_w_num:4; + u64 i_iosp:1; + u64 i_rsvd:51; } ii_itte3_fld_s; } ii_itte3_u_t; @@ -694,13 +694,13 @@ typedef union ii_itte3_u { ************************************************************************/ typedef union ii_itte4_u { - uint64_t ii_itte4_regval; + u64 ii_itte4_regval; struct { - uint64_t i_offset:5; - uint64_t i_rsvd_1:3; - uint64_t i_w_num:4; - uint64_t i_iosp:1; - uint64_t i_rsvd:51; + u64 i_offset:5; + u64 i_rsvd_1:3; + u64 i_w_num:4; + u64 i_iosp:1; + u64 i_rsvd:51; } ii_itte4_fld_s; } ii_itte4_u_t; @@ -732,13 +732,13 @@ typedef union ii_itte4_u { ************************************************************************/ typedef union ii_itte5_u { - uint64_t ii_itte5_regval; + u64 ii_itte5_regval; struct { - uint64_t i_offset:5; - uint64_t i_rsvd_1:3; - uint64_t i_w_num:4; - uint64_t i_iosp:1; - uint64_t i_rsvd:51; + u64 i_offset:5; + u64 i_rsvd_1:3; + u64 i_w_num:4; + u64 i_iosp:1; + u64 i_rsvd:51; } ii_itte5_fld_s; } ii_itte5_u_t; @@ -770,13 +770,13 @@ typedef union ii_itte5_u { ************************************************************************/ typedef union ii_itte6_u { - uint64_t ii_itte6_regval; + u64 ii_itte6_regval; struct { - uint64_t i_offset:5; - uint64_t i_rsvd_1:3; - uint64_t i_w_num:4; - uint64_t i_iosp:1; - uint64_t i_rsvd:51; + u64 i_offset:5; + u64 i_rsvd_1:3; + u64 i_w_num:4; + u64 i_iosp:1; + u64 i_rsvd:51; } ii_itte6_fld_s; } ii_itte6_u_t; @@ -808,13 +808,13 @@ typedef union ii_itte6_u { ************************************************************************/ typedef union ii_itte7_u { - uint64_t ii_itte7_regval; + u64 ii_itte7_regval; struct { - uint64_t i_offset:5; - uint64_t i_rsvd_1:3; - uint64_t i_w_num:4; - uint64_t i_iosp:1; - uint64_t i_rsvd:51; + u64 i_offset:5; + u64 i_rsvd_1:3; + u64 i_w_num:4; + u64 i_iosp:1; + u64 i_rsvd:51; } ii_itte7_fld_s; } ii_itte7_u_t; @@ -843,22 +843,22 @@ typedef union ii_itte7_u { ************************************************************************/ typedef union ii_iprb0_u { - uint64_t ii_iprb0_regval; - struct { - uint64_t i_c:8; - uint64_t i_na:14; - uint64_t i_rsvd_2:2; - uint64_t i_nb:14; - uint64_t i_rsvd_1:2; - uint64_t i_m:2; - uint64_t i_f:1; - uint64_t i_of_cnt:5; - uint64_t i_error:1; - uint64_t i_rd_to:1; - uint64_t i_spur_wr:1; - uint64_t i_spur_rd:1; - uint64_t i_rsvd:11; - uint64_t i_mult_err:1; + u64 ii_iprb0_regval; + struct { + u64 i_c:8; + u64 i_na:14; + u64 i_rsvd_2:2; + u64 i_nb:14; + u64 i_rsvd_1:2; + u64 i_m:2; + u64 i_f:1; + u64 i_of_cnt:5; + u64 i_error:1; + u64 i_rd_to:1; + u64 i_spur_wr:1; + u64 i_spur_rd:1; + u64 i_rsvd:11; + u64 i_mult_err:1; } ii_iprb0_fld_s; } ii_iprb0_u_t; @@ -887,22 +887,22 @@ typedef union ii_iprb0_u { ************************************************************************/ typedef union ii_iprb8_u { - uint64_t ii_iprb8_regval; - struct { - uint64_t i_c:8; - uint64_t i_na:14; - uint64_t i_rsvd_2:2; - uint64_t i_nb:14; - uint64_t i_rsvd_1:2; - uint64_t i_m:2; - uint64_t i_f:1; - uint64_t i_of_cnt:5; - uint64_t i_error:1; - uint64_t i_rd_to:1; - uint64_t i_spur_wr:1; - uint64_t i_spur_rd:1; - uint64_t i_rsvd:11; - uint64_t i_mult_err:1; + u64 ii_iprb8_regval; + struct { + u64 i_c:8; + u64 i_na:14; + u64 i_rsvd_2:2; + u64 i_nb:14; + u64 i_rsvd_1:2; + u64 i_m:2; + u64 i_f:1; + u64 i_of_cnt:5; + u64 i_error:1; + u64 i_rd_to:1; + u64 i_spur_wr:1; + u64 i_spur_rd:1; + u64 i_rsvd:11; + u64 i_mult_err:1; } ii_iprb8_fld_s; } ii_iprb8_u_t; @@ -931,22 +931,22 @@ typedef union ii_iprb8_u { ************************************************************************/ typedef union ii_iprb9_u { - uint64_t ii_iprb9_regval; - struct { - uint64_t i_c:8; - uint64_t i_na:14; - uint64_t i_rsvd_2:2; - uint64_t i_nb:14; - uint64_t i_rsvd_1:2; - uint64_t i_m:2; - uint64_t i_f:1; - uint64_t i_of_cnt:5; - uint64_t i_error:1; - uint64_t i_rd_to:1; - uint64_t i_spur_wr:1; - uint64_t i_spur_rd:1; - uint64_t i_rsvd:11; - uint64_t i_mult_err:1; + u64 ii_iprb9_regval; + struct { + u64 i_c:8; + u64 i_na:14; + u64 i_rsvd_2:2; + u64 i_nb:14; + u64 i_rsvd_1:2; + u64 i_m:2; + u64 i_f:1; + u64 i_of_cnt:5; + u64 i_error:1; + u64 i_rd_to:1; + u64 i_spur_wr:1; + u64 i_spur_rd:1; + u64 i_rsvd:11; + u64 i_mult_err:1; } ii_iprb9_fld_s; } ii_iprb9_u_t; @@ -975,22 +975,22 @@ typedef union ii_iprb9_u { ************************************************************************/ typedef union ii_iprba_u { - uint64_t ii_iprba_regval; - struct { - uint64_t i_c:8; - uint64_t i_na:14; - uint64_t i_rsvd_2:2; - uint64_t i_nb:14; - uint64_t i_rsvd_1:2; - uint64_t i_m:2; - uint64_t i_f:1; - uint64_t i_of_cnt:5; - uint64_t i_error:1; - uint64_t i_rd_to:1; - uint64_t i_spur_wr:1; - uint64_t i_spur_rd:1; - uint64_t i_rsvd:11; - uint64_t i_mult_err:1; + u64 ii_iprba_regval; + struct { + u64 i_c:8; + u64 i_na:14; + u64 i_rsvd_2:2; + u64 i_nb:14; + u64 i_rsvd_1:2; + u64 i_m:2; + u64 i_f:1; + u64 i_of_cnt:5; + u64 i_error:1; + u64 i_rd_to:1; + u64 i_spur_wr:1; + u64 i_spur_rd:1; + u64 i_rsvd:11; + u64 i_mult_err:1; } ii_iprba_fld_s; } ii_iprba_u_t; @@ -1019,22 +1019,22 @@ typedef union ii_iprba_u { ************************************************************************/ typedef union ii_iprbb_u { - uint64_t ii_iprbb_regval; - struct { - uint64_t i_c:8; - uint64_t i_na:14; - uint64_t i_rsvd_2:2; - uint64_t i_nb:14; - uint64_t i_rsvd_1:2; - uint64_t i_m:2; - uint64_t i_f:1; - uint64_t i_of_cnt:5; - uint64_t i_error:1; - uint64_t i_rd_to:1; - uint64_t i_spur_wr:1; - uint64_t i_spur_rd:1; - uint64_t i_rsvd:11; - uint64_t i_mult_err:1; + u64 ii_iprbb_regval; + struct { + u64 i_c:8; + u64 i_na:14; + u64 i_rsvd_2:2; + u64 i_nb:14; + u64 i_rsvd_1:2; + u64 i_m:2; + u64 i_f:1; + u64 i_of_cnt:5; + u64 i_error:1; + u64 i_rd_to:1; + u64 i_spur_wr:1; + u64 i_spur_rd:1; + u64 i_rsvd:11; + u64 i_mult_err:1; } ii_iprbb_fld_s; } ii_iprbb_u_t; @@ -1063,22 +1063,22 @@ typedef union ii_iprbb_u { ************************************************************************/ typedef union ii_iprbc_u { - uint64_t ii_iprbc_regval; - struct { - uint64_t i_c:8; - uint64_t i_na:14; - uint64_t i_rsvd_2:2; - uint64_t i_nb:14; - uint64_t i_rsvd_1:2; - uint64_t i_m:2; - uint64_t i_f:1; - uint64_t i_of_cnt:5; - uint64_t i_error:1; - uint64_t i_rd_to:1; - uint64_t i_spur_wr:1; - uint64_t i_spur_rd:1; - uint64_t i_rsvd:11; - uint64_t i_mult_err:1; + u64 ii_iprbc_regval; + struct { + u64 i_c:8; + u64 i_na:14; + u64 i_rsvd_2:2; + u64 i_nb:14; + u64 i_rsvd_1:2; + u64 i_m:2; + u64 i_f:1; + u64 i_of_cnt:5; + u64 i_error:1; + u64 i_rd_to:1; + u64 i_spur_wr:1; + u64 i_spur_rd:1; + u64 i_rsvd:11; + u64 i_mult_err:1; } ii_iprbc_fld_s; } ii_iprbc_u_t; @@ -1107,22 +1107,22 @@ typedef union ii_iprbc_u { ************************************************************************/ typedef union ii_iprbd_u { - uint64_t ii_iprbd_regval; - struct { - uint64_t i_c:8; - uint64_t i_na:14; - uint64_t i_rsvd_2:2; - uint64_t i_nb:14; - uint64_t i_rsvd_1:2; - uint64_t i_m:2; - uint64_t i_f:1; - uint64_t i_of_cnt:5; - uint64_t i_error:1; - uint64_t i_rd_to:1; - uint64_t i_spur_wr:1; - uint64_t i_spur_rd:1; - uint64_t i_rsvd:11; - uint64_t i_mult_err:1; + u64 ii_iprbd_regval; + struct { + u64 i_c:8; + u64 i_na:14; + u64 i_rsvd_2:2; + u64 i_nb:14; + u64 i_rsvd_1:2; + u64 i_m:2; + u64 i_f:1; + u64 i_of_cnt:5; + u64 i_error:1; + u64 i_rd_to:1; + u64 i_spur_wr:1; + u64 i_spur_rd:1; + u64 i_rsvd:11; + u64 i_mult_err:1; } ii_iprbd_fld_s; } ii_iprbd_u_t; @@ -1151,22 +1151,22 @@ typedef union ii_iprbd_u { ************************************************************************/ typedef union ii_iprbe_u { - uint64_t ii_iprbe_regval; - struct { - uint64_t i_c:8; - uint64_t i_na:14; - uint64_t i_rsvd_2:2; - uint64_t i_nb:14; - uint64_t i_rsvd_1:2; - uint64_t i_m:2; - uint64_t i_f:1; - uint64_t i_of_cnt:5; - uint64_t i_error:1; - uint64_t i_rd_to:1; - uint64_t i_spur_wr:1; - uint64_t i_spur_rd:1; - uint64_t i_rsvd:11; - uint64_t i_mult_err:1; + u64 ii_iprbe_regval; + struct { + u64 i_c:8; + u64 i_na:14; + u64 i_rsvd_2:2; + u64 i_nb:14; + u64 i_rsvd_1:2; + u64 i_m:2; + u64 i_f:1; + u64 i_of_cnt:5; + u64 i_error:1; + u64 i_rd_to:1; + u64 i_spur_wr:1; + u64 i_spur_rd:1; + u64 i_rsvd:11; + u64 i_mult_err:1; } ii_iprbe_fld_s; } ii_iprbe_u_t; @@ -1195,22 +1195,22 @@ typedef union ii_iprbe_u { ************************************************************************/ typedef union ii_iprbf_u { - uint64_t ii_iprbf_regval; - struct { - uint64_t i_c:8; - uint64_t i_na:14; - uint64_t i_rsvd_2:2; - uint64_t i_nb:14; - uint64_t i_rsvd_1:2; - uint64_t i_m:2; - uint64_t i_f:1; - uint64_t i_of_cnt:5; - uint64_t i_error:1; - uint64_t i_rd_to:1; - uint64_t i_spur_wr:1; - uint64_t i_spur_rd:1; - uint64_t i_rsvd:11; - uint64_t i_mult_err:1; + u64 ii_iprbf_regval; + struct { + u64 i_c:8; + u64 i_na:14; + u64 i_rsvd_2:2; + u64 i_nb:14; + u64 i_rsvd_1:2; + u64 i_m:2; + u64 i_f:1; + u64 i_of_cnt:5; + u64 i_error:1; + u64 i_rd_to:1; + u64 i_spur_wr:1; + u64 i_spur_rd:1; + u64 i_rsvd:11; + u64 i_mult_err:1; } ii_iprbe_fld_s; } ii_iprbf_u_t; @@ -1232,10 +1232,10 @@ typedef union ii_iprbf_u { ************************************************************************/ typedef union ii_ixcc_u { - uint64_t ii_ixcc_regval; + u64 ii_ixcc_regval; struct { - uint64_t i_time_out:26; - uint64_t i_rsvd:38; + u64 i_time_out:26; + u64 i_rsvd:38; } ii_ixcc_fld_s; } ii_ixcc_u_t; @@ -1256,16 +1256,16 @@ typedef union ii_ixcc_u { ************************************************************************/ typedef union ii_imem_u { - uint64_t ii_imem_regval; - struct { - uint64_t i_w0_esd:1; - uint64_t i_rsvd_3:3; - uint64_t i_b0_esd:1; - uint64_t i_rsvd_2:3; - uint64_t i_b1_esd:1; - uint64_t i_rsvd_1:3; - uint64_t i_clr_precise:1; - uint64_t i_rsvd:51; + u64 ii_imem_regval; + struct { + u64 i_w0_esd:1; + u64 i_rsvd_3:3; + u64 i_b0_esd:1; + u64 i_rsvd_2:3; + u64 i_b1_esd:1; + u64 i_rsvd_1:3; + u64 i_clr_precise:1; + u64 i_rsvd:51; } ii_imem_fld_s; } ii_imem_u_t; @@ -1294,13 +1294,13 @@ typedef union ii_imem_u { ************************************************************************/ typedef union ii_ixtt_u { - uint64_t ii_ixtt_regval; + u64 ii_ixtt_regval; struct { - uint64_t i_tail_to:26; - uint64_t i_rsvd_1:6; - uint64_t i_rrsp_ps:23; - uint64_t i_rrsp_to:5; - uint64_t i_rsvd:4; + u64 i_tail_to:26; + u64 i_rsvd_1:6; + u64 i_rrsp_ps:23; + u64 i_rrsp_to:5; + u64 i_rsvd:4; } ii_ixtt_fld_s; } ii_ixtt_u_t; @@ -1316,37 +1316,37 @@ typedef union ii_ixtt_u { ************************************************************************/ typedef union ii_ieclr_u { - uint64_t ii_ieclr_regval; - struct { - uint64_t i_e_prb_0:1; - uint64_t i_rsvd:7; - uint64_t i_e_prb_8:1; - uint64_t i_e_prb_9:1; - uint64_t i_e_prb_a:1; - uint64_t i_e_prb_b:1; - uint64_t i_e_prb_c:1; - uint64_t i_e_prb_d:1; - uint64_t i_e_prb_e:1; - uint64_t i_e_prb_f:1; - uint64_t i_e_crazy:1; - uint64_t i_e_bte_0:1; - uint64_t i_e_bte_1:1; - uint64_t i_reserved_1:10; - uint64_t i_spur_rd_hdr:1; - uint64_t i_cam_intr_to:1; - uint64_t i_cam_overflow:1; - uint64_t i_cam_read_miss:1; - uint64_t i_ioq_rep_underflow:1; - uint64_t i_ioq_req_underflow:1; - uint64_t i_ioq_rep_overflow:1; - uint64_t i_ioq_req_overflow:1; - uint64_t i_iiq_rep_overflow:1; - uint64_t i_iiq_req_overflow:1; - uint64_t i_ii_xn_rep_cred_overflow:1; - uint64_t i_ii_xn_req_cred_overflow:1; - uint64_t i_ii_xn_invalid_cmd:1; - uint64_t i_xn_ii_invalid_cmd:1; - uint64_t i_reserved_2:21; + u64 ii_ieclr_regval; + struct { + u64 i_e_prb_0:1; + u64 i_rsvd:7; + u64 i_e_prb_8:1; + u64 i_e_prb_9:1; + u64 i_e_prb_a:1; + u64 i_e_prb_b:1; + u64 i_e_prb_c:1; + u64 i_e_prb_d:1; + u64 i_e_prb_e:1; + u64 i_e_prb_f:1; + u64 i_e_crazy:1; + u64 i_e_bte_0:1; + u64 i_e_bte_1:1; + u64 i_reserved_1:10; + u64 i_spur_rd_hdr:1; + u64 i_cam_intr_to:1; + u64 i_cam_overflow:1; + u64 i_cam_read_miss:1; + u64 i_ioq_rep_underflow:1; + u64 i_ioq_req_underflow:1; + u64 i_ioq_rep_overflow:1; + u64 i_ioq_req_overflow:1; + u64 i_iiq_rep_overflow:1; + u64 i_iiq_req_overflow:1; + u64 i_ii_xn_rep_cred_overflow:1; + u64 i_ii_xn_req_cred_overflow:1; + u64 i_ii_xn_invalid_cmd:1; + u64 i_xn_ii_invalid_cmd:1; + u64 i_reserved_2:21; } ii_ieclr_fld_s; } ii_ieclr_u_t; @@ -1360,12 +1360,12 @@ typedef union ii_ieclr_u { ************************************************************************/ typedef union ii_ibcr_u { - uint64_t ii_ibcr_regval; + u64 ii_ibcr_regval; struct { - uint64_t i_count:4; - uint64_t i_rsvd_1:4; - uint64_t i_soft_reset:1; - uint64_t i_rsvd:55; + u64 i_count:4; + u64 i_rsvd_1:4; + u64 i_soft_reset:1; + u64 i_rsvd:55; } ii_ibcr_fld_s; } ii_ibcr_u_t; @@ -1399,22 +1399,22 @@ typedef union ii_ibcr_u { ************************************************************************/ typedef union ii_ixsm_u { - uint64_t ii_ixsm_regval; - struct { - uint64_t i_byte_en:32; - uint64_t i_reserved:1; - uint64_t i_tag:3; - uint64_t i_alt_pactyp:4; - uint64_t i_bo:1; - uint64_t i_error:1; - uint64_t i_vbpm:1; - uint64_t i_gbr:1; - uint64_t i_ds:2; - uint64_t i_ct:1; - uint64_t i_tnum:5; - uint64_t i_pactyp:4; - uint64_t i_sidn:4; - uint64_t i_didn:4; + u64 ii_ixsm_regval; + struct { + u64 i_byte_en:32; + u64 i_reserved:1; + u64 i_tag:3; + u64 i_alt_pactyp:4; + u64 i_bo:1; + u64 i_error:1; + u64 i_vbpm:1; + u64 i_gbr:1; + u64 i_ds:2; + u64 i_ct:1; + u64 i_tnum:5; + u64 i_pactyp:4; + u64 i_sidn:4; + u64 i_didn:4; } ii_ixsm_fld_s; } ii_ixsm_u_t; @@ -1426,11 +1426,11 @@ typedef union ii_ixsm_u { ************************************************************************/ typedef union ii_ixss_u { - uint64_t ii_ixss_regval; + u64 ii_ixss_regval; struct { - uint64_t i_sideband:8; - uint64_t i_rsvd:55; - uint64_t i_valid:1; + u64 i_sideband:8; + u64 i_rsvd:55; + u64 i_valid:1; } ii_ixss_fld_s; } ii_ixss_u_t; @@ -1447,17 +1447,17 @@ typedef union ii_ixss_u { ************************************************************************/ typedef union ii_ilct_u { - uint64_t ii_ilct_regval; - struct { - uint64_t i_test_seed:20; - uint64_t i_test_mask:8; - uint64_t i_test_data:20; - uint64_t i_test_valid:1; - uint64_t i_test_cberr:1; - uint64_t i_test_flit:3; - uint64_t i_test_clear:1; - uint64_t i_test_err_capture:1; - uint64_t i_rsvd:9; + u64 ii_ilct_regval; + struct { + u64 i_test_seed:20; + u64 i_test_mask:8; + u64 i_test_data:20; + u64 i_test_valid:1; + u64 i_test_cberr:1; + u64 i_test_flit:3; + u64 i_test_clear:1; + u64 i_test_err_capture:1; + u64 i_rsvd:9; } ii_ilct_fld_s; } ii_ilct_u_t; @@ -1482,20 +1482,20 @@ typedef union ii_ilct_u { ************************************************************************/ typedef union ii_iieph1_u { - uint64_t ii_iieph1_regval; - struct { - uint64_t i_command:7; - uint64_t i_rsvd_5:1; - uint64_t i_suppl:14; - uint64_t i_rsvd_4:1; - uint64_t i_source:14; - uint64_t i_rsvd_3:1; - uint64_t i_err_type:4; - uint64_t i_rsvd_2:4; - uint64_t i_overrun:1; - uint64_t i_rsvd_1:3; - uint64_t i_valid:1; - uint64_t i_rsvd:13; + u64 ii_iieph1_regval; + struct { + u64 i_command:7; + u64 i_rsvd_5:1; + u64 i_suppl:14; + u64 i_rsvd_4:1; + u64 i_source:14; + u64 i_rsvd_3:1; + u64 i_err_type:4; + u64 i_rsvd_2:4; + u64 i_overrun:1; + u64 i_rsvd_1:3; + u64 i_valid:1; + u64 i_rsvd:13; } ii_iieph1_fld_s; } ii_iieph1_u_t; @@ -1511,13 +1511,13 @@ typedef union ii_iieph1_u { ************************************************************************/ typedef union ii_iieph2_u { - uint64_t ii_iieph2_regval; + u64 ii_iieph2_regval; struct { - uint64_t i_rsvd_0:3; - uint64_t i_address:47; - uint64_t i_rsvd_1:10; - uint64_t i_tail:1; - uint64_t i_rsvd:3; + u64 i_rsvd_0:3; + u64 i_address:47; + u64 i_rsvd_1:10; + u64 i_tail:1; + u64 i_rsvd:3; } ii_iieph2_fld_s; } ii_iieph2_u_t; @@ -1532,9 +1532,9 @@ typedef union ii_iieph2_u { ************************************************************************/ typedef union ii_islapr_u { - uint64_t ii_islapr_regval; + u64 ii_islapr_regval; struct { - uint64_t i_region:64; + u64 i_region:64; } ii_islapr_fld_s; } ii_islapr_u_t; @@ -1547,10 +1547,10 @@ typedef union ii_islapr_u { ************************************************************************/ typedef union ii_islapo_u { - uint64_t ii_islapo_regval; + u64 ii_islapo_regval; struct { - uint64_t i_io_sbx_ovrride:56; - uint64_t i_rsvd:8; + u64 i_io_sbx_ovrride:56; + u64 i_rsvd:8; } ii_islapo_fld_s; } ii_islapo_u_t; @@ -1563,14 +1563,14 @@ typedef union ii_islapo_u { ************************************************************************/ typedef union ii_iwi_u { - uint64_t ii_iwi_regval; - struct { - uint64_t i_prescale:24; - uint64_t i_rsvd:8; - uint64_t i_timeout:8; - uint64_t i_rsvd1:8; - uint64_t i_intrpt_retry_period:8; - uint64_t i_rsvd2:8; + u64 ii_iwi_regval; + struct { + u64 i_prescale:24; + u64 i_rsvd:8; + u64 i_timeout:8; + u64 i_rsvd1:8; + u64 i_intrpt_retry_period:8; + u64 i_rsvd2:8; } ii_iwi_fld_s; } ii_iwi_u_t; @@ -1582,26 +1582,26 @@ typedef union ii_iwi_u { ************************************************************************/ typedef union ii_iwel_u { - uint64_t ii_iwel_regval; - struct { - uint64_t i_intr_timed_out:1; - uint64_t i_rsvd:7; - uint64_t i_cam_overflow:1; - uint64_t i_cam_read_miss:1; - uint64_t i_rsvd1:2; - uint64_t i_ioq_rep_underflow:1; - uint64_t i_ioq_req_underflow:1; - uint64_t i_ioq_rep_overflow:1; - uint64_t i_ioq_req_overflow:1; - uint64_t i_iiq_rep_overflow:1; - uint64_t i_iiq_req_overflow:1; - uint64_t i_rsvd2:6; - uint64_t i_ii_xn_rep_cred_over_under:1; - uint64_t i_ii_xn_req_cred_over_under:1; - uint64_t i_rsvd3:6; - uint64_t i_ii_xn_invalid_cmd:1; - uint64_t i_xn_ii_invalid_cmd:1; - uint64_t i_rsvd4:30; + u64 ii_iwel_regval; + struct { + u64 i_intr_timed_out:1; + u64 i_rsvd:7; + u64 i_cam_overflow:1; + u64 i_cam_read_miss:1; + u64 i_rsvd1:2; + u64 i_ioq_rep_underflow:1; + u64 i_ioq_req_underflow:1; + u64 i_ioq_rep_overflow:1; + u64 i_ioq_req_overflow:1; + u64 i_iiq_rep_overflow:1; + u64 i_iiq_req_overflow:1; + u64 i_rsvd2:6; + u64 i_ii_xn_rep_cred_over_under:1; + u64 i_ii_xn_req_cred_over_under:1; + u64 i_rsvd3:6; + u64 i_ii_xn_invalid_cmd:1; + u64 i_xn_ii_invalid_cmd:1; + u64 i_rsvd4:30; } ii_iwel_fld_s; } ii_iwel_u_t; @@ -1612,22 +1612,22 @@ typedef union ii_iwel_u { ************************************************************************/ typedef union ii_iwc_u { - uint64_t ii_iwc_regval; - struct { - uint64_t i_dma_byte_swap:1; - uint64_t i_rsvd:3; - uint64_t i_cam_read_lines_reset:1; - uint64_t i_rsvd1:3; - uint64_t i_ii_xn_cred_over_under_log:1; - uint64_t i_rsvd2:19; - uint64_t i_xn_rep_iq_depth:5; - uint64_t i_rsvd3:3; - uint64_t i_xn_req_iq_depth:5; - uint64_t i_rsvd4:3; - uint64_t i_iiq_depth:6; - uint64_t i_rsvd5:12; - uint64_t i_force_rep_cred:1; - uint64_t i_force_req_cred:1; + u64 ii_iwc_regval; + struct { + u64 i_dma_byte_swap:1; + u64 i_rsvd:3; + u64 i_cam_read_lines_reset:1; + u64 i_rsvd1:3; + u64 i_ii_xn_cred_over_under_log:1; + u64 i_rsvd2:19; + u64 i_xn_rep_iq_depth:5; + u64 i_rsvd3:3; + u64 i_xn_req_iq_depth:5; + u64 i_rsvd4:3; + u64 i_iiq_depth:6; + u64 i_rsvd5:12; + u64 i_force_rep_cred:1; + u64 i_force_req_cred:1; } ii_iwc_fld_s; } ii_iwc_u_t; @@ -1638,12 +1638,12 @@ typedef union ii_iwc_u { ************************************************************************/ typedef union ii_iws_u { - uint64_t ii_iws_regval; + u64 ii_iws_regval; struct { - uint64_t i_xn_rep_iq_credits:5; - uint64_t i_rsvd:3; - uint64_t i_xn_req_iq_credits:5; - uint64_t i_rsvd1:51; + u64 i_xn_rep_iq_credits:5; + u64 i_rsvd:3; + u64 i_xn_req_iq_credits:5; + u64 i_rsvd1:51; } ii_iws_fld_s; } ii_iws_u_t; @@ -1654,26 +1654,26 @@ typedef union ii_iws_u { ************************************************************************/ typedef union ii_iweim_u { - uint64_t ii_iweim_regval; - struct { - uint64_t i_intr_timed_out:1; - uint64_t i_rsvd:7; - uint64_t i_cam_overflow:1; - uint64_t i_cam_read_miss:1; - uint64_t i_rsvd1:2; - uint64_t i_ioq_rep_underflow:1; - uint64_t i_ioq_req_underflow:1; - uint64_t i_ioq_rep_overflow:1; - uint64_t i_ioq_req_overflow:1; - uint64_t i_iiq_rep_overflow:1; - uint64_t i_iiq_req_overflow:1; - uint64_t i_rsvd2:6; - uint64_t i_ii_xn_rep_cred_overflow:1; - uint64_t i_ii_xn_req_cred_overflow:1; - uint64_t i_rsvd3:6; - uint64_t i_ii_xn_invalid_cmd:1; - uint64_t i_xn_ii_invalid_cmd:1; - uint64_t i_rsvd4:30; + u64 ii_iweim_regval; + struct { + u64 i_intr_timed_out:1; + u64 i_rsvd:7; + u64 i_cam_overflow:1; + u64 i_cam_read_miss:1; + u64 i_rsvd1:2; + u64 i_ioq_rep_underflow:1; + u64 i_ioq_req_underflow:1; + u64 i_ioq_rep_overflow:1; + u64 i_ioq_req_overflow:1; + u64 i_iiq_rep_overflow:1; + u64 i_iiq_req_overflow:1; + u64 i_rsvd2:6; + u64 i_ii_xn_rep_cred_overflow:1; + u64 i_ii_xn_req_cred_overflow:1; + u64 i_rsvd3:6; + u64 i_ii_xn_invalid_cmd:1; + u64 i_xn_ii_invalid_cmd:1; + u64 i_rsvd4:30; } ii_iweim_fld_s; } ii_iweim_u_t; @@ -1688,13 +1688,13 @@ typedef union ii_iweim_u { ************************************************************************/ typedef union ii_ipca_u { - uint64_t ii_ipca_regval; + u64 ii_ipca_regval; struct { - uint64_t i_wid:4; - uint64_t i_adjust:1; - uint64_t i_rsvd_1:3; - uint64_t i_field:2; - uint64_t i_rsvd:54; + u64 i_wid:4; + u64 i_adjust:1; + u64 i_rsvd_1:3; + u64 i_field:2; + u64 i_rsvd:54; } ii_ipca_fld_s; } ii_ipca_u_t; @@ -1709,12 +1709,12 @@ typedef union ii_ipca_u { ************************************************************************/ typedef union ii_iprte0a_u { - uint64_t ii_iprte0a_regval; + u64 ii_iprte0a_regval; struct { - uint64_t i_rsvd_1:54; - uint64_t i_widget:4; - uint64_t i_to_cnt:5; - uint64_t i_vld:1; + u64 i_rsvd_1:54; + u64 i_widget:4; + u64 i_to_cnt:5; + u64 i_vld:1; } ii_iprte0a_fld_s; } ii_iprte0a_u_t; @@ -1729,12 +1729,12 @@ typedef union ii_iprte0a_u { ************************************************************************/ typedef union ii_iprte1a_u { - uint64_t ii_iprte1a_regval; + u64 ii_iprte1a_regval; struct { - uint64_t i_rsvd_1:54; - uint64_t i_widget:4; - uint64_t i_to_cnt:5; - uint64_t i_vld:1; + u64 i_rsvd_1:54; + u64 i_widget:4; + u64 i_to_cnt:5; + u64 i_vld:1; } ii_iprte1a_fld_s; } ii_iprte1a_u_t; @@ -1749,12 +1749,12 @@ typedef union ii_iprte1a_u { ************************************************************************/ typedef union ii_iprte2a_u { - uint64_t ii_iprte2a_regval; + u64 ii_iprte2a_regval; struct { - uint64_t i_rsvd_1:54; - uint64_t i_widget:4; - uint64_t i_to_cnt:5; - uint64_t i_vld:1; + u64 i_rsvd_1:54; + u64 i_widget:4; + u64 i_to_cnt:5; + u64 i_vld:1; } ii_iprte2a_fld_s; } ii_iprte2a_u_t; @@ -1769,12 +1769,12 @@ typedef union ii_iprte2a_u { ************************************************************************/ typedef union ii_iprte3a_u { - uint64_t ii_iprte3a_regval; + u64 ii_iprte3a_regval; struct { - uint64_t i_rsvd_1:54; - uint64_t i_widget:4; - uint64_t i_to_cnt:5; - uint64_t i_vld:1; + u64 i_rsvd_1:54; + u64 i_widget:4; + u64 i_to_cnt:5; + u64 i_vld:1; } ii_iprte3a_fld_s; } ii_iprte3a_u_t; @@ -1789,12 +1789,12 @@ typedef union ii_iprte3a_u { ************************************************************************/ typedef union ii_iprte4a_u { - uint64_t ii_iprte4a_regval; + u64 ii_iprte4a_regval; struct { - uint64_t i_rsvd_1:54; - uint64_t i_widget:4; - uint64_t i_to_cnt:5; - uint64_t i_vld:1; + u64 i_rsvd_1:54; + u64 i_widget:4; + u64 i_to_cnt:5; + u64 i_vld:1; } ii_iprte4a_fld_s; } ii_iprte4a_u_t; @@ -1809,12 +1809,12 @@ typedef union ii_iprte4a_u { ************************************************************************/ typedef union ii_iprte5a_u { - uint64_t ii_iprte5a_regval; + u64 ii_iprte5a_regval; struct { - uint64_t i_rsvd_1:54; - uint64_t i_widget:4; - uint64_t i_to_cnt:5; - uint64_t i_vld:1; + u64 i_rsvd_1:54; + u64 i_widget:4; + u64 i_to_cnt:5; + u64 i_vld:1; } ii_iprte5a_fld_s; } ii_iprte5a_u_t; @@ -1829,12 +1829,12 @@ typedef union ii_iprte5a_u { ************************************************************************/ typedef union ii_iprte6a_u { - uint64_t ii_iprte6a_regval; + u64 ii_iprte6a_regval; struct { - uint64_t i_rsvd_1:54; - uint64_t i_widget:4; - uint64_t i_to_cnt:5; - uint64_t i_vld:1; + u64 i_rsvd_1:54; + u64 i_widget:4; + u64 i_to_cnt:5; + u64 i_vld:1; } ii_iprte6a_fld_s; } ii_iprte6a_u_t; @@ -1849,12 +1849,12 @@ typedef union ii_iprte6a_u { ************************************************************************/ typedef union ii_iprte7a_u { - uint64_t ii_iprte7a_regval; + u64 ii_iprte7a_regval; struct { - uint64_t i_rsvd_1:54; - uint64_t i_widget:4; - uint64_t i_to_cnt:5; - uint64_t i_vld:1; + u64 i_rsvd_1:54; + u64 i_widget:4; + u64 i_to_cnt:5; + u64 i_vld:1; } ii_iprtea7_fld_s; } ii_iprte7a_u_t; @@ -1869,12 +1869,12 @@ typedef union ii_iprte7a_u { ************************************************************************/ typedef union ii_iprte0b_u { - uint64_t ii_iprte0b_regval; + u64 ii_iprte0b_regval; struct { - uint64_t i_rsvd_1:3; - uint64_t i_address:47; - uint64_t i_init:3; - uint64_t i_source:11; + u64 i_rsvd_1:3; + u64 i_address:47; + u64 i_init:3; + u64 i_source:11; } ii_iprte0b_fld_s; } ii_iprte0b_u_t; @@ -1889,12 +1889,12 @@ typedef union ii_iprte0b_u { ************************************************************************/ typedef union ii_iprte1b_u { - uint64_t ii_iprte1b_regval; + u64 ii_iprte1b_regval; struct { - uint64_t i_rsvd_1:3; - uint64_t i_address:47; - uint64_t i_init:3; - uint64_t i_source:11; + u64 i_rsvd_1:3; + u64 i_address:47; + u64 i_init:3; + u64 i_source:11; } ii_iprte1b_fld_s; } ii_iprte1b_u_t; @@ -1909,12 +1909,12 @@ typedef union ii_iprte1b_u { ************************************************************************/ typedef union ii_iprte2b_u { - uint64_t ii_iprte2b_regval; + u64 ii_iprte2b_regval; struct { - uint64_t i_rsvd_1:3; - uint64_t i_address:47; - uint64_t i_init:3; - uint64_t i_source:11; + u64 i_rsvd_1:3; + u64 i_address:47; + u64 i_init:3; + u64 i_source:11; } ii_iprte2b_fld_s; } ii_iprte2b_u_t; @@ -1929,12 +1929,12 @@ typedef union ii_iprte2b_u { ************************************************************************/ typedef union ii_iprte3b_u { - uint64_t ii_iprte3b_regval; + u64 ii_iprte3b_regval; struct { - uint64_t i_rsvd_1:3; - uint64_t i_address:47; - uint64_t i_init:3; - uint64_t i_source:11; + u64 i_rsvd_1:3; + u64 i_address:47; + u64 i_init:3; + u64 i_source:11; } ii_iprte3b_fld_s; } ii_iprte3b_u_t; @@ -1949,12 +1949,12 @@ typedef union ii_iprte3b_u { ************************************************************************/ typedef union ii_iprte4b_u { - uint64_t ii_iprte4b_regval; + u64 ii_iprte4b_regval; struct { - uint64_t i_rsvd_1:3; - uint64_t i_address:47; - uint64_t i_init:3; - uint64_t i_source:11; + u64 i_rsvd_1:3; + u64 i_address:47; + u64 i_init:3; + u64 i_source:11; } ii_iprte4b_fld_s; } ii_iprte4b_u_t; @@ -1969,12 +1969,12 @@ typedef union ii_iprte4b_u { ************************************************************************/ typedef union ii_iprte5b_u { - uint64_t ii_iprte5b_regval; + u64 ii_iprte5b_regval; struct { - uint64_t i_rsvd_1:3; - uint64_t i_address:47; - uint64_t i_init:3; - uint64_t i_source:11; + u64 i_rsvd_1:3; + u64 i_address:47; + u64 i_init:3; + u64 i_source:11; } ii_iprte5b_fld_s; } ii_iprte5b_u_t; @@ -1989,12 +1989,12 @@ typedef union ii_iprte5b_u { ************************************************************************/ typedef union ii_iprte6b_u { - uint64_t ii_iprte6b_regval; + u64 ii_iprte6b_regval; struct { - uint64_t i_rsvd_1:3; - uint64_t i_address:47; - uint64_t i_init:3; - uint64_t i_source:11; + u64 i_rsvd_1:3; + u64 i_address:47; + u64 i_init:3; + u64 i_source:11; } ii_iprte6b_fld_s; } ii_iprte6b_u_t; @@ -2010,12 +2010,12 @@ typedef union ii_iprte6b_u { ************************************************************************/ typedef union ii_iprte7b_u { - uint64_t ii_iprte7b_regval; + u64 ii_iprte7b_regval; struct { - uint64_t i_rsvd_1:3; - uint64_t i_address:47; - uint64_t i_init:3; - uint64_t i_source:11; + u64 i_rsvd_1:3; + u64 i_address:47; + u64 i_init:3; + u64 i_source:11; } ii_iprte7b_fld_s; } ii_iprte7b_u_t; @@ -2038,13 +2038,13 @@ typedef union ii_iprte7b_u { ************************************************************************/ typedef union ii_ipdr_u { - uint64_t ii_ipdr_regval; + u64 ii_ipdr_regval; struct { - uint64_t i_te:3; - uint64_t i_rsvd_1:1; - uint64_t i_pnd:1; - uint64_t i_init_rpcnt:1; - uint64_t i_rsvd:58; + u64 i_te:3; + u64 i_rsvd_1:1; + u64 i_pnd:1; + u64 i_init_rpcnt:1; + u64 i_rsvd:58; } ii_ipdr_fld_s; } ii_ipdr_u_t; @@ -2066,11 +2066,11 @@ typedef union ii_ipdr_u { ************************************************************************/ typedef union ii_icdr_u { - uint64_t ii_icdr_regval; + u64 ii_icdr_regval; struct { - uint64_t i_crb_num:4; - uint64_t i_pnd:1; - uint64_t i_rsvd:59; + u64 i_crb_num:4; + u64 i_pnd:1; + u64 i_rsvd:59; } ii_icdr_fld_s; } ii_icdr_u_t; @@ -2092,13 +2092,13 @@ typedef union ii_icdr_u { ************************************************************************/ typedef union ii_ifdr_u { - uint64_t ii_ifdr_regval; + u64 ii_ifdr_regval; struct { - uint64_t i_ioq_max_rq:7; - uint64_t i_set_ioq_rq:1; - uint64_t i_ioq_max_rp:7; - uint64_t i_set_ioq_rp:1; - uint64_t i_rsvd:48; + u64 i_ioq_max_rq:7; + u64 i_set_ioq_rq:1; + u64 i_ioq_max_rp:7; + u64 i_set_ioq_rp:1; + u64 i_rsvd:48; } ii_ifdr_fld_s; } ii_ifdr_u_t; @@ -2114,12 +2114,12 @@ typedef union ii_ifdr_u { ************************************************************************/ typedef union ii_iiap_u { - uint64_t ii_iiap_regval; + u64 ii_iiap_regval; struct { - uint64_t i_rq_mls:6; - uint64_t i_rsvd_1:2; - uint64_t i_rp_mls:6; - uint64_t i_rsvd:50; + u64 i_rq_mls:6; + u64 i_rsvd_1:2; + u64 i_rp_mls:6; + u64 i_rsvd:50; } ii_iiap_fld_s; } ii_iiap_u_t; @@ -2133,22 +2133,22 @@ typedef union ii_iiap_u { ************************************************************************/ typedef union ii_icmr_u { - uint64_t ii_icmr_regval; - struct { - uint64_t i_sp_msg:1; - uint64_t i_rd_hdr:1; - uint64_t i_rsvd_4:2; - uint64_t i_c_cnt:4; - uint64_t i_rsvd_3:4; - uint64_t i_clr_rqpd:1; - uint64_t i_clr_rppd:1; - uint64_t i_rsvd_2:2; - uint64_t i_fc_cnt:4; - uint64_t i_crb_vld:15; - uint64_t i_crb_mark:15; - uint64_t i_rsvd_1:2; - uint64_t i_precise:1; - uint64_t i_rsvd:11; + u64 ii_icmr_regval; + struct { + u64 i_sp_msg:1; + u64 i_rd_hdr:1; + u64 i_rsvd_4:2; + u64 i_c_cnt:4; + u64 i_rsvd_3:4; + u64 i_clr_rqpd:1; + u64 i_clr_rppd:1; + u64 i_rsvd_2:2; + u64 i_fc_cnt:4; + u64 i_crb_vld:15; + u64 i_crb_mark:15; + u64 i_rsvd_1:2; + u64 i_precise:1; + u64 i_rsvd:11; } ii_icmr_fld_s; } ii_icmr_u_t; @@ -2161,13 +2161,13 @@ typedef union ii_icmr_u { ************************************************************************/ typedef union ii_iccr_u { - uint64_t ii_iccr_regval; + u64 ii_iccr_regval; struct { - uint64_t i_crb_num:4; - uint64_t i_rsvd_1:4; - uint64_t i_cmd:8; - uint64_t i_pending:1; - uint64_t i_rsvd:47; + u64 i_crb_num:4; + u64 i_rsvd_1:4; + u64 i_cmd:8; + u64 i_pending:1; + u64 i_rsvd:47; } ii_iccr_fld_s; } ii_iccr_u_t; @@ -2178,10 +2178,10 @@ typedef union ii_iccr_u { ************************************************************************/ typedef union ii_icto_u { - uint64_t ii_icto_regval; + u64 ii_icto_regval; struct { - uint64_t i_timeout:8; - uint64_t i_rsvd:56; + u64 i_timeout:8; + u64 i_rsvd:56; } ii_icto_fld_s; } ii_icto_u_t; @@ -2197,10 +2197,10 @@ typedef union ii_icto_u { ************************************************************************/ typedef union ii_ictp_u { - uint64_t ii_ictp_regval; + u64 ii_ictp_regval; struct { - uint64_t i_prescale:24; - uint64_t i_rsvd:40; + u64 i_prescale:24; + u64 i_rsvd:40; } ii_ictp_fld_s; } ii_ictp_u_t; @@ -2228,14 +2228,14 @@ typedef union ii_ictp_u { ************************************************************************/ typedef union ii_icrb0_a_u { - uint64_t ii_icrb0_a_regval; - struct { - uint64_t ia_iow:1; - uint64_t ia_vld:1; - uint64_t ia_addr:47; - uint64_t ia_tnum:5; - uint64_t ia_sidn:4; - uint64_t ia_rsvd:6; + u64 ii_icrb0_a_regval; + struct { + u64 ia_iow:1; + u64 ia_vld:1; + u64 ia_addr:47; + u64 ia_tnum:5; + u64 ia_sidn:4; + u64 ia_rsvd:6; } ii_icrb0_a_fld_s; } ii_icrb0_a_u_t; @@ -2249,30 +2249,30 @@ typedef union ii_icrb0_a_u { ************************************************************************/ typedef union ii_icrb0_b_u { - uint64_t ii_icrb0_b_regval; - struct { - uint64_t ib_xt_err:1; - uint64_t ib_mark:1; - uint64_t ib_ln_uce:1; - uint64_t ib_errcode:3; - uint64_t ib_error:1; - uint64_t ib_stall__bte_1:1; - uint64_t ib_stall__bte_0:1; - uint64_t ib_stall__intr:1; - uint64_t ib_stall_ib:1; - uint64_t ib_intvn:1; - uint64_t ib_wb:1; - uint64_t ib_hold:1; - uint64_t ib_ack:1; - uint64_t ib_resp:1; - uint64_t ib_ack_cnt:11; - uint64_t ib_rsvd:7; - uint64_t ib_exc:5; - uint64_t ib_init:3; - uint64_t ib_imsg:8; - uint64_t ib_imsgtype:2; - uint64_t ib_use_old:1; - uint64_t ib_rsvd_1:11; + u64 ii_icrb0_b_regval; + struct { + u64 ib_xt_err:1; + u64 ib_mark:1; + u64 ib_ln_uce:1; + u64 ib_errcode:3; + u64 ib_error:1; + u64 ib_stall__bte_1:1; + u64 ib_stall__bte_0:1; + u64 ib_stall__intr:1; + u64 ib_stall_ib:1; + u64 ib_intvn:1; + u64 ib_wb:1; + u64 ib_hold:1; + u64 ib_ack:1; + u64 ib_resp:1; + u64 ib_ack_cnt:11; + u64 ib_rsvd:7; + u64 ib_exc:5; + u64 ib_init:3; + u64 ib_imsg:8; + u64 ib_imsgtype:2; + u64 ib_use_old:1; + u64 ib_rsvd_1:11; } ii_icrb0_b_fld_s; } ii_icrb0_b_u_t; @@ -2286,17 +2286,17 @@ typedef union ii_icrb0_b_u { ************************************************************************/ typedef union ii_icrb0_c_u { - uint64_t ii_icrb0_c_regval; - struct { - uint64_t ic_source:15; - uint64_t ic_size:2; - uint64_t ic_ct:1; - uint64_t ic_bte_num:1; - uint64_t ic_gbr:1; - uint64_t ic_resprqd:1; - uint64_t ic_bo:1; - uint64_t ic_suppl:15; - uint64_t ic_rsvd:27; + u64 ii_icrb0_c_regval; + struct { + u64 ic_source:15; + u64 ic_size:2; + u64 ic_ct:1; + u64 ic_bte_num:1; + u64 ic_gbr:1; + u64 ic_resprqd:1; + u64 ic_bo:1; + u64 ic_suppl:15; + u64 ic_rsvd:27; } ii_icrb0_c_fld_s; } ii_icrb0_c_u_t; @@ -2310,14 +2310,14 @@ typedef union ii_icrb0_c_u { ************************************************************************/ typedef union ii_icrb0_d_u { - uint64_t ii_icrb0_d_regval; - struct { - uint64_t id_pa_be:43; - uint64_t id_bte_op:1; - uint64_t id_pr_psc:4; - uint64_t id_pr_cnt:4; - uint64_t id_sleep:1; - uint64_t id_rsvd:11; + u64 ii_icrb0_d_regval; + struct { + u64 id_pa_be:43; + u64 id_bte_op:1; + u64 id_pr_psc:4; + u64 id_pr_cnt:4; + u64 id_sleep:1; + u64 id_rsvd:11; } ii_icrb0_d_fld_s; } ii_icrb0_d_u_t; @@ -2331,14 +2331,14 @@ typedef union ii_icrb0_d_u { ************************************************************************/ typedef union ii_icrb0_e_u { - uint64_t ii_icrb0_e_regval; - struct { - uint64_t ie_timeout:8; - uint64_t ie_context:15; - uint64_t ie_rsvd:1; - uint64_t ie_tvld:1; - uint64_t ie_cvld:1; - uint64_t ie_rsvd_0:38; + u64 ii_icrb0_e_regval; + struct { + u64 ie_timeout:8; + u64 ie_context:15; + u64 ie_rsvd:1; + u64 ie_tvld:1; + u64 ie_cvld:1; + u64 ie_rsvd_0:38; } ii_icrb0_e_fld_s; } ii_icrb0_e_u_t; @@ -2351,12 +2351,12 @@ typedef union ii_icrb0_e_u { ************************************************************************/ typedef union ii_icsml_u { - uint64_t ii_icsml_regval; + u64 ii_icsml_regval; struct { - uint64_t i_tt_addr:47; - uint64_t i_newsuppl_ex:14; - uint64_t i_reserved:2; - uint64_t i_overflow:1; + u64 i_tt_addr:47; + u64 i_newsuppl_ex:14; + u64 i_reserved:2; + u64 i_overflow:1; } ii_icsml_fld_s; } ii_icsml_u_t; @@ -2369,10 +2369,10 @@ typedef union ii_icsml_u { ************************************************************************/ typedef union ii_icsmm_u { - uint64_t ii_icsmm_regval; + u64 ii_icsmm_regval; struct { - uint64_t i_tt_ack_cnt:11; - uint64_t i_reserved:53; + u64 i_tt_ack_cnt:11; + u64 i_reserved:53; } ii_icsmm_fld_s; } ii_icsmm_u_t; @@ -2385,48 +2385,48 @@ typedef union ii_icsmm_u { ************************************************************************/ typedef union ii_icsmh_u { - uint64_t ii_icsmh_regval; - struct { - uint64_t i_tt_vld:1; - uint64_t i_xerr:1; - uint64_t i_ft_cwact_o:1; - uint64_t i_ft_wact_o:1; - uint64_t i_ft_active_o:1; - uint64_t i_sync:1; - uint64_t i_mnusg:1; - uint64_t i_mnusz:1; - uint64_t i_plusz:1; - uint64_t i_plusg:1; - uint64_t i_tt_exc:5; - uint64_t i_tt_wb:1; - uint64_t i_tt_hold:1; - uint64_t i_tt_ack:1; - uint64_t i_tt_resp:1; - uint64_t i_tt_intvn:1; - uint64_t i_g_stall_bte1:1; - uint64_t i_g_stall_bte0:1; - uint64_t i_g_stall_il:1; - uint64_t i_g_stall_ib:1; - uint64_t i_tt_imsg:8; - uint64_t i_tt_imsgtype:2; - uint64_t i_tt_use_old:1; - uint64_t i_tt_respreqd:1; - uint64_t i_tt_bte_num:1; - uint64_t i_cbn:1; - uint64_t i_match:1; - uint64_t i_rpcnt_lt_34:1; - uint64_t i_rpcnt_ge_34:1; - uint64_t i_rpcnt_lt_18:1; - uint64_t i_rpcnt_ge_18:1; - uint64_t i_rpcnt_lt_2:1; - uint64_t i_rpcnt_ge_2:1; - uint64_t i_rqcnt_lt_18:1; - uint64_t i_rqcnt_ge_18:1; - uint64_t i_rqcnt_lt_2:1; - uint64_t i_rqcnt_ge_2:1; - uint64_t i_tt_device:7; - uint64_t i_tt_init:3; - uint64_t i_reserved:5; + u64 ii_icsmh_regval; + struct { + u64 i_tt_vld:1; + u64 i_xerr:1; + u64 i_ft_cwact_o:1; + u64 i_ft_wact_o:1; + u64 i_ft_active_o:1; + u64 i_sync:1; + u64 i_mnusg:1; + u64 i_mnusz:1; + u64 i_plusz:1; + u64 i_plusg:1; + u64 i_tt_exc:5; + u64 i_tt_wb:1; + u64 i_tt_hold:1; + u64 i_tt_ack:1; + u64 i_tt_resp:1; + u64 i_tt_intvn:1; + u64 i_g_stall_bte1:1; + u64 i_g_stall_bte0:1; + u64 i_g_stall_il:1; + u64 i_g_stall_ib:1; + u64 i_tt_imsg:8; + u64 i_tt_imsgtype:2; + u64 i_tt_use_old:1; + u64 i_tt_respreqd:1; + u64 i_tt_bte_num:1; + u64 i_cbn:1; + u64 i_match:1; + u64 i_rpcnt_lt_34:1; + u64 i_rpcnt_ge_34:1; + u64 i_rpcnt_lt_18:1; + u64 i_rpcnt_ge_18:1; + u64 i_rpcnt_lt_2:1; + u64 i_rpcnt_ge_2:1; + u64 i_rqcnt_lt_18:1; + u64 i_rqcnt_ge_18:1; + u64 i_rqcnt_lt_2:1; + u64 i_rqcnt_ge_2:1; + u64 i_tt_device:7; + u64 i_tt_init:3; + u64 i_reserved:5; } ii_icsmh_fld_s; } ii_icsmh_u_t; @@ -2439,14 +2439,14 @@ typedef union ii_icsmh_u { ************************************************************************/ typedef union ii_idbss_u { - uint64_t ii_idbss_regval; - struct { - uint64_t i_iioclk_core_submenu:3; - uint64_t i_rsvd:5; - uint64_t i_fsbclk_wrapper_submenu:3; - uint64_t i_rsvd_1:5; - uint64_t i_iioclk_menu:5; - uint64_t i_rsvd_2:43; + u64 ii_idbss_regval; + struct { + u64 i_iioclk_core_submenu:3; + u64 i_rsvd:5; + u64 i_fsbclk_wrapper_submenu:3; + u64 i_rsvd_1:5; + u64 i_iioclk_menu:5; + u64 i_rsvd_2:43; } ii_idbss_fld_s; } ii_idbss_u_t; @@ -2466,13 +2466,13 @@ typedef union ii_idbss_u { ************************************************************************/ typedef union ii_ibls0_u { - uint64_t ii_ibls0_regval; + u64 ii_ibls0_regval; struct { - uint64_t i_length:16; - uint64_t i_error:1; - uint64_t i_rsvd_1:3; - uint64_t i_busy:1; - uint64_t i_rsvd:43; + u64 i_length:16; + u64 i_error:1; + u64 i_rsvd_1:3; + u64 i_busy:1; + u64 i_rsvd:43; } ii_ibls0_fld_s; } ii_ibls0_u_t; @@ -2487,11 +2487,11 @@ typedef union ii_ibls0_u { ************************************************************************/ typedef union ii_ibsa0_u { - uint64_t ii_ibsa0_regval; + u64 ii_ibsa0_regval; struct { - uint64_t i_rsvd_1:7; - uint64_t i_addr:42; - uint64_t i_rsvd:15; + u64 i_rsvd_1:7; + u64 i_addr:42; + u64 i_rsvd:15; } ii_ibsa0_fld_s; } ii_ibsa0_u_t; @@ -2506,11 +2506,11 @@ typedef union ii_ibsa0_u { ************************************************************************/ typedef union ii_ibda0_u { - uint64_t ii_ibda0_regval; + u64 ii_ibda0_regval; struct { - uint64_t i_rsvd_1:7; - uint64_t i_addr:42; - uint64_t i_rsvd:15; + u64 i_rsvd_1:7; + u64 i_addr:42; + u64 i_rsvd:15; } ii_ibda0_fld_s; } ii_ibda0_u_t; @@ -2527,14 +2527,14 @@ typedef union ii_ibda0_u { ************************************************************************/ typedef union ii_ibct0_u { - uint64_t ii_ibct0_regval; - struct { - uint64_t i_zerofill:1; - uint64_t i_rsvd_2:3; - uint64_t i_notify:1; - uint64_t i_rsvd_1:3; - uint64_t i_poison:1; - uint64_t i_rsvd:55; + u64 ii_ibct0_regval; + struct { + u64 i_zerofill:1; + u64 i_rsvd_2:3; + u64 i_notify:1; + u64 i_rsvd_1:3; + u64 i_poison:1; + u64 i_rsvd:55; } ii_ibct0_fld_s; } ii_ibct0_u_t; @@ -2546,11 +2546,11 @@ typedef union ii_ibct0_u { ************************************************************************/ typedef union ii_ibna0_u { - uint64_t ii_ibna0_regval; + u64 ii_ibna0_regval; struct { - uint64_t i_rsvd_1:7; - uint64_t i_addr:42; - uint64_t i_rsvd:15; + u64 i_rsvd_1:7; + u64 i_addr:42; + u64 i_rsvd:15; } ii_ibna0_fld_s; } ii_ibna0_u_t; @@ -2563,13 +2563,13 @@ typedef union ii_ibna0_u { ************************************************************************/ typedef union ii_ibia0_u { - uint64_t ii_ibia0_regval; + u64 ii_ibia0_regval; struct { - uint64_t i_rsvd_2:1; - uint64_t i_node_id:11; - uint64_t i_rsvd_1:4; - uint64_t i_level:7; - uint64_t i_rsvd:41; + u64 i_rsvd_2:1; + u64 i_node_id:11; + u64 i_rsvd_1:4; + u64 i_level:7; + u64 i_rsvd:41; } ii_ibia0_fld_s; } ii_ibia0_u_t; @@ -2589,13 +2589,13 @@ typedef union ii_ibia0_u { ************************************************************************/ typedef union ii_ibls1_u { - uint64_t ii_ibls1_regval; + u64 ii_ibls1_regval; struct { - uint64_t i_length:16; - uint64_t i_error:1; - uint64_t i_rsvd_1:3; - uint64_t i_busy:1; - uint64_t i_rsvd:43; + u64 i_length:16; + u64 i_error:1; + u64 i_rsvd_1:3; + u64 i_busy:1; + u64 i_rsvd:43; } ii_ibls1_fld_s; } ii_ibls1_u_t; @@ -2610,11 +2610,11 @@ typedef union ii_ibls1_u { ************************************************************************/ typedef union ii_ibsa1_u { - uint64_t ii_ibsa1_regval; + u64 ii_ibsa1_regval; struct { - uint64_t i_rsvd_1:7; - uint64_t i_addr:33; - uint64_t i_rsvd:24; + u64 i_rsvd_1:7; + u64 i_addr:33; + u64 i_rsvd:24; } ii_ibsa1_fld_s; } ii_ibsa1_u_t; @@ -2629,11 +2629,11 @@ typedef union ii_ibsa1_u { ************************************************************************/ typedef union ii_ibda1_u { - uint64_t ii_ibda1_regval; + u64 ii_ibda1_regval; struct { - uint64_t i_rsvd_1:7; - uint64_t i_addr:33; - uint64_t i_rsvd:24; + u64 i_rsvd_1:7; + u64 i_addr:33; + u64 i_rsvd:24; } ii_ibda1_fld_s; } ii_ibda1_u_t; @@ -2650,14 +2650,14 @@ typedef union ii_ibda1_u { ************************************************************************/ typedef union ii_ibct1_u { - uint64_t ii_ibct1_regval; - struct { - uint64_t i_zerofill:1; - uint64_t i_rsvd_2:3; - uint64_t i_notify:1; - uint64_t i_rsvd_1:3; - uint64_t i_poison:1; - uint64_t i_rsvd:55; + u64 ii_ibct1_regval; + struct { + u64 i_zerofill:1; + u64 i_rsvd_2:3; + u64 i_notify:1; + u64 i_rsvd_1:3; + u64 i_poison:1; + u64 i_rsvd:55; } ii_ibct1_fld_s; } ii_ibct1_u_t; @@ -2669,11 +2669,11 @@ typedef union ii_ibct1_u { ************************************************************************/ typedef union ii_ibna1_u { - uint64_t ii_ibna1_regval; + u64 ii_ibna1_regval; struct { - uint64_t i_rsvd_1:7; - uint64_t i_addr:33; - uint64_t i_rsvd:24; + u64 i_rsvd_1:7; + u64 i_addr:33; + u64 i_rsvd:24; } ii_ibna1_fld_s; } ii_ibna1_u_t; @@ -2686,13 +2686,13 @@ typedef union ii_ibna1_u { ************************************************************************/ typedef union ii_ibia1_u { - uint64_t ii_ibia1_regval; + u64 ii_ibia1_regval; struct { - uint64_t i_pi_id:1; - uint64_t i_node_id:8; - uint64_t i_rsvd_1:7; - uint64_t i_level:7; - uint64_t i_rsvd:41; + u64 i_pi_id:1; + u64 i_node_id:8; + u64 i_rsvd_1:7; + u64 i_level:7; + u64 i_rsvd:41; } ii_ibia1_fld_s; } ii_ibia1_u_t; @@ -2712,12 +2712,12 @@ typedef union ii_ibia1_u { ************************************************************************/ typedef union ii_ipcr_u { - uint64_t ii_ipcr_regval; + u64 ii_ipcr_regval; struct { - uint64_t i_ippr0_c:4; - uint64_t i_ippr1_c:4; - uint64_t i_icct:8; - uint64_t i_rsvd:48; + u64 i_ippr0_c:4; + u64 i_ippr1_c:4; + u64 i_icct:8; + u64 i_rsvd:48; } ii_ipcr_fld_s; } ii_ipcr_u_t; @@ -2728,10 +2728,10 @@ typedef union ii_ipcr_u { ************************************************************************/ typedef union ii_ippr_u { - uint64_t ii_ippr_regval; + u64 ii_ippr_regval; struct { - uint64_t i_ippr0:32; - uint64_t i_ippr1:32; + u64 i_ippr0:32; + u64 i_ippr1:32; } ii_ippr_fld_s; } ii_ippr_u_t; @@ -3267,15 +3267,15 @@ typedef ii_icrb0_e_u_t icrbe_t; #define IO_PERF_SETS 32 /* Bit for the widget in inbound access register */ -#define IIO_IIWA_WIDGET(_w) ((uint64_t)(1ULL << _w)) +#define IIO_IIWA_WIDGET(_w) ((u64)(1ULL << _w)) /* Bit for the widget in outbound access register */ -#define IIO_IOWA_WIDGET(_w) ((uint64_t)(1ULL << _w)) +#define IIO_IOWA_WIDGET(_w) ((u64)(1ULL << _w)) /* NOTE: The following define assumes that we are going to get * widget numbers from 8 thru F and the device numbers within * widget from 0 thru 7. */ -#define IIO_IIDEM_WIDGETDEV_MASK(w, d) ((uint64_t)(1ULL << (8 * ((w) - 8) + (d)))) +#define IIO_IIDEM_WIDGETDEV_MASK(w, d) ((u64)(1ULL << (8 * ((w) - 8) + (d)))) /* IO Interrupt Destination Register */ #define IIO_IIDSR_SENT_SHIFT 28 @@ -3302,9 +3302,9 @@ typedef ii_icrb0_e_u_t icrbe_t; */ typedef union hubii_wcr_u { - uint64_t wcr_reg_value; + u64 wcr_reg_value; struct { - uint64_t wcr_widget_id:4, /* LLP crossbar credit */ + u64 wcr_widget_id:4, /* LLP crossbar credit */ wcr_tag_mode:1, /* Tag mode */ wcr_rsvd1:8, /* Reserved */ wcr_xbar_crd:3, /* LLP crossbar credit */ @@ -3324,9 +3324,9 @@ performance registers */ performed */ typedef union io_perf_sel { - uint64_t perf_sel_reg; + u64 perf_sel_reg; struct { - uint64_t perf_ippr0:4, perf_ippr1:4, perf_icct:8, perf_rsvd:48; + u64 perf_ippr0:4, perf_ippr1:4, perf_icct:8, perf_rsvd:48; } perf_sel_bits; } io_perf_sel_t; @@ -3334,24 +3334,24 @@ typedef union io_perf_sel { hardware problems there is only one counter, not two. */ typedef union io_perf_cnt { - uint64_t perf_cnt; + u64 perf_cnt; struct { - uint64_t perf_cnt:20, perf_rsvd2:12, perf_rsvd1:32; + u64 perf_cnt:20, perf_rsvd2:12, perf_rsvd1:32; } perf_cnt_bits; } io_perf_cnt_t; typedef union iprte_a { - uint64_t entry; - struct { - uint64_t i_rsvd_1:3; - uint64_t i_addr:38; - uint64_t i_init:3; - uint64_t i_source:8; - uint64_t i_rsvd:2; - uint64_t i_widget:4; - uint64_t i_to_cnt:5; - uint64_t i_vld:1; + u64 entry; + struct { + u64 i_rsvd_1:3; + u64 i_addr:38; + u64 i_init:3; + u64 i_source:8; + u64 i_rsvd:2; + u64 i_widget:4; + u64 i_to_cnt:5; + u64 i_vld:1; } iprte_fields; } iprte_a_t; diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h index 8b9e10e7cdb..e77f0c9b7d3 100644 --- a/include/asm-ia64/sn/sn_sal.h +++ b/include/asm-ia64/sn/sn_sal.h @@ -273,7 +273,7 @@ ia64_sn_console_putc(char ch) ret_stuff.v0 = 0; ret_stuff.v1 = 0; ret_stuff.v2 = 0; - SAL_CALL_NOLOCK(ret_stuff, SN_SAL_CONSOLE_PUTC, (uint64_t)ch, 0, 0, 0, 0, 0, 0); + SAL_CALL_NOLOCK(ret_stuff, SN_SAL_CONSOLE_PUTC, (u64)ch, 0, 0, 0, 0, 0, 0); return ret_stuff.status; } @@ -290,7 +290,7 @@ ia64_sn_console_putb(const char *buf, int len) ret_stuff.v0 = 0; ret_stuff.v1 = 0; ret_stuff.v2 = 0; - SAL_CALL_NOLOCK(ret_stuff, SN_SAL_CONSOLE_PUTB, (uint64_t)buf, (uint64_t)len, 0, 0, 0, 0, 0); + SAL_CALL_NOLOCK(ret_stuff, SN_SAL_CONSOLE_PUTB, (u64)buf, (u64)len, 0, 0, 0, 0, 0); if ( ret_stuff.status == 0 ) { return ret_stuff.v0; @@ -310,7 +310,7 @@ ia64_sn_plat_specific_err_print(int (*hook)(const char*, ...), char *rec) ret_stuff.v0 = 0; ret_stuff.v1 = 0; ret_stuff.v2 = 0; - SAL_CALL_REENTRANT(ret_stuff, SN_SAL_PRINT_ERROR, (uint64_t)hook, (uint64_t)rec, 0, 0, 0, 0, 0); + SAL_CALL_REENTRANT(ret_stuff, SN_SAL_PRINT_ERROR, (u64)hook, (u64)rec, 0, 0, 0, 0, 0); return ret_stuff.status; } @@ -398,7 +398,7 @@ ia64_sn_console_intr_status(void) * Enable an interrupt on the SAL console device. */ static inline void -ia64_sn_console_intr_enable(uint64_t intr) +ia64_sn_console_intr_enable(u64 intr) { struct ia64_sal_retval ret_stuff; @@ -415,7 +415,7 @@ ia64_sn_console_intr_enable(uint64_t intr) * Disable an interrupt on the SAL console device. */ static inline void -ia64_sn_console_intr_disable(uint64_t intr) +ia64_sn_console_intr_disable(u64 intr) { struct ia64_sal_retval ret_stuff; @@ -441,7 +441,7 @@ ia64_sn_console_xmit_chars(char *buf, int len) ret_stuff.v1 = 0; ret_stuff.v2 = 0; SAL_CALL_NOLOCK(ret_stuff, SN_SAL_CONSOLE_XMIT_CHARS, - (uint64_t)buf, (uint64_t)len, + (u64)buf, (u64)len, 0, 0, 0, 0, 0); if (ret_stuff.status == 0) { diff --git a/include/asm-ia64/sn/tioca.h b/include/asm-ia64/sn/tioca.h index bc1aacfb948..666222d7f0f 100644 --- a/include/asm-ia64/sn/tioca.h +++ b/include/asm-ia64/sn/tioca.h @@ -19,47 +19,47 @@ */ struct tioca { - uint64_t ca_id; /* 0x000000 */ - uint64_t ca_control1; /* 0x000008 */ - uint64_t ca_control2; /* 0x000010 */ - uint64_t ca_status1; /* 0x000018 */ - uint64_t ca_status2; /* 0x000020 */ - uint64_t ca_gart_aperature; /* 0x000028 */ - uint64_t ca_gfx_detach; /* 0x000030 */ - uint64_t ca_inta_dest_addr; /* 0x000038 */ - uint64_t ca_intb_dest_addr; /* 0x000040 */ - uint64_t ca_err_int_dest_addr; /* 0x000048 */ - uint64_t ca_int_status; /* 0x000050 */ - uint64_t ca_int_status_alias; /* 0x000058 */ - uint64_t ca_mult_error; /* 0x000060 */ - uint64_t ca_mult_error_alias; /* 0x000068 */ - uint64_t ca_first_error; /* 0x000070 */ - uint64_t ca_int_mask; /* 0x000078 */ - uint64_t ca_crm_pkterr_type; /* 0x000080 */ - uint64_t ca_crm_pkterr_type_alias; /* 0x000088 */ - uint64_t ca_crm_ct_error_detail_1; /* 0x000090 */ - uint64_t ca_crm_ct_error_detail_2; /* 0x000098 */ - uint64_t ca_crm_tnumto; /* 0x0000A0 */ - uint64_t ca_gart_err; /* 0x0000A8 */ - uint64_t ca_pcierr_type; /* 0x0000B0 */ - uint64_t ca_pcierr_addr; /* 0x0000B8 */ - - uint64_t ca_pad_0000C0[3]; /* 0x0000{C0..D0} */ - - uint64_t ca_pci_rd_buf_flush; /* 0x0000D8 */ - uint64_t ca_pci_dma_addr_extn; /* 0x0000E0 */ - uint64_t ca_agp_dma_addr_extn; /* 0x0000E8 */ - uint64_t ca_force_inta; /* 0x0000F0 */ - uint64_t ca_force_intb; /* 0x0000F8 */ - uint64_t ca_debug_vector_sel; /* 0x000100 */ - uint64_t ca_debug_mux_core_sel; /* 0x000108 */ - uint64_t ca_debug_mux_pci_sel; /* 0x000110 */ - uint64_t ca_debug_domain_sel; /* 0x000118 */ - - uint64_t ca_pad_000120[28]; /* 0x0001{20..F8} */ - - uint64_t ca_gart_ptr_table; /* 0x200 */ - uint64_t ca_gart_tlb_addr[8]; /* 0x2{08..40} */ + u64 ca_id; /* 0x000000 */ + u64 ca_control1; /* 0x000008 */ + u64 ca_control2; /* 0x000010 */ + u64 ca_status1; /* 0x000018 */ + u64 ca_status2; /* 0x000020 */ + u64 ca_gart_aperature; /* 0x000028 */ + u64 ca_gfx_detach; /* 0x000030 */ + u64 ca_inta_dest_addr; /* 0x000038 */ + u64 ca_intb_dest_addr; /* 0x000040 */ + u64 ca_err_int_dest_addr; /* 0x000048 */ + u64 ca_int_status; /* 0x000050 */ + u64 ca_int_status_alias; /* 0x000058 */ + u64 ca_mult_error; /* 0x000060 */ + u64 ca_mult_error_alias; /* 0x000068 */ + u64 ca_first_error; /* 0x000070 */ + u64 ca_int_mask; /* 0x000078 */ + u64 ca_crm_pkterr_type; /* 0x000080 */ + u64 ca_crm_pkterr_type_alias; /* 0x000088 */ + u64 ca_crm_ct_error_detail_1; /* 0x000090 */ + u64 ca_crm_ct_error_detail_2; /* 0x000098 */ + u64 ca_crm_tnumto; /* 0x0000A0 */ + u64 ca_gart_err; /* 0x0000A8 */ + u64 ca_pcierr_type; /* 0x0000B0 */ + u64 ca_pcierr_addr; /* 0x0000B8 */ + + u64 ca_pad_0000C0[3]; /* 0x0000{C0..D0} */ + + u64 ca_pci_rd_buf_flush; /* 0x0000D8 */ + u64 ca_pci_dma_addr_extn; /* 0x0000E0 */ + u64 ca_agp_dma_addr_extn; /* 0x0000E8 */ + u64 ca_force_inta; /* 0x0000F0 */ + u64 ca_force_intb; /* 0x0000F8 */ + u64 ca_debug_vector_sel; /* 0x000100 */ + u64 ca_debug_mux_core_sel; /* 0x000108 */ + u64 ca_debug_mux_pci_sel; /* 0x000110 */ + u64 ca_debug_domain_sel; /* 0x000118 */ + + u64 ca_pad_000120[28]; /* 0x0001{20..F8} */ + + u64 ca_gart_ptr_table; /* 0x200 */ + u64 ca_gart_tlb_addr[8]; /* 0x2{08..40} */ }; /* diff --git a/include/asm-ia64/sn/tioca_provider.h b/include/asm-ia64/sn/tioca_provider.h index b532ef6148e..ab7fe246346 100644 --- a/include/asm-ia64/sn/tioca_provider.h +++ b/include/asm-ia64/sn/tioca_provider.h @@ -56,31 +56,31 @@ struct tioca_kernel { /* * General GART stuff */ - uint64_t ca_ap_size; /* size of aperature in bytes */ - uint32_t ca_gart_entries; /* # uint64_t entries in gart */ - uint32_t ca_ap_pagesize; /* aperature page size in bytes */ - uint64_t ca_ap_bus_base; /* bus address of CA aperature */ - uint64_t ca_gart_size; /* gart size in bytes */ - uint64_t *ca_gart; /* gart table vaddr */ - uint64_t ca_gart_coretalk_addr; /* gart coretalk addr */ - uint8_t ca_gart_iscoherent; /* used in tioca_tlbflush */ + u64 ca_ap_size; /* size of aperature in bytes */ + u32 ca_gart_entries; /* # u64 entries in gart */ + u32 ca_ap_pagesize; /* aperature page size in bytes */ + u64 ca_ap_bus_base; /* bus address of CA aperature */ + u64 ca_gart_size; /* gart size in bytes */ + u64 *ca_gart; /* gart table vaddr */ + u64 ca_gart_coretalk_addr; /* gart coretalk addr */ + u8 ca_gart_iscoherent; /* used in tioca_tlbflush */ /* PCI GART convenience values */ - uint64_t ca_pciap_base; /* pci aperature bus base address */ - uint64_t ca_pciap_size; /* pci aperature size (bytes) */ - uint64_t ca_pcigart_base; /* gfx GART bus base address */ - uint64_t *ca_pcigart; /* gfx GART vm address */ - uint32_t ca_pcigart_entries; - uint32_t ca_pcigart_start; /* PCI start index in ca_gart */ + u64 ca_pciap_base; /* pci aperature bus base address */ + u64 ca_pciap_size; /* pci aperature size (bytes) */ + u64 ca_pcigart_base; /* gfx GART bus base address */ + u64 *ca_pcigart; /* gfx GART vm address */ + u32 ca_pcigart_entries; + u32 ca_pcigart_start; /* PCI start index in ca_gart */ void *ca_pcigart_pagemap; /* AGP GART convenience values */ - uint64_t ca_gfxap_base; /* gfx aperature bus base address */ - uint64_t ca_gfxap_size; /* gfx aperature size (bytes) */ - uint64_t ca_gfxgart_base; /* gfx GART bus base address */ - uint64_t *ca_gfxgart; /* gfx GART vm address */ - uint32_t ca_gfxgart_entries; - uint32_t ca_gfxgart_start; /* agpgart start index in ca_gart */ + u64 ca_gfxap_base; /* gfx aperature bus base address */ + u64 ca_gfxap_size; /* gfx aperature size (bytes) */ + u64 ca_gfxgart_base; /* gfx GART bus base address */ + u64 *ca_gfxgart; /* gfx GART vm address */ + u32 ca_gfxgart_entries; + u32 ca_gfxgart_start; /* agpgart start index in ca_gart */ }; /* @@ -93,11 +93,11 @@ struct tioca_kernel { struct tioca_common { struct pcibus_bussoft ca_common; /* common pciio header */ - uint32_t ca_rev; - uint32_t ca_closest_nasid; + u32 ca_rev; + u32 ca_closest_nasid; - uint64_t ca_prom_private; - uint64_t ca_kernel_private; + u64 ca_prom_private; + u64 ca_kernel_private; }; /** @@ -139,9 +139,9 @@ tioca_paddr_to_gart(unsigned long paddr) */ static inline unsigned long -tioca_physpage_to_gart(uint64_t page_addr) +tioca_physpage_to_gart(u64 page_addr) { - uint64_t coretalk_addr; + u64 coretalk_addr; coretalk_addr = PHYS_TO_TIODMA(page_addr); if (!coretalk_addr) { @@ -161,7 +161,7 @@ tioca_physpage_to_gart(uint64_t page_addr) static inline void tioca_tlbflush(struct tioca_kernel *tioca_kernel) { - volatile uint64_t tmp; + volatile u64 tmp; volatile struct tioca *ca_base; struct tioca_common *tioca_common; @@ -200,7 +200,7 @@ tioca_tlbflush(struct tioca_kernel *tioca_kernel) tmp = __sn_readq_relaxed(&ca_base->ca_control2); } -extern uint32_t tioca_gart_found; +extern u32 tioca_gart_found; extern struct list_head tioca_list; extern int tioca_init_provider(void); extern void tioca_fastwrite_enable(struct tioca_kernel *tioca_kern); diff --git a/include/asm-ia64/sn/tioce.h b/include/asm-ia64/sn/tioce.h index ecaddf96008..d4c990712ea 100644 --- a/include/asm-ia64/sn/tioce.h +++ b/include/asm-ia64/sn/tioce.h @@ -35,72 +35,72 @@ typedef volatile struct tioce { /* * ADMIN : Administration Registers */ - uint64_t ce_adm_id; /* 0x000000 */ - uint64_t ce_pad_000008; /* 0x000008 */ - uint64_t ce_adm_dyn_credit_status; /* 0x000010 */ - uint64_t ce_adm_last_credit_status; /* 0x000018 */ - uint64_t ce_adm_credit_limit; /* 0x000020 */ - uint64_t ce_adm_force_credit; /* 0x000028 */ - uint64_t ce_adm_control; /* 0x000030 */ - uint64_t ce_adm_mmr_chn_timeout; /* 0x000038 */ - uint64_t ce_adm_ssp_ure_timeout; /* 0x000040 */ - uint64_t ce_adm_ssp_dre_timeout; /* 0x000048 */ - uint64_t ce_adm_ssp_debug_sel; /* 0x000050 */ - uint64_t ce_adm_int_status; /* 0x000058 */ - uint64_t ce_adm_int_status_alias; /* 0x000060 */ - uint64_t ce_adm_int_mask; /* 0x000068 */ - uint64_t ce_adm_int_pending; /* 0x000070 */ - uint64_t ce_adm_force_int; /* 0x000078 */ - uint64_t ce_adm_ure_ups_buf_barrier_flush; /* 0x000080 */ - uint64_t ce_adm_int_dest[15]; /* 0x000088 -- 0x0000F8 */ - uint64_t ce_adm_error_summary; /* 0x000100 */ - uint64_t ce_adm_error_summary_alias; /* 0x000108 */ - uint64_t ce_adm_error_mask; /* 0x000110 */ - uint64_t ce_adm_first_error; /* 0x000118 */ - uint64_t ce_adm_error_overflow; /* 0x000120 */ - uint64_t ce_adm_error_overflow_alias; /* 0x000128 */ - uint64_t ce_pad_000130[2]; /* 0x000130 -- 0x000138 */ - uint64_t ce_adm_tnum_error; /* 0x000140 */ - uint64_t ce_adm_mmr_err_detail; /* 0x000148 */ - uint64_t ce_adm_msg_sram_perr_detail; /* 0x000150 */ - uint64_t ce_adm_bap_sram_perr_detail; /* 0x000158 */ - uint64_t ce_adm_ce_sram_perr_detail; /* 0x000160 */ - uint64_t ce_adm_ce_credit_oflow_detail; /* 0x000168 */ - uint64_t ce_adm_tx_link_idle_max_timer; /* 0x000170 */ - uint64_t ce_adm_pcie_debug_sel; /* 0x000178 */ - uint64_t ce_pad_000180[16]; /* 0x000180 -- 0x0001F8 */ - - uint64_t ce_adm_pcie_debug_sel_top; /* 0x000200 */ - uint64_t ce_adm_pcie_debug_lat_sel_lo_top; /* 0x000208 */ - uint64_t ce_adm_pcie_debug_lat_sel_hi_top; /* 0x000210 */ - uint64_t ce_adm_pcie_debug_trig_sel_top; /* 0x000218 */ - uint64_t ce_adm_pcie_debug_trig_lat_sel_lo_top; /* 0x000220 */ - uint64_t ce_adm_pcie_debug_trig_lat_sel_hi_top; /* 0x000228 */ - uint64_t ce_adm_pcie_trig_compare_top; /* 0x000230 */ - uint64_t ce_adm_pcie_trig_compare_en_top; /* 0x000238 */ - uint64_t ce_adm_ssp_debug_sel_top; /* 0x000240 */ - uint64_t ce_adm_ssp_debug_lat_sel_lo_top; /* 0x000248 */ - uint64_t ce_adm_ssp_debug_lat_sel_hi_top; /* 0x000250 */ - uint64_t ce_adm_ssp_debug_trig_sel_top; /* 0x000258 */ - uint64_t ce_adm_ssp_debug_trig_lat_sel_lo_top; /* 0x000260 */ - uint64_t ce_adm_ssp_debug_trig_lat_sel_hi_top; /* 0x000268 */ - uint64_t ce_adm_ssp_trig_compare_top; /* 0x000270 */ - uint64_t ce_adm_ssp_trig_compare_en_top; /* 0x000278 */ - uint64_t ce_pad_000280[48]; /* 0x000280 -- 0x0003F8 */ - - uint64_t ce_adm_bap_ctrl; /* 0x000400 */ - uint64_t ce_pad_000408[127]; /* 0x000408 -- 0x0007F8 */ - - uint64_t ce_msg_buf_data63_0[35]; /* 0x000800 -- 0x000918 */ - uint64_t ce_pad_000920[29]; /* 0x000920 -- 0x0009F8 */ - - uint64_t ce_msg_buf_data127_64[35]; /* 0x000A00 -- 0x000B18 */ - uint64_t ce_pad_000B20[29]; /* 0x000B20 -- 0x000BF8 */ - - uint64_t ce_msg_buf_parity[35]; /* 0x000C00 -- 0x000D18 */ - uint64_t ce_pad_000D20[29]; /* 0x000D20 -- 0x000DF8 */ - - uint64_t ce_pad_000E00[576]; /* 0x000E00 -- 0x001FF8 */ + u64 ce_adm_id; /* 0x000000 */ + u64 ce_pad_000008; /* 0x000008 */ + u64 ce_adm_dyn_credit_status; /* 0x000010 */ + u64 ce_adm_last_credit_status; /* 0x000018 */ + u64 ce_adm_credit_limit; /* 0x000020 */ + u64 ce_adm_force_credit; /* 0x000028 */ + u64 ce_adm_control; /* 0x000030 */ + u64 ce_adm_mmr_chn_timeout; /* 0x000038 */ + u64 ce_adm_ssp_ure_timeout; /* 0x000040 */ + u64 ce_adm_ssp_dre_timeout; /* 0x000048 */ + u64 ce_adm_ssp_debug_sel; /* 0x000050 */ + u64 ce_adm_int_status; /* 0x000058 */ + u64 ce_adm_int_status_alias; /* 0x000060 */ + u64 ce_adm_int_mask; /* 0x000068 */ + u64 ce_adm_int_pending; /* 0x000070 */ + u64 ce_adm_force_int; /* 0x000078 */ + u64 ce_adm_ure_ups_buf_barrier_flush; /* 0x000080 */ + u64 ce_adm_int_dest[15]; /* 0x000088 -- 0x0000F8 */ + u64 ce_adm_error_summary; /* 0x000100 */ + u64 ce_adm_error_summary_alias; /* 0x000108 */ + u64 ce_adm_error_mask; /* 0x000110 */ + u64 ce_adm_first_error; /* 0x000118 */ + u64 ce_adm_error_overflow; /* 0x000120 */ + u64 ce_adm_error_overflow_alias; /* 0x000128 */ + u64 ce_pad_000130[2]; /* 0x000130 -- 0x000138 */ + u64 ce_adm_tnum_error; /* 0x000140 */ + u64 ce_adm_mmr_err_detail; /* 0x000148 */ + u64 ce_adm_msg_sram_perr_detail; /* 0x000150 */ + u64 ce_adm_bap_sram_perr_detail; /* 0x000158 */ + u64 ce_adm_ce_sram_perr_detail; /* 0x000160 */ + u64 ce_adm_ce_credit_oflow_detail; /* 0x000168 */ + u64 ce_adm_tx_link_idle_max_timer; /* 0x000170 */ + u64 ce_adm_pcie_debug_sel; /* 0x000178 */ + u64 ce_pad_000180[16]; /* 0x000180 -- 0x0001F8 */ + + u64 ce_adm_pcie_debug_sel_top; /* 0x000200 */ + u64 ce_adm_pcie_debug_lat_sel_lo_top; /* 0x000208 */ + u64 ce_adm_pcie_debug_lat_sel_hi_top; /* 0x000210 */ + u64 ce_adm_pcie_debug_trig_sel_top; /* 0x000218 */ + u64 ce_adm_pcie_debug_trig_lat_sel_lo_top; /* 0x000220 */ + u64 ce_adm_pcie_debug_trig_lat_sel_hi_top; /* 0x000228 */ + u64 ce_adm_pcie_trig_compare_top; /* 0x000230 */ + u64 ce_adm_pcie_trig_compare_en_top; /* 0x000238 */ + u64 ce_adm_ssp_debug_sel_top; /* 0x000240 */ + u64 ce_adm_ssp_debug_lat_sel_lo_top; /* 0x000248 */ + u64 ce_adm_ssp_debug_lat_sel_hi_top; /* 0x000250 */ + u64 ce_adm_ssp_debug_trig_sel_top; /* 0x000258 */ + u64 ce_adm_ssp_debug_trig_lat_sel_lo_top; /* 0x000260 */ + u64 ce_adm_ssp_debug_trig_lat_sel_hi_top; /* 0x000268 */ + u64 ce_adm_ssp_trig_compare_top; /* 0x000270 */ + u64 ce_adm_ssp_trig_compare_en_top; /* 0x000278 */ + u64 ce_pad_000280[48]; /* 0x000280 -- 0x0003F8 */ + + u64 ce_adm_bap_ctrl; /* 0x000400 */ + u64 ce_pad_000408[127]; /* 0x000408 -- 0x0007F8 */ + + u64 ce_msg_buf_data63_0[35]; /* 0x000800 -- 0x000918 */ + u64 ce_pad_000920[29]; /* 0x000920 -- 0x0009F8 */ + + u64 ce_msg_buf_data127_64[35]; /* 0x000A00 -- 0x000B18 */ + u64 ce_pad_000B20[29]; /* 0x000B20 -- 0x000BF8 */ + + u64 ce_msg_buf_parity[35]; /* 0x000C00 -- 0x000D18 */ + u64 ce_pad_000D20[29]; /* 0x000D20 -- 0x000DF8 */ + + u64 ce_pad_000E00[576]; /* 0x000E00 -- 0x001FF8 */ /* * LSI : LSI's PCI Express Link Registers (Link#1 and Link#2) @@ -109,141 +109,141 @@ typedef volatile struct tioce { */ #define ce_lsi(link_num) ce_lsi[link_num-1] struct ce_lsi_reg { - uint64_t ce_lsi_lpu_id; /* 0x00z000 */ - uint64_t ce_lsi_rst; /* 0x00z008 */ - uint64_t ce_lsi_dbg_stat; /* 0x00z010 */ - uint64_t ce_lsi_dbg_cfg; /* 0x00z018 */ - uint64_t ce_lsi_ltssm_ctrl; /* 0x00z020 */ - uint64_t ce_lsi_lk_stat; /* 0x00z028 */ - uint64_t ce_pad_00z030[2]; /* 0x00z030 -- 0x00z038 */ - uint64_t ce_lsi_int_and_stat; /* 0x00z040 */ - uint64_t ce_lsi_int_mask; /* 0x00z048 */ - uint64_t ce_pad_00z050[22]; /* 0x00z050 -- 0x00z0F8 */ - uint64_t ce_lsi_lk_perf_cnt_sel; /* 0x00z100 */ - uint64_t ce_pad_00z108; /* 0x00z108 */ - uint64_t ce_lsi_lk_perf_cnt_ctrl; /* 0x00z110 */ - uint64_t ce_pad_00z118; /* 0x00z118 */ - uint64_t ce_lsi_lk_perf_cnt1; /* 0x00z120 */ - uint64_t ce_lsi_lk_perf_cnt1_test; /* 0x00z128 */ - uint64_t ce_lsi_lk_perf_cnt2; /* 0x00z130 */ - uint64_t ce_lsi_lk_perf_cnt2_test; /* 0x00z138 */ - uint64_t ce_pad_00z140[24]; /* 0x00z140 -- 0x00z1F8 */ - uint64_t ce_lsi_lk_lyr_cfg; /* 0x00z200 */ - uint64_t ce_lsi_lk_lyr_status; /* 0x00z208 */ - uint64_t ce_lsi_lk_lyr_int_stat; /* 0x00z210 */ - uint64_t ce_lsi_lk_ly_int_stat_test; /* 0x00z218 */ - uint64_t ce_lsi_lk_ly_int_stat_mask; /* 0x00z220 */ - uint64_t ce_pad_00z228[3]; /* 0x00z228 -- 0x00z238 */ - uint64_t ce_lsi_fc_upd_ctl; /* 0x00z240 */ - uint64_t ce_pad_00z248[3]; /* 0x00z248 -- 0x00z258 */ - uint64_t ce_lsi_flw_ctl_upd_to_timer; /* 0x00z260 */ - uint64_t ce_lsi_flw_ctl_upd_timer0; /* 0x00z268 */ - uint64_t ce_lsi_flw_ctl_upd_timer1; /* 0x00z270 */ - uint64_t ce_pad_00z278[49]; /* 0x00z278 -- 0x00z3F8 */ - uint64_t ce_lsi_freq_nak_lat_thrsh; /* 0x00z400 */ - uint64_t ce_lsi_ack_nak_lat_tmr; /* 0x00z408 */ - uint64_t ce_lsi_rply_tmr_thr; /* 0x00z410 */ - uint64_t ce_lsi_rply_tmr; /* 0x00z418 */ - uint64_t ce_lsi_rply_num_stat; /* 0x00z420 */ - uint64_t ce_lsi_rty_buf_max_addr; /* 0x00z428 */ - uint64_t ce_lsi_rty_fifo_ptr; /* 0x00z430 */ - uint64_t ce_lsi_rty_fifo_rd_wr_ptr; /* 0x00z438 */ - uint64_t ce_lsi_rty_fifo_cred; /* 0x00z440 */ - uint64_t ce_lsi_seq_cnt; /* 0x00z448 */ - uint64_t ce_lsi_ack_sent_seq_num; /* 0x00z450 */ - uint64_t ce_lsi_seq_cnt_fifo_max_addr; /* 0x00z458 */ - uint64_t ce_lsi_seq_cnt_fifo_ptr; /* 0x00z460 */ - uint64_t ce_lsi_seq_cnt_rd_wr_ptr; /* 0x00z468 */ - uint64_t ce_lsi_tx_lk_ts_ctl; /* 0x00z470 */ - uint64_t ce_pad_00z478; /* 0x00z478 */ - uint64_t ce_lsi_mem_addr_ctl; /* 0x00z480 */ - uint64_t ce_lsi_mem_d_ld0; /* 0x00z488 */ - uint64_t ce_lsi_mem_d_ld1; /* 0x00z490 */ - uint64_t ce_lsi_mem_d_ld2; /* 0x00z498 */ - uint64_t ce_lsi_mem_d_ld3; /* 0x00z4A0 */ - uint64_t ce_lsi_mem_d_ld4; /* 0x00z4A8 */ - uint64_t ce_pad_00z4B0[2]; /* 0x00z4B0 -- 0x00z4B8 */ - uint64_t ce_lsi_rty_d_cnt; /* 0x00z4C0 */ - uint64_t ce_lsi_seq_buf_cnt; /* 0x00z4C8 */ - uint64_t ce_lsi_seq_buf_bt_d; /* 0x00z4D0 */ - uint64_t ce_pad_00z4D8; /* 0x00z4D8 */ - uint64_t ce_lsi_ack_lat_thr; /* 0x00z4E0 */ - uint64_t ce_pad_00z4E8[3]; /* 0x00z4E8 -- 0x00z4F8 */ - uint64_t ce_lsi_nxt_rcv_seq_1_cntr; /* 0x00z500 */ - uint64_t ce_lsi_unsp_dllp_rcvd; /* 0x00z508 */ - uint64_t ce_lsi_rcv_lk_ts_ctl; /* 0x00z510 */ - uint64_t ce_pad_00z518[29]; /* 0x00z518 -- 0x00z5F8 */ - uint64_t ce_lsi_phy_lyr_cfg; /* 0x00z600 */ - uint64_t ce_pad_00z608; /* 0x00z608 */ - uint64_t ce_lsi_phy_lyr_int_stat; /* 0x00z610 */ - uint64_t ce_lsi_phy_lyr_int_stat_test; /* 0x00z618 */ - uint64_t ce_lsi_phy_lyr_int_mask; /* 0x00z620 */ - uint64_t ce_pad_00z628[11]; /* 0x00z628 -- 0x00z678 */ - uint64_t ce_lsi_rcv_phy_cfg; /* 0x00z680 */ - uint64_t ce_lsi_rcv_phy_stat1; /* 0x00z688 */ - uint64_t ce_lsi_rcv_phy_stat2; /* 0x00z690 */ - uint64_t ce_lsi_rcv_phy_stat3; /* 0x00z698 */ - uint64_t ce_lsi_rcv_phy_int_stat; /* 0x00z6A0 */ - uint64_t ce_lsi_rcv_phy_int_stat_test; /* 0x00z6A8 */ - uint64_t ce_lsi_rcv_phy_int_mask; /* 0x00z6B0 */ - uint64_t ce_pad_00z6B8[9]; /* 0x00z6B8 -- 0x00z6F8 */ - uint64_t ce_lsi_tx_phy_cfg; /* 0x00z700 */ - uint64_t ce_lsi_tx_phy_stat; /* 0x00z708 */ - uint64_t ce_lsi_tx_phy_int_stat; /* 0x00z710 */ - uint64_t ce_lsi_tx_phy_int_stat_test; /* 0x00z718 */ - uint64_t ce_lsi_tx_phy_int_mask; /* 0x00z720 */ - uint64_t ce_lsi_tx_phy_stat2; /* 0x00z728 */ - uint64_t ce_pad_00z730[10]; /* 0x00z730 -- 0x00z77F */ - uint64_t ce_lsi_ltssm_cfg1; /* 0x00z780 */ - uint64_t ce_lsi_ltssm_cfg2; /* 0x00z788 */ - uint64_t ce_lsi_ltssm_cfg3; /* 0x00z790 */ - uint64_t ce_lsi_ltssm_cfg4; /* 0x00z798 */ - uint64_t ce_lsi_ltssm_cfg5; /* 0x00z7A0 */ - uint64_t ce_lsi_ltssm_stat1; /* 0x00z7A8 */ - uint64_t ce_lsi_ltssm_stat2; /* 0x00z7B0 */ - uint64_t ce_lsi_ltssm_int_stat; /* 0x00z7B8 */ - uint64_t ce_lsi_ltssm_int_stat_test; /* 0x00z7C0 */ - uint64_t ce_lsi_ltssm_int_mask; /* 0x00z7C8 */ - uint64_t ce_lsi_ltssm_stat_wr_en; /* 0x00z7D0 */ - uint64_t ce_pad_00z7D8[5]; /* 0x00z7D8 -- 0x00z7F8 */ - uint64_t ce_lsi_gb_cfg1; /* 0x00z800 */ - uint64_t ce_lsi_gb_cfg2; /* 0x00z808 */ - uint64_t ce_lsi_gb_cfg3; /* 0x00z810 */ - uint64_t ce_lsi_gb_cfg4; /* 0x00z818 */ - uint64_t ce_lsi_gb_stat; /* 0x00z820 */ - uint64_t ce_lsi_gb_int_stat; /* 0x00z828 */ - uint64_t ce_lsi_gb_int_stat_test; /* 0x00z830 */ - uint64_t ce_lsi_gb_int_mask; /* 0x00z838 */ - uint64_t ce_lsi_gb_pwr_dn1; /* 0x00z840 */ - uint64_t ce_lsi_gb_pwr_dn2; /* 0x00z848 */ - uint64_t ce_pad_00z850[246]; /* 0x00z850 -- 0x00zFF8 */ + u64 ce_lsi_lpu_id; /* 0x00z000 */ + u64 ce_lsi_rst; /* 0x00z008 */ + u64 ce_lsi_dbg_stat; /* 0x00z010 */ + u64 ce_lsi_dbg_cfg; /* 0x00z018 */ + u64 ce_lsi_ltssm_ctrl; /* 0x00z020 */ + u64 ce_lsi_lk_stat; /* 0x00z028 */ + u64 ce_pad_00z030[2]; /* 0x00z030 -- 0x00z038 */ + u64 ce_lsi_int_and_stat; /* 0x00z040 */ + u64 ce_lsi_int_mask; /* 0x00z048 */ + u64 ce_pad_00z050[22]; /* 0x00z050 -- 0x00z0F8 */ + u64 ce_lsi_lk_perf_cnt_sel; /* 0x00z100 */ + u64 ce_pad_00z108; /* 0x00z108 */ + u64 ce_lsi_lk_perf_cnt_ctrl; /* 0x00z110 */ + u64 ce_pad_00z118; /* 0x00z118 */ + u64 ce_lsi_lk_perf_cnt1; /* 0x00z120 */ + u64 ce_lsi_lk_perf_cnt1_test; /* 0x00z128 */ + u64 ce_lsi_lk_perf_cnt2; /* 0x00z130 */ + u64 ce_lsi_lk_perf_cnt2_test; /* 0x00z138 */ + u64 ce_pad_00z140[24]; /* 0x00z140 -- 0x00z1F8 */ + u64 ce_lsi_lk_lyr_cfg; /* 0x00z200 */ + u64 ce_lsi_lk_lyr_status; /* 0x00z208 */ + u64 ce_lsi_lk_lyr_int_stat; /* 0x00z210 */ + u64 ce_lsi_lk_ly_int_stat_test; /* 0x00z218 */ + u64 ce_lsi_lk_ly_int_stat_mask; /* 0x00z220 */ + u64 ce_pad_00z228[3]; /* 0x00z228 -- 0x00z238 */ + u64 ce_lsi_fc_upd_ctl; /* 0x00z240 */ + u64 ce_pad_00z248[3]; /* 0x00z248 -- 0x00z258 */ + u64 ce_lsi_flw_ctl_upd_to_timer; /* 0x00z260 */ + u64 ce_lsi_flw_ctl_upd_timer0; /* 0x00z268 */ + u64 ce_lsi_flw_ctl_upd_timer1; /* 0x00z270 */ + u64 ce_pad_00z278[49]; /* 0x00z278 -- 0x00z3F8 */ + u64 ce_lsi_freq_nak_lat_thrsh; /* 0x00z400 */ + u64 ce_lsi_ack_nak_lat_tmr; /* 0x00z408 */ + u64 ce_lsi_rply_tmr_thr; /* 0x00z410 */ + u64 ce_lsi_rply_tmr; /* 0x00z418 */ + u64 ce_lsi_rply_num_stat; /* 0x00z420 */ + u64 ce_lsi_rty_buf_max_addr; /* 0x00z428 */ + u64 ce_lsi_rty_fifo_ptr; /* 0x00z430 */ + u64 ce_lsi_rty_fifo_rd_wr_ptr; /* 0x00z438 */ + u64 ce_lsi_rty_fifo_cred; /* 0x00z440 */ + u64 ce_lsi_seq_cnt; /* 0x00z448 */ + u64 ce_lsi_ack_sent_seq_num; /* 0x00z450 */ + u64 ce_lsi_seq_cnt_fifo_max_addr; /* 0x00z458 */ + u64 ce_lsi_seq_cnt_fifo_ptr; /* 0x00z460 */ + u64 ce_lsi_seq_cnt_rd_wr_ptr; /* 0x00z468 */ + u64 ce_lsi_tx_lk_ts_ctl; /* 0x00z470 */ + u64 ce_pad_00z478; /* 0x00z478 */ + u64 ce_lsi_mem_addr_ctl; /* 0x00z480 */ + u64 ce_lsi_mem_d_ld0; /* 0x00z488 */ + u64 ce_lsi_mem_d_ld1; /* 0x00z490 */ + u64 ce_lsi_mem_d_ld2; /* 0x00z498 */ + u64 ce_lsi_mem_d_ld3; /* 0x00z4A0 */ + u64 ce_lsi_mem_d_ld4; /* 0x00z4A8 */ + u64 ce_pad_00z4B0[2]; /* 0x00z4B0 -- 0x00z4B8 */ + u64 ce_lsi_rty_d_cnt; /* 0x00z4C0 */ + u64 ce_lsi_seq_buf_cnt; /* 0x00z4C8 */ + u64 ce_lsi_seq_buf_bt_d; /* 0x00z4D0 */ + u64 ce_pad_00z4D8; /* 0x00z4D8 */ + u64 ce_lsi_ack_lat_thr; /* 0x00z4E0 */ + u64 ce_pad_00z4E8[3]; /* 0x00z4E8 -- 0x00z4F8 */ + u64 ce_lsi_nxt_rcv_seq_1_cntr; /* 0x00z500 */ + u64 ce_lsi_unsp_dllp_rcvd; /* 0x00z508 */ + u64 ce_lsi_rcv_lk_ts_ctl; /* 0x00z510 */ + u64 ce_pad_00z518[29]; /* 0x00z518 -- 0x00z5F8 */ + u64 ce_lsi_phy_lyr_cfg; /* 0x00z600 */ + u64 ce_pad_00z608; /* 0x00z608 */ + u64 ce_lsi_phy_lyr_int_stat; /* 0x00z610 */ + u64 ce_lsi_phy_lyr_int_stat_test; /* 0x00z618 */ + u64 ce_lsi_phy_lyr_int_mask; /* 0x00z620 */ + u64 ce_pad_00z628[11]; /* 0x00z628 -- 0x00z678 */ + u64 ce_lsi_rcv_phy_cfg; /* 0x00z680 */ + u64 ce_lsi_rcv_phy_stat1; /* 0x00z688 */ + u64 ce_lsi_rcv_phy_stat2; /* 0x00z690 */ + u64 ce_lsi_rcv_phy_stat3; /* 0x00z698 */ + u64 ce_lsi_rcv_phy_int_stat; /* 0x00z6A0 */ + u64 ce_lsi_rcv_phy_int_stat_test; /* 0x00z6A8 */ + u64 ce_lsi_rcv_phy_int_mask; /* 0x00z6B0 */ + u64 ce_pad_00z6B8[9]; /* 0x00z6B8 -- 0x00z6F8 */ + u64 ce_lsi_tx_phy_cfg; /* 0x00z700 */ + u64 ce_lsi_tx_phy_stat; /* 0x00z708 */ + u64 ce_lsi_tx_phy_int_stat; /* 0x00z710 */ + u64 ce_lsi_tx_phy_int_stat_test; /* 0x00z718 */ + u64 ce_lsi_tx_phy_int_mask; /* 0x00z720 */ + u64 ce_lsi_tx_phy_stat2; /* 0x00z728 */ + u64 ce_pad_00z730[10]; /* 0x00z730 -- 0x00z77F */ + u64 ce_lsi_ltssm_cfg1; /* 0x00z780 */ + u64 ce_lsi_ltssm_cfg2; /* 0x00z788 */ + u64 ce_lsi_ltssm_cfg3; /* 0x00z790 */ + u64 ce_lsi_ltssm_cfg4; /* 0x00z798 */ + u64 ce_lsi_ltssm_cfg5; /* 0x00z7A0 */ + u64 ce_lsi_ltssm_stat1; /* 0x00z7A8 */ + u64 ce_lsi_ltssm_stat2; /* 0x00z7B0 */ + u64 ce_lsi_ltssm_int_stat; /* 0x00z7B8 */ + u64 ce_lsi_ltssm_int_stat_test; /* 0x00z7C0 */ + u64 ce_lsi_ltssm_int_mask; /* 0x00z7C8 */ + u64 ce_lsi_ltssm_stat_wr_en; /* 0x00z7D0 */ + u64 ce_pad_00z7D8[5]; /* 0x00z7D8 -- 0x00z7F8 */ + u64 ce_lsi_gb_cfg1; /* 0x00z800 */ + u64 ce_lsi_gb_cfg2; /* 0x00z808 */ + u64 ce_lsi_gb_cfg3; /* 0x00z810 */ + u64 ce_lsi_gb_cfg4; /* 0x00z818 */ + u64 ce_lsi_gb_stat; /* 0x00z820 */ + u64 ce_lsi_gb_int_stat; /* 0x00z828 */ + u64 ce_lsi_gb_int_stat_test; /* 0x00z830 */ + u64 ce_lsi_gb_int_mask; /* 0x00z838 */ + u64 ce_lsi_gb_pwr_dn1; /* 0x00z840 */ + u64 ce_lsi_gb_pwr_dn2; /* 0x00z848 */ + u64 ce_pad_00z850[246]; /* 0x00z850 -- 0x00zFF8 */ } ce_lsi[2]; - uint64_t ce_pad_004000[10]; /* 0x004000 -- 0x004048 */ + u64 ce_pad_004000[10]; /* 0x004000 -- 0x004048 */ /* * CRM: Coretalk Receive Module Registers */ - uint64_t ce_crm_debug_mux; /* 0x004050 */ - uint64_t ce_pad_004058; /* 0x004058 */ - uint64_t ce_crm_ssp_err_cmd_wrd; /* 0x004060 */ - uint64_t ce_crm_ssp_err_addr; /* 0x004068 */ - uint64_t ce_crm_ssp_err_syn; /* 0x004070 */ + u64 ce_crm_debug_mux; /* 0x004050 */ + u64 ce_pad_004058; /* 0x004058 */ + u64 ce_crm_ssp_err_cmd_wrd; /* 0x004060 */ + u64 ce_crm_ssp_err_addr; /* 0x004068 */ + u64 ce_crm_ssp_err_syn; /* 0x004070 */ - uint64_t ce_pad_004078[499]; /* 0x004078 -- 0x005008 */ + u64 ce_pad_004078[499]; /* 0x004078 -- 0x005008 */ /* * CXM: Coretalk Xmit Module Registers */ - uint64_t ce_cxm_dyn_credit_status; /* 0x005010 */ - uint64_t ce_cxm_last_credit_status; /* 0x005018 */ - uint64_t ce_cxm_credit_limit; /* 0x005020 */ - uint64_t ce_cxm_force_credit; /* 0x005028 */ - uint64_t ce_cxm_disable_bypass; /* 0x005030 */ - uint64_t ce_pad_005038[3]; /* 0x005038 -- 0x005048 */ - uint64_t ce_cxm_debug_mux; /* 0x005050 */ + u64 ce_cxm_dyn_credit_status; /* 0x005010 */ + u64 ce_cxm_last_credit_status; /* 0x005018 */ + u64 ce_cxm_credit_limit; /* 0x005020 */ + u64 ce_cxm_force_credit; /* 0x005028 */ + u64 ce_cxm_disable_bypass; /* 0x005030 */ + u64 ce_pad_005038[3]; /* 0x005038 -- 0x005048 */ + u64 ce_cxm_debug_mux; /* 0x005050 */ - uint64_t ce_pad_005058[501]; /* 0x005058 -- 0x005FF8 */ + u64 ce_pad_005058[501]; /* 0x005058 -- 0x005FF8 */ /* * DTL: Downstream Transaction Layer Regs (Link#1 and Link#2) @@ -258,209 +258,209 @@ typedef volatile struct tioce { #define ce_utl(link_num) ce_dtl_utl[link_num-1] struct ce_dtl_utl_reg { /* DTL */ - uint64_t ce_dtl_dtdr_credit_limit; /* 0x00y000 */ - uint64_t ce_dtl_dtdr_credit_force; /* 0x00y008 */ - uint64_t ce_dtl_dyn_credit_status; /* 0x00y010 */ - uint64_t ce_dtl_dtl_last_credit_stat; /* 0x00y018 */ - uint64_t ce_dtl_dtl_ctrl; /* 0x00y020 */ - uint64_t ce_pad_00y028[5]; /* 0x00y028 -- 0x00y048 */ - uint64_t ce_dtl_debug_sel; /* 0x00y050 */ - uint64_t ce_pad_00y058[501]; /* 0x00y058 -- 0x00yFF8 */ + u64 ce_dtl_dtdr_credit_limit; /* 0x00y000 */ + u64 ce_dtl_dtdr_credit_force; /* 0x00y008 */ + u64 ce_dtl_dyn_credit_status; /* 0x00y010 */ + u64 ce_dtl_dtl_last_credit_stat; /* 0x00y018 */ + u64 ce_dtl_dtl_ctrl; /* 0x00y020 */ + u64 ce_pad_00y028[5]; /* 0x00y028 -- 0x00y048 */ + u64 ce_dtl_debug_sel; /* 0x00y050 */ + u64 ce_pad_00y058[501]; /* 0x00y058 -- 0x00yFF8 */ /* UTL */ - uint64_t ce_utl_utl_ctrl; /* 0x00z000 */ - uint64_t ce_utl_debug_sel; /* 0x00z008 */ - uint64_t ce_pad_00z010[510]; /* 0x00z010 -- 0x00zFF8 */ + u64 ce_utl_utl_ctrl; /* 0x00z000 */ + u64 ce_utl_debug_sel; /* 0x00z008 */ + u64 ce_pad_00z010[510]; /* 0x00z010 -- 0x00zFF8 */ } ce_dtl_utl[2]; - uint64_t ce_pad_00A000[514]; /* 0x00A000 -- 0x00B008 */ + u64 ce_pad_00A000[514]; /* 0x00A000 -- 0x00B008 */ /* * URE: Upstream Request Engine */ - uint64_t ce_ure_dyn_credit_status; /* 0x00B010 */ - uint64_t ce_ure_last_credit_status; /* 0x00B018 */ - uint64_t ce_ure_credit_limit; /* 0x00B020 */ - uint64_t ce_pad_00B028; /* 0x00B028 */ - uint64_t ce_ure_control; /* 0x00B030 */ - uint64_t ce_ure_status; /* 0x00B038 */ - uint64_t ce_pad_00B040[2]; /* 0x00B040 -- 0x00B048 */ - uint64_t ce_ure_debug_sel; /* 0x00B050 */ - uint64_t ce_ure_pcie_debug_sel; /* 0x00B058 */ - uint64_t ce_ure_ssp_err_cmd_wrd; /* 0x00B060 */ - uint64_t ce_ure_ssp_err_addr; /* 0x00B068 */ - uint64_t ce_ure_page_map; /* 0x00B070 */ - uint64_t ce_ure_dir_map[TIOCE_NUM_PORTS]; /* 0x00B078 */ - uint64_t ce_ure_pipe_sel1; /* 0x00B088 */ - uint64_t ce_ure_pipe_mask1; /* 0x00B090 */ - uint64_t ce_ure_pipe_sel2; /* 0x00B098 */ - uint64_t ce_ure_pipe_mask2; /* 0x00B0A0 */ - uint64_t ce_ure_pcie1_credits_sent; /* 0x00B0A8 */ - uint64_t ce_ure_pcie1_credits_used; /* 0x00B0B0 */ - uint64_t ce_ure_pcie1_credit_limit; /* 0x00B0B8 */ - uint64_t ce_ure_pcie2_credits_sent; /* 0x00B0C0 */ - uint64_t ce_ure_pcie2_credits_used; /* 0x00B0C8 */ - uint64_t ce_ure_pcie2_credit_limit; /* 0x00B0D0 */ - uint64_t ce_ure_pcie_force_credit; /* 0x00B0D8 */ - uint64_t ce_ure_rd_tnum_val; /* 0x00B0E0 */ - uint64_t ce_ure_rd_tnum_rsp_rcvd; /* 0x00B0E8 */ - uint64_t ce_ure_rd_tnum_esent_timer; /* 0x00B0F0 */ - uint64_t ce_ure_rd_tnum_error; /* 0x00B0F8 */ - uint64_t ce_ure_rd_tnum_first_cl; /* 0x00B100 */ - uint64_t ce_ure_rd_tnum_link_buf; /* 0x00B108 */ - uint64_t ce_ure_wr_tnum_val; /* 0x00B110 */ - uint64_t ce_ure_sram_err_addr0; /* 0x00B118 */ - uint64_t ce_ure_sram_err_addr1; /* 0x00B120 */ - uint64_t ce_ure_sram_err_addr2; /* 0x00B128 */ - uint64_t ce_ure_sram_rd_addr0; /* 0x00B130 */ - uint64_t ce_ure_sram_rd_addr1; /* 0x00B138 */ - uint64_t ce_ure_sram_rd_addr2; /* 0x00B140 */ - uint64_t ce_ure_sram_wr_addr0; /* 0x00B148 */ - uint64_t ce_ure_sram_wr_addr1; /* 0x00B150 */ - uint64_t ce_ure_sram_wr_addr2; /* 0x00B158 */ - uint64_t ce_ure_buf_flush10; /* 0x00B160 */ - uint64_t ce_ure_buf_flush11; /* 0x00B168 */ - uint64_t ce_ure_buf_flush12; /* 0x00B170 */ - uint64_t ce_ure_buf_flush13; /* 0x00B178 */ - uint64_t ce_ure_buf_flush20; /* 0x00B180 */ - uint64_t ce_ure_buf_flush21; /* 0x00B188 */ - uint64_t ce_ure_buf_flush22; /* 0x00B190 */ - uint64_t ce_ure_buf_flush23; /* 0x00B198 */ - uint64_t ce_ure_pcie_control1; /* 0x00B1A0 */ - uint64_t ce_ure_pcie_control2; /* 0x00B1A8 */ - - uint64_t ce_pad_00B1B0[458]; /* 0x00B1B0 -- 0x00BFF8 */ + u64 ce_ure_dyn_credit_status; /* 0x00B010 */ + u64 ce_ure_last_credit_status; /* 0x00B018 */ + u64 ce_ure_credit_limit; /* 0x00B020 */ + u64 ce_pad_00B028; /* 0x00B028 */ + u64 ce_ure_control; /* 0x00B030 */ + u64 ce_ure_status; /* 0x00B038 */ + u64 ce_pad_00B040[2]; /* 0x00B040 -- 0x00B048 */ + u64 ce_ure_debug_sel; /* 0x00B050 */ + u64 ce_ure_pcie_debug_sel; /* 0x00B058 */ + u64 ce_ure_ssp_err_cmd_wrd; /* 0x00B060 */ + u64 ce_ure_ssp_err_addr; /* 0x00B068 */ + u64 ce_ure_page_map; /* 0x00B070 */ + u64 ce_ure_dir_map[TIOCE_NUM_PORTS]; /* 0x00B078 */ + u64 ce_ure_pipe_sel1; /* 0x00B088 */ + u64 ce_ure_pipe_mask1; /* 0x00B090 */ + u64 ce_ure_pipe_sel2; /* 0x00B098 */ + u64 ce_ure_pipe_mask2; /* 0x00B0A0 */ + u64 ce_ure_pcie1_credits_sent; /* 0x00B0A8 */ + u64 ce_ure_pcie1_credits_used; /* 0x00B0B0 */ + u64 ce_ure_pcie1_credit_limit; /* 0x00B0B8 */ + u64 ce_ure_pcie2_credits_sent; /* 0x00B0C0 */ + u64 ce_ure_pcie2_credits_used; /* 0x00B0C8 */ + u64 ce_ure_pcie2_credit_limit; /* 0x00B0D0 */ + u64 ce_ure_pcie_force_credit; /* 0x00B0D8 */ + u64 ce_ure_rd_tnum_val; /* 0x00B0E0 */ + u64 ce_ure_rd_tnum_rsp_rcvd; /* 0x00B0E8 */ + u64 ce_ure_rd_tnum_esent_timer; /* 0x00B0F0 */ + u64 ce_ure_rd_tnum_error; /* 0x00B0F8 */ + u64 ce_ure_rd_tnum_first_cl; /* 0x00B100 */ + u64 ce_ure_rd_tnum_link_buf; /* 0x00B108 */ + u64 ce_ure_wr_tnum_val; /* 0x00B110 */ + u64 ce_ure_sram_err_addr0; /* 0x00B118 */ + u64 ce_ure_sram_err_addr1; /* 0x00B120 */ + u64 ce_ure_sram_err_addr2; /* 0x00B128 */ + u64 ce_ure_sram_rd_addr0; /* 0x00B130 */ + u64 ce_ure_sram_rd_addr1; /* 0x00B138 */ + u64 ce_ure_sram_rd_addr2; /* 0x00B140 */ + u64 ce_ure_sram_wr_addr0; /* 0x00B148 */ + u64 ce_ure_sram_wr_addr1; /* 0x00B150 */ + u64 ce_ure_sram_wr_addr2; /* 0x00B158 */ + u64 ce_ure_buf_flush10; /* 0x00B160 */ + u64 ce_ure_buf_flush11; /* 0x00B168 */ + u64 ce_ure_buf_flush12; /* 0x00B170 */ + u64 ce_ure_buf_flush13; /* 0x00B178 */ + u64 ce_ure_buf_flush20; /* 0x00B180 */ + u64 ce_ure_buf_flush21; /* 0x00B188 */ + u64 ce_ure_buf_flush22; /* 0x00B190 */ + u64 ce_ure_buf_flush23; /* 0x00B198 */ + u64 ce_ure_pcie_control1; /* 0x00B1A0 */ + u64 ce_ure_pcie_control2; /* 0x00B1A8 */ + + u64 ce_pad_00B1B0[458]; /* 0x00B1B0 -- 0x00BFF8 */ /* Upstream Data Buffer, Port1 */ struct ce_ure_maint_ups_dat1_data { - uint64_t data63_0[512]; /* 0x00C000 -- 0x00CFF8 */ - uint64_t data127_64[512]; /* 0x00D000 -- 0x00DFF8 */ - uint64_t parity[512]; /* 0x00E000 -- 0x00EFF8 */ + u64 data63_0[512]; /* 0x00C000 -- 0x00CFF8 */ + u64 data127_64[512]; /* 0x00D000 -- 0x00DFF8 */ + u64 parity[512]; /* 0x00E000 -- 0x00EFF8 */ } ce_ure_maint_ups_dat1; /* Upstream Header Buffer, Port1 */ struct ce_ure_maint_ups_hdr1_data { - uint64_t data63_0[512]; /* 0x00F000 -- 0x00FFF8 */ - uint64_t data127_64[512]; /* 0x010000 -- 0x010FF8 */ - uint64_t parity[512]; /* 0x011000 -- 0x011FF8 */ + u64 data63_0[512]; /* 0x00F000 -- 0x00FFF8 */ + u64 data127_64[512]; /* 0x010000 -- 0x010FF8 */ + u64 parity[512]; /* 0x011000 -- 0x011FF8 */ } ce_ure_maint_ups_hdr1; /* Upstream Data Buffer, Port2 */ struct ce_ure_maint_ups_dat2_data { - uint64_t data63_0[512]; /* 0x012000 -- 0x012FF8 */ - uint64_t data127_64[512]; /* 0x013000 -- 0x013FF8 */ - uint64_t parity[512]; /* 0x014000 -- 0x014FF8 */ + u64 data63_0[512]; /* 0x012000 -- 0x012FF8 */ + u64 data127_64[512]; /* 0x013000 -- 0x013FF8 */ + u64 parity[512]; /* 0x014000 -- 0x014FF8 */ } ce_ure_maint_ups_dat2; /* Upstream Header Buffer, Port2 */ struct ce_ure_maint_ups_hdr2_data { - uint64_t data63_0[512]; /* 0x015000 -- 0x015FF8 */ - uint64_t data127_64[512]; /* 0x016000 -- 0x016FF8 */ - uint64_t parity[512]; /* 0x017000 -- 0x017FF8 */ + u64 data63_0[512]; /* 0x015000 -- 0x015FF8 */ + u64 data127_64[512]; /* 0x016000 -- 0x016FF8 */ + u64 parity[512]; /* 0x017000 -- 0x017FF8 */ } ce_ure_maint_ups_hdr2; /* Downstream Data Buffer */ struct ce_ure_maint_dns_dat_data { - uint64_t data63_0[512]; /* 0x018000 -- 0x018FF8 */ - uint64_t data127_64[512]; /* 0x019000 -- 0x019FF8 */ - uint64_t parity[512]; /* 0x01A000 -- 0x01AFF8 */ + u64 data63_0[512]; /* 0x018000 -- 0x018FF8 */ + u64 data127_64[512]; /* 0x019000 -- 0x019FF8 */ + u64 parity[512]; /* 0x01A000 -- 0x01AFF8 */ } ce_ure_maint_dns_dat; /* Downstream Header Buffer */ struct ce_ure_maint_dns_hdr_data { - uint64_t data31_0[64]; /* 0x01B000 -- 0x01B1F8 */ - uint64_t data95_32[64]; /* 0x01B200 -- 0x01B3F8 */ - uint64_t parity[64]; /* 0x01B400 -- 0x01B5F8 */ + u64 data31_0[64]; /* 0x01B000 -- 0x01B1F8 */ + u64 data95_32[64]; /* 0x01B200 -- 0x01B3F8 */ + u64 parity[64]; /* 0x01B400 -- 0x01B5F8 */ } ce_ure_maint_dns_hdr; /* RCI Buffer Data */ struct ce_ure_maint_rci_data { - uint64_t data41_0[64]; /* 0x01B600 -- 0x01B7F8 */ - uint64_t data69_42[64]; /* 0x01B800 -- 0x01B9F8 */ + u64 data41_0[64]; /* 0x01B600 -- 0x01B7F8 */ + u64 data69_42[64]; /* 0x01B800 -- 0x01B9F8 */ } ce_ure_maint_rci; /* Response Queue */ - uint64_t ce_ure_maint_rspq[64]; /* 0x01BA00 -- 0x01BBF8 */ + u64 ce_ure_maint_rspq[64]; /* 0x01BA00 -- 0x01BBF8 */ - uint64_t ce_pad_01C000[4224]; /* 0x01BC00 -- 0x023FF8 */ + u64 ce_pad_01C000[4224]; /* 0x01BC00 -- 0x023FF8 */ /* Admin Build-a-Packet Buffer */ struct ce_adm_maint_bap_buf_data { - uint64_t data63_0[258]; /* 0x024000 -- 0x024808 */ - uint64_t data127_64[258]; /* 0x024810 -- 0x025018 */ - uint64_t parity[258]; /* 0x025020 -- 0x025828 */ + u64 data63_0[258]; /* 0x024000 -- 0x024808 */ + u64 data127_64[258]; /* 0x024810 -- 0x025018 */ + u64 parity[258]; /* 0x025020 -- 0x025828 */ } ce_adm_maint_bap_buf; - uint64_t ce_pad_025830[5370]; /* 0x025830 -- 0x02FFF8 */ + u64 ce_pad_025830[5370]; /* 0x025830 -- 0x02FFF8 */ /* URE: 40bit PMU ATE Buffer */ /* 0x030000 -- 0x037FF8 */ - uint64_t ce_ure_ate40[TIOCE_NUM_M40_ATES]; + u64 ce_ure_ate40[TIOCE_NUM_M40_ATES]; /* URE: 32/40bit PMU ATE Buffer */ /* 0x038000 -- 0x03BFF8 */ - uint64_t ce_ure_ate3240[TIOCE_NUM_M3240_ATES]; + u64 ce_ure_ate3240[TIOCE_NUM_M3240_ATES]; - uint64_t ce_pad_03C000[2050]; /* 0x03C000 -- 0x040008 */ + u64 ce_pad_03C000[2050]; /* 0x03C000 -- 0x040008 */ /* * DRE: Down Stream Request Engine */ - uint64_t ce_dre_dyn_credit_status1; /* 0x040010 */ - uint64_t ce_dre_dyn_credit_status2; /* 0x040018 */ - uint64_t ce_dre_last_credit_status1; /* 0x040020 */ - uint64_t ce_dre_last_credit_status2; /* 0x040028 */ - uint64_t ce_dre_credit_limit1; /* 0x040030 */ - uint64_t ce_dre_credit_limit2; /* 0x040038 */ - uint64_t ce_dre_force_credit1; /* 0x040040 */ - uint64_t ce_dre_force_credit2; /* 0x040048 */ - uint64_t ce_dre_debug_mux1; /* 0x040050 */ - uint64_t ce_dre_debug_mux2; /* 0x040058 */ - uint64_t ce_dre_ssp_err_cmd_wrd; /* 0x040060 */ - uint64_t ce_dre_ssp_err_addr; /* 0x040068 */ - uint64_t ce_dre_comp_err_cmd_wrd; /* 0x040070 */ - uint64_t ce_dre_comp_err_addr; /* 0x040078 */ - uint64_t ce_dre_req_status; /* 0x040080 */ - uint64_t ce_dre_config1; /* 0x040088 */ - uint64_t ce_dre_config2; /* 0x040090 */ - uint64_t ce_dre_config_req_status; /* 0x040098 */ - uint64_t ce_pad_0400A0[12]; /* 0x0400A0 -- 0x0400F8 */ - uint64_t ce_dre_dyn_fifo; /* 0x040100 */ - uint64_t ce_pad_040108[3]; /* 0x040108 -- 0x040118 */ - uint64_t ce_dre_last_fifo; /* 0x040120 */ - - uint64_t ce_pad_040128[27]; /* 0x040128 -- 0x0401F8 */ + u64 ce_dre_dyn_credit_status1; /* 0x040010 */ + u64 ce_dre_dyn_credit_status2; /* 0x040018 */ + u64 ce_dre_last_credit_status1; /* 0x040020 */ + u64 ce_dre_last_credit_status2; /* 0x040028 */ + u64 ce_dre_credit_limit1; /* 0x040030 */ + u64 ce_dre_credit_limit2; /* 0x040038 */ + u64 ce_dre_force_credit1; /* 0x040040 */ + u64 ce_dre_force_credit2; /* 0x040048 */ + u64 ce_dre_debug_mux1; /* 0x040050 */ + u64 ce_dre_debug_mux2; /* 0x040058 */ + u64 ce_dre_ssp_err_cmd_wrd; /* 0x040060 */ + u64 ce_dre_ssp_err_addr; /* 0x040068 */ + u64 ce_dre_comp_err_cmd_wrd; /* 0x040070 */ + u64 ce_dre_comp_err_addr; /* 0x040078 */ + u64 ce_dre_req_status; /* 0x040080 */ + u64 ce_dre_config1; /* 0x040088 */ + u64 ce_dre_config2; /* 0x040090 */ + u64 ce_dre_config_req_status; /* 0x040098 */ + u64 ce_pad_0400A0[12]; /* 0x0400A0 -- 0x0400F8 */ + u64 ce_dre_dyn_fifo; /* 0x040100 */ + u64 ce_pad_040108[3]; /* 0x040108 -- 0x040118 */ + u64 ce_dre_last_fifo; /* 0x040120 */ + + u64 ce_pad_040128[27]; /* 0x040128 -- 0x0401F8 */ /* DRE Downstream Head Queue */ struct ce_dre_maint_ds_head_queue { - uint64_t data63_0[32]; /* 0x040200 -- 0x0402F8 */ - uint64_t data127_64[32]; /* 0x040300 -- 0x0403F8 */ - uint64_t parity[32]; /* 0x040400 -- 0x0404F8 */ + u64 data63_0[32]; /* 0x040200 -- 0x0402F8 */ + u64 data127_64[32]; /* 0x040300 -- 0x0403F8 */ + u64 parity[32]; /* 0x040400 -- 0x0404F8 */ } ce_dre_maint_ds_head_q; - uint64_t ce_pad_040500[352]; /* 0x040500 -- 0x040FF8 */ + u64 ce_pad_040500[352]; /* 0x040500 -- 0x040FF8 */ /* DRE Downstream Data Queue */ struct ce_dre_maint_ds_data_queue { - uint64_t data63_0[256]; /* 0x041000 -- 0x0417F8 */ - uint64_t ce_pad_041800[256]; /* 0x041800 -- 0x041FF8 */ - uint64_t data127_64[256]; /* 0x042000 -- 0x0427F8 */ - uint64_t ce_pad_042800[256]; /* 0x042800 -- 0x042FF8 */ - uint64_t parity[256]; /* 0x043000 -- 0x0437F8 */ - uint64_t ce_pad_043800[256]; /* 0x043800 -- 0x043FF8 */ + u64 data63_0[256]; /* 0x041000 -- 0x0417F8 */ + u64 ce_pad_041800[256]; /* 0x041800 -- 0x041FF8 */ + u64 data127_64[256]; /* 0x042000 -- 0x0427F8 */ + u64 ce_pad_042800[256]; /* 0x042800 -- 0x042FF8 */ + u64 parity[256]; /* 0x043000 -- 0x0437F8 */ + u64 ce_pad_043800[256]; /* 0x043800 -- 0x043FF8 */ } ce_dre_maint_ds_data_q; /* DRE URE Upstream Response Queue */ struct ce_dre_maint_ure_us_rsp_queue { - uint64_t data63_0[8]; /* 0x044000 -- 0x044038 */ - uint64_t ce_pad_044040[24]; /* 0x044040 -- 0x0440F8 */ - uint64_t data127_64[8]; /* 0x044100 -- 0x044138 */ - uint64_t ce_pad_044140[24]; /* 0x044140 -- 0x0441F8 */ - uint64_t parity[8]; /* 0x044200 -- 0x044238 */ - uint64_t ce_pad_044240[24]; /* 0x044240 -- 0x0442F8 */ + u64 data63_0[8]; /* 0x044000 -- 0x044038 */ + u64 ce_pad_044040[24]; /* 0x044040 -- 0x0440F8 */ + u64 data127_64[8]; /* 0x044100 -- 0x044138 */ + u64 ce_pad_044140[24]; /* 0x044140 -- 0x0441F8 */ + u64 parity[8]; /* 0x044200 -- 0x044238 */ + u64 ce_pad_044240[24]; /* 0x044240 -- 0x0442F8 */ } ce_dre_maint_ure_us_rsp_q; - uint64_t ce_dre_maint_us_wrt_rsp[32];/* 0x044300 -- 0x0443F8 */ + u64 ce_dre_maint_us_wrt_rsp[32];/* 0x044300 -- 0x0443F8 */ - uint64_t ce_end_of_struct; /* 0x044400 */ + u64 ce_end_of_struct; /* 0x044400 */ } tioce_t; @@ -625,11 +625,11 @@ typedef volatile struct tioce { #define CE_URE_BUS_MASK (0xFFULL << BUS_SRC_ID_SHFT) #define CE_URE_DEV_MASK (0x1FULL << DEV_SRC_ID_SHFT) #define CE_URE_FNC_MASK (0x07ULL << FNC_SRC_ID_SHFT) -#define CE_URE_PIPE_BUS(b) (((uint64_t)(b) << BUS_SRC_ID_SHFT) & \ +#define CE_URE_PIPE_BUS(b) (((u64)(b) << BUS_SRC_ID_SHFT) & \ CE_URE_BUS_MASK) -#define CE_URE_PIPE_DEV(d) (((uint64_t)(d) << DEV_SRC_ID_SHFT) & \ +#define CE_URE_PIPE_DEV(d) (((u64)(d) << DEV_SRC_ID_SHFT) & \ CE_URE_DEV_MASK) -#define CE_URE_PIPE_FNC(f) (((uint64_t)(f) << FNC_SRC_ID_SHFT) & \ +#define CE_URE_PIPE_FNC(f) (((u64)(f) << FNC_SRC_ID_SHFT) & \ CE_URE_FNC_MASK) #define CE_URE_SEL1_SHFT 0 @@ -660,9 +660,9 @@ typedef volatile struct tioce { #define CE_URE_PN1_MASK (0xFFULL << CE_URE_PN1_SHFT) #define CE_URE_PN2_SHFT 24 #define CE_URE_PN2_MASK (0xFFULL << CE_URE_PN2_SHFT) -#define CE_URE_PN1_SET(n) (((uint64_t)(n) << CE_URE_PN1_SHFT) & \ +#define CE_URE_PN1_SET(n) (((u64)(n) << CE_URE_PN1_SHFT) & \ CE_URE_PN1_MASK) -#define CE_URE_PN2_SET(n) (((uint64_t)(n) << CE_URE_PN2_SHFT) & \ +#define CE_URE_PN2_SET(n) (((u64)(n) << CE_URE_PN2_SHFT) & \ CE_URE_PN2_MASK) /* ce_ure_pcie_control2 register bit masks & shifts */ @@ -681,9 +681,9 @@ typedef volatile struct tioce { #define CE_URE_PSN1_MASK (0x1FFFULL << CE_URE_PSN1_SHFT) #define CE_URE_PSN2_SHFT 32 #define CE_URE_PSN2_MASK (0x1FFFULL << CE_URE_PSN2_SHFT) -#define CE_URE_PSN1_SET(n) (((uint64_t)(n) << CE_URE_PSN1_SHFT) & \ +#define CE_URE_PSN1_SET(n) (((u64)(n) << CE_URE_PSN1_SHFT) & \ CE_URE_PSN1_MASK) -#define CE_URE_PSN2_SET(n) (((uint64_t)(n) << CE_URE_PSN2_SHFT) & \ +#define CE_URE_PSN2_SET(n) (((u64)(n) << CE_URE_PSN2_SHFT) & \ CE_URE_PSN2_MASK) /* diff --git a/include/asm-ia64/sn/tioce_provider.h b/include/asm-ia64/sn/tioce_provider.h index cb414908671..6d62b13f7ae 100644 --- a/include/asm-ia64/sn/tioce_provider.h +++ b/include/asm-ia64/sn/tioce_provider.h @@ -21,9 +21,9 @@ struct tioce_common { struct pcibus_bussoft ce_pcibus; /* common pciio header */ - uint32_t ce_rev; - uint64_t ce_kernel_private; - uint64_t ce_prom_private; + u32 ce_rev; + u64 ce_kernel_private; + u64 ce_prom_private; }; struct tioce_kernel { @@ -31,31 +31,31 @@ struct tioce_kernel { spinlock_t ce_lock; struct list_head ce_dmamap_list; - uint64_t ce_ate40_shadow[TIOCE_NUM_M40_ATES]; - uint64_t ce_ate3240_shadow[TIOCE_NUM_M3240_ATES]; - uint32_t ce_ate3240_pagesize; + u64 ce_ate40_shadow[TIOCE_NUM_M40_ATES]; + u64 ce_ate3240_shadow[TIOCE_NUM_M3240_ATES]; + u32 ce_ate3240_pagesize; - uint8_t ce_port1_secondary; + u8 ce_port1_secondary; /* per-port resources */ struct { int dirmap_refcnt; - uint64_t dirmap_shadow; + u64 dirmap_shadow; } ce_port[TIOCE_NUM_PORTS]; }; struct tioce_dmamap { struct list_head ce_dmamap_list; /* headed by tioce_kernel */ - uint32_t refcnt; + u32 refcnt; - uint64_t nbytes; /* # bytes mapped */ + u64 nbytes; /* # bytes mapped */ - uint64_t ct_start; /* coretalk start address */ - uint64_t pci_start; /* bus start address */ + u64 ct_start; /* coretalk start address */ + u64 pci_start; /* bus start address */ - uint64_t *ate_hw; /* hw ptr of first ate in map */ - uint64_t *ate_shadow; /* shadow ptr of firat ate */ - uint16_t ate_count; /* # ate's in the map */ + u64 *ate_hw; /* hw ptr of first ate in map */ + u64 *ate_shadow; /* shadow ptr of firat ate */ + u16 ate_count; /* # ate's in the map */ }; extern int tioce_init_provider(void); diff --git a/include/asm-ia64/sn/tiocp.h b/include/asm-ia64/sn/tiocp.h index 5f2489c9d2d..f47c08ab483 100644 --- a/include/asm-ia64/sn/tiocp.h +++ b/include/asm-ia64/sn/tiocp.h @@ -21,189 +21,189 @@ struct tiocp{ /* 0x000000-0x00FFFF -- Local Registers */ /* 0x000000-0x000057 -- (Legacy Widget Space) Configuration */ - uint64_t cp_id; /* 0x000000 */ - uint64_t cp_stat; /* 0x000008 */ - uint64_t cp_err_upper; /* 0x000010 */ - uint64_t cp_err_lower; /* 0x000018 */ + u64 cp_id; /* 0x000000 */ + u64 cp_stat; /* 0x000008 */ + u64 cp_err_upper; /* 0x000010 */ + u64 cp_err_lower; /* 0x000018 */ #define cp_err cp_err_lower - uint64_t cp_control; /* 0x000020 */ - uint64_t cp_req_timeout; /* 0x000028 */ - uint64_t cp_intr_upper; /* 0x000030 */ - uint64_t cp_intr_lower; /* 0x000038 */ + u64 cp_control; /* 0x000020 */ + u64 cp_req_timeout; /* 0x000028 */ + u64 cp_intr_upper; /* 0x000030 */ + u64 cp_intr_lower; /* 0x000038 */ #define cp_intr cp_intr_lower - uint64_t cp_err_cmdword; /* 0x000040 */ - uint64_t _pad_000048; /* 0x000048 */ - uint64_t cp_tflush; /* 0x000050 */ + u64 cp_err_cmdword; /* 0x000040 */ + u64 _pad_000048; /* 0x000048 */ + u64 cp_tflush; /* 0x000050 */ /* 0x000058-0x00007F -- Bridge-specific Configuration */ - uint64_t cp_aux_err; /* 0x000058 */ - uint64_t cp_resp_upper; /* 0x000060 */ - uint64_t cp_resp_lower; /* 0x000068 */ + u64 cp_aux_err; /* 0x000058 */ + u64 cp_resp_upper; /* 0x000060 */ + u64 cp_resp_lower; /* 0x000068 */ #define cp_resp cp_resp_lower - uint64_t cp_tst_pin_ctrl; /* 0x000070 */ - uint64_t cp_addr_lkerr; /* 0x000078 */ + u64 cp_tst_pin_ctrl; /* 0x000070 */ + u64 cp_addr_lkerr; /* 0x000078 */ /* 0x000080-0x00008F -- PMU & MAP */ - uint64_t cp_dir_map; /* 0x000080 */ - uint64_t _pad_000088; /* 0x000088 */ + u64 cp_dir_map; /* 0x000080 */ + u64 _pad_000088; /* 0x000088 */ /* 0x000090-0x00009F -- SSRAM */ - uint64_t cp_map_fault; /* 0x000090 */ - uint64_t _pad_000098; /* 0x000098 */ + u64 cp_map_fault; /* 0x000090 */ + u64 _pad_000098; /* 0x000098 */ /* 0x0000A0-0x0000AF -- Arbitration */ - uint64_t cp_arb; /* 0x0000A0 */ - uint64_t _pad_0000A8; /* 0x0000A8 */ + u64 cp_arb; /* 0x0000A0 */ + u64 _pad_0000A8; /* 0x0000A8 */ /* 0x0000B0-0x0000BF -- Number In A Can or ATE Parity Error */ - uint64_t cp_ate_parity_err; /* 0x0000B0 */ - uint64_t _pad_0000B8; /* 0x0000B8 */ + u64 cp_ate_parity_err; /* 0x0000B0 */ + u64 _pad_0000B8; /* 0x0000B8 */ /* 0x0000C0-0x0000FF -- PCI/GIO */ - uint64_t cp_bus_timeout; /* 0x0000C0 */ - uint64_t cp_pci_cfg; /* 0x0000C8 */ - uint64_t cp_pci_err_upper; /* 0x0000D0 */ - uint64_t cp_pci_err_lower; /* 0x0000D8 */ + u64 cp_bus_timeout; /* 0x0000C0 */ + u64 cp_pci_cfg; /* 0x0000C8 */ + u64 cp_pci_err_upper; /* 0x0000D0 */ + u64 cp_pci_err_lower; /* 0x0000D8 */ #define cp_pci_err cp_pci_err_lower - uint64_t _pad_0000E0[4]; /* 0x0000{E0..F8} */ + u64 _pad_0000E0[4]; /* 0x0000{E0..F8} */ /* 0x000100-0x0001FF -- Interrupt */ - uint64_t cp_int_status; /* 0x000100 */ - uint64_t cp_int_enable; /* 0x000108 */ - uint64_t cp_int_rst_stat; /* 0x000110 */ - uint64_t cp_int_mode; /* 0x000118 */ - uint64_t cp_int_device; /* 0x000120 */ - uint64_t cp_int_host_err; /* 0x000128 */ - uint64_t cp_int_addr[8]; /* 0x0001{30,,,68} */ - uint64_t cp_err_int_view; /* 0x000170 */ - uint64_t cp_mult_int; /* 0x000178 */ - uint64_t cp_force_always[8]; /* 0x0001{80,,,B8} */ - uint64_t cp_force_pin[8]; /* 0x0001{C0,,,F8} */ + u64 cp_int_status; /* 0x000100 */ + u64 cp_int_enable; /* 0x000108 */ + u64 cp_int_rst_stat; /* 0x000110 */ + u64 cp_int_mode; /* 0x000118 */ + u64 cp_int_device; /* 0x000120 */ + u64 cp_int_host_err; /* 0x000128 */ + u64 cp_int_addr[8]; /* 0x0001{30,,,68} */ + u64 cp_err_int_view; /* 0x000170 */ + u64 cp_mult_int; /* 0x000178 */ + u64 cp_force_always[8]; /* 0x0001{80,,,B8} */ + u64 cp_force_pin[8]; /* 0x0001{C0,,,F8} */ /* 0x000200-0x000298 -- Device */ - uint64_t cp_device[4]; /* 0x0002{00,,,18} */ - uint64_t _pad_000220[4]; /* 0x0002{20,,,38} */ - uint64_t cp_wr_req_buf[4]; /* 0x0002{40,,,58} */ - uint64_t _pad_000260[4]; /* 0x0002{60,,,78} */ - uint64_t cp_rrb_map[2]; /* 0x0002{80,,,88} */ + u64 cp_device[4]; /* 0x0002{00,,,18} */ + u64 _pad_000220[4]; /* 0x0002{20,,,38} */ + u64 cp_wr_req_buf[4]; /* 0x0002{40,,,58} */ + u64 _pad_000260[4]; /* 0x0002{60,,,78} */ + u64 cp_rrb_map[2]; /* 0x0002{80,,,88} */ #define cp_even_resp cp_rrb_map[0] /* 0x000280 */ #define cp_odd_resp cp_rrb_map[1] /* 0x000288 */ - uint64_t cp_resp_status; /* 0x000290 */ - uint64_t cp_resp_clear; /* 0x000298 */ + u64 cp_resp_status; /* 0x000290 */ + u64 cp_resp_clear; /* 0x000298 */ - uint64_t _pad_0002A0[12]; /* 0x0002{A0..F8} */ + u64 _pad_0002A0[12]; /* 0x0002{A0..F8} */ /* 0x000300-0x0003F8 -- Buffer Address Match Registers */ struct { - uint64_t upper; /* 0x0003{00,,,F0} */ - uint64_t lower; /* 0x0003{08,,,F8} */ + u64 upper; /* 0x0003{00,,,F0} */ + u64 lower; /* 0x0003{08,,,F8} */ } cp_buf_addr_match[16]; /* 0x000400-0x0005FF -- Performance Monitor Registers (even only) */ struct { - uint64_t flush_w_touch; /* 0x000{400,,,5C0} */ - uint64_t flush_wo_touch; /* 0x000{408,,,5C8} */ - uint64_t inflight; /* 0x000{410,,,5D0} */ - uint64_t prefetch; /* 0x000{418,,,5D8} */ - uint64_t total_pci_retry; /* 0x000{420,,,5E0} */ - uint64_t max_pci_retry; /* 0x000{428,,,5E8} */ - uint64_t max_latency; /* 0x000{430,,,5F0} */ - uint64_t clear_all; /* 0x000{438,,,5F8} */ + u64 flush_w_touch; /* 0x000{400,,,5C0} */ + u64 flush_wo_touch; /* 0x000{408,,,5C8} */ + u64 inflight; /* 0x000{410,,,5D0} */ + u64 prefetch; /* 0x000{418,,,5D8} */ + u64 total_pci_retry; /* 0x000{420,,,5E0} */ + u64 max_pci_retry; /* 0x000{428,,,5E8} */ + u64 max_latency; /* 0x000{430,,,5F0} */ + u64 clear_all; /* 0x000{438,,,5F8} */ } cp_buf_count[8]; /* 0x000600-0x0009FF -- PCI/X registers */ - uint64_t cp_pcix_bus_err_addr; /* 0x000600 */ - uint64_t cp_pcix_bus_err_attr; /* 0x000608 */ - uint64_t cp_pcix_bus_err_data; /* 0x000610 */ - uint64_t cp_pcix_pio_split_addr; /* 0x000618 */ - uint64_t cp_pcix_pio_split_attr; /* 0x000620 */ - uint64_t cp_pcix_dma_req_err_attr; /* 0x000628 */ - uint64_t cp_pcix_dma_req_err_addr; /* 0x000630 */ - uint64_t cp_pcix_timeout; /* 0x000638 */ + u64 cp_pcix_bus_err_addr; /* 0x000600 */ + u64 cp_pcix_bus_err_attr; /* 0x000608 */ + u64 cp_pcix_bus_err_data; /* 0x000610 */ + u64 cp_pcix_pio_split_addr; /* 0x000618 */ + u64 cp_pcix_pio_split_attr; /* 0x000620 */ + u64 cp_pcix_dma_req_err_attr; /* 0x000628 */ + u64 cp_pcix_dma_req_err_addr; /* 0x000630 */ + u64 cp_pcix_timeout; /* 0x000638 */ - uint64_t _pad_000640[24]; /* 0x000{640,,,6F8} */ + u64 _pad_000640[24]; /* 0x000{640,,,6F8} */ /* 0x000700-0x000737 -- Debug Registers */ - uint64_t cp_ct_debug_ctl; /* 0x000700 */ - uint64_t cp_br_debug_ctl; /* 0x000708 */ - uint64_t cp_mux3_debug_ctl; /* 0x000710 */ - uint64_t cp_mux4_debug_ctl; /* 0x000718 */ - uint64_t cp_mux5_debug_ctl; /* 0x000720 */ - uint64_t cp_mux6_debug_ctl; /* 0x000728 */ - uint64_t cp_mux7_debug_ctl; /* 0x000730 */ + u64 cp_ct_debug_ctl; /* 0x000700 */ + u64 cp_br_debug_ctl; /* 0x000708 */ + u64 cp_mux3_debug_ctl; /* 0x000710 */ + u64 cp_mux4_debug_ctl; /* 0x000718 */ + u64 cp_mux5_debug_ctl; /* 0x000720 */ + u64 cp_mux6_debug_ctl; /* 0x000728 */ + u64 cp_mux7_debug_ctl; /* 0x000730 */ - uint64_t _pad_000738[89]; /* 0x000{738,,,9F8} */ + u64 _pad_000738[89]; /* 0x000{738,,,9F8} */ /* 0x000A00-0x000BFF -- PCI/X Read&Write Buffer */ struct { - uint64_t cp_buf_addr; /* 0x000{A00,,,AF0} */ - uint64_t cp_buf_attr; /* 0X000{A08,,,AF8} */ + u64 cp_buf_addr; /* 0x000{A00,,,AF0} */ + u64 cp_buf_attr; /* 0X000{A08,,,AF8} */ } cp_pcix_read_buf_64[16]; struct { - uint64_t cp_buf_addr; /* 0x000{B00,,,BE0} */ - uint64_t cp_buf_attr; /* 0x000{B08,,,BE8} */ - uint64_t cp_buf_valid; /* 0x000{B10,,,BF0} */ - uint64_t __pad1; /* 0x000{B18,,,BF8} */ + u64 cp_buf_addr; /* 0x000{B00,,,BE0} */ + u64 cp_buf_attr; /* 0x000{B08,,,BE8} */ + u64 cp_buf_valid; /* 0x000{B10,,,BF0} */ + u64 __pad1; /* 0x000{B18,,,BF8} */ } cp_pcix_write_buf_64[8]; /* End of Local Registers -- Start of Address Map space */ - char _pad_000c00[0x010000 - 0x000c00]; + char _pad_000c00[0x010000 - 0x000c00]; /* 0x010000-0x011FF8 -- Internal ATE RAM (Auto Parity Generation) */ - uint64_t cp_int_ate_ram[1024]; /* 0x010000-0x011FF8 */ + u64 cp_int_ate_ram[1024]; /* 0x010000-0x011FF8 */ - char _pad_012000[0x14000 - 0x012000]; + char _pad_012000[0x14000 - 0x012000]; /* 0x014000-0x015FF8 -- Internal ATE RAM (Manual Parity Generation) */ - uint64_t cp_int_ate_ram_mp[1024]; /* 0x014000-0x015FF8 */ + u64 cp_int_ate_ram_mp[1024]; /* 0x014000-0x015FF8 */ - char _pad_016000[0x18000 - 0x016000]; + char _pad_016000[0x18000 - 0x016000]; /* 0x18000-0x197F8 -- TIOCP Write Request Ram */ - uint64_t cp_wr_req_lower[256]; /* 0x18000 - 0x187F8 */ - uint64_t cp_wr_req_upper[256]; /* 0x18800 - 0x18FF8 */ - uint64_t cp_wr_req_parity[256]; /* 0x19000 - 0x197F8 */ + u64 cp_wr_req_lower[256]; /* 0x18000 - 0x187F8 */ + u64 cp_wr_req_upper[256]; /* 0x18800 - 0x18FF8 */ + u64 cp_wr_req_parity[256]; /* 0x19000 - 0x197F8 */ - char _pad_019800[0x1C000 - 0x019800]; + char _pad_019800[0x1C000 - 0x019800]; /* 0x1C000-0x1EFF8 -- TIOCP Read Response Ram */ - uint64_t cp_rd_resp_lower[512]; /* 0x1C000 - 0x1CFF8 */ - uint64_t cp_rd_resp_upper[512]; /* 0x1D000 - 0x1DFF8 */ - uint64_t cp_rd_resp_parity[512]; /* 0x1E000 - 0x1EFF8 */ + u64 cp_rd_resp_lower[512]; /* 0x1C000 - 0x1CFF8 */ + u64 cp_rd_resp_upper[512]; /* 0x1D000 - 0x1DFF8 */ + u64 cp_rd_resp_parity[512]; /* 0x1E000 - 0x1EFF8 */ - char _pad_01F000[0x20000 - 0x01F000]; + char _pad_01F000[0x20000 - 0x01F000]; /* 0x020000-0x021FFF -- Host Device (CP) Configuration Space (not used) */ - char _pad_020000[0x021000 - 0x20000]; + char _pad_020000[0x021000 - 0x20000]; /* 0x021000-0x027FFF -- PCI Device Configuration Spaces */ union { - uint8_t c[0x1000 / 1]; /* 0x02{0000,,,7FFF} */ - uint16_t s[0x1000 / 2]; /* 0x02{0000,,,7FFF} */ - uint32_t l[0x1000 / 4]; /* 0x02{0000,,,7FFF} */ - uint64_t d[0x1000 / 8]; /* 0x02{0000,,,7FFF} */ + u8 c[0x1000 / 1]; /* 0x02{0000,,,7FFF} */ + u16 s[0x1000 / 2]; /* 0x02{0000,,,7FFF} */ + u32 l[0x1000 / 4]; /* 0x02{0000,,,7FFF} */ + u64 d[0x1000 / 8]; /* 0x02{0000,,,7FFF} */ union { - uint8_t c[0x100 / 1]; - uint16_t s[0x100 / 2]; - uint32_t l[0x100 / 4]; - uint64_t d[0x100 / 8]; + u8 c[0x100 / 1]; + u16 s[0x100 / 2]; + u32 l[0x100 / 4]; + u64 d[0x100 / 8]; } f[8]; } cp_type0_cfg_dev[7]; /* 0x02{1000,,,7FFF} */ /* 0x028000-0x028FFF -- PCI Type 1 Configuration Space */ union { - uint8_t c[0x1000 / 1]; /* 0x028000-0x029000 */ - uint16_t s[0x1000 / 2]; /* 0x028000-0x029000 */ - uint32_t l[0x1000 / 4]; /* 0x028000-0x029000 */ - uint64_t d[0x1000 / 8]; /* 0x028000-0x029000 */ + u8 c[0x1000 / 1]; /* 0x028000-0x029000 */ + u16 s[0x1000 / 2]; /* 0x028000-0x029000 */ + u32 l[0x1000 / 4]; /* 0x028000-0x029000 */ + u64 d[0x1000 / 8]; /* 0x028000-0x029000 */ union { - uint8_t c[0x100 / 1]; - uint16_t s[0x100 / 2]; - uint32_t l[0x100 / 4]; - uint64_t d[0x100 / 8]; + u8 c[0x100 / 1]; + u16 s[0x100 / 2]; + u32 l[0x100 / 4]; + u64 d[0x100 / 8]; } f[8]; } cp_type1_cfg; /* 0x028000-0x029000 */ @@ -211,30 +211,30 @@ struct tiocp{ /* 0x030000-0x030007 -- PCI Interrupt Acknowledge Cycle */ union { - uint8_t c[8 / 1]; - uint16_t s[8 / 2]; - uint32_t l[8 / 4]; - uint64_t d[8 / 8]; + u8 c[8 / 1]; + u16 s[8 / 2]; + u32 l[8 / 4]; + u64 d[8 / 8]; } cp_pci_iack; /* 0x030000-0x030007 */ char _pad_030007[0x040000-0x030008]; /* 0x040000-0x040007 -- PCIX Special Cycle */ union { - uint8_t c[8 / 1]; - uint16_t s[8 / 2]; - uint32_t l[8 / 4]; - uint64_t d[8 / 8]; + u8 c[8 / 1]; + u16 s[8 / 2]; + u32 l[8 / 4]; + u64 d[8 / 8]; } cp_pcix_cycle; /* 0x040000-0x040007 */ char _pad_040007[0x200000-0x040008]; /* 0x200000-0x7FFFFF -- PCI/GIO Device Spaces */ union { - uint8_t c[0x100000 / 1]; - uint16_t s[0x100000 / 2]; - uint32_t l[0x100000 / 4]; - uint64_t d[0x100000 / 8]; + u8 c[0x100000 / 1]; + u16 s[0x100000 / 2]; + u32 l[0x100000 / 4]; + u64 d[0x100000 / 8]; } cp_devio_raw[6]; /* 0x200000-0x7FFFFF */ #define cp_devio(n) cp_devio_raw[((n)<2)?(n*2):(n+2)] @@ -243,10 +243,10 @@ struct tiocp{ /* 0xA00000-0xBFFFFF -- PCI/GIO Device Spaces w/flush */ union { - uint8_t c[0x100000 / 1]; - uint16_t s[0x100000 / 2]; - uint32_t l[0x100000 / 4]; - uint64_t d[0x100000 / 8]; + u8 c[0x100000 / 1]; + u16 s[0x100000 / 2]; + u32 l[0x100000 / 4]; + u64 d[0x100000 / 8]; } cp_devio_raw_flush[6]; /* 0xA00000-0xBFFFFF */ #define cp_devio_flush(n) cp_devio_raw_flush[((n)<2)?(n*2):(n+2)] diff --git a/include/asm-ia64/sn/tiocx.h b/include/asm-ia64/sn/tiocx.h index 5699e75e502..d29728492f3 100644 --- a/include/asm-ia64/sn/tiocx.h +++ b/include/asm-ia64/sn/tiocx.h @@ -40,10 +40,10 @@ struct cx_drv { }; /* create DMA address by stripping AS bits */ -#define TIOCX_DMA_ADDR(a) (uint64_t)((uint64_t)(a) & 0xffffcfffffffffUL) +#define TIOCX_DMA_ADDR(a) (u64)((u64)(a) & 0xffffcfffffffffUL) -#define TIOCX_TO_TIOCX_DMA_ADDR(a) (uint64_t)(((uint64_t)(a) & 0xfffffffff) | \ - ((((uint64_t)(a)) & 0xffffc000000000UL) <<2)) +#define TIOCX_TO_TIOCX_DMA_ADDR(a) (u64)(((u64)(a) & 0xfffffffff) | \ + ((((u64)(a)) & 0xffffc000000000UL) <<2)) #define TIO_CE_ASIC_PARTNUM 0xce00 #define TIOCX_CORELET 3 @@ -63,10 +63,10 @@ extern int cx_device_unregister(struct cx_dev *); extern int cx_device_register(nasid_t, int, int, struct hubdev_info *, int); extern int cx_driver_unregister(struct cx_drv *); extern int cx_driver_register(struct cx_drv *); -extern uint64_t tiocx_dma_addr(uint64_t addr); -extern uint64_t tiocx_swin_base(int nasid); -extern void tiocx_mmr_store(int nasid, uint64_t offset, uint64_t value); -extern uint64_t tiocx_mmr_load(int nasid, uint64_t offset); +extern u64 tiocx_dma_addr(u64 addr); +extern u64 tiocx_swin_base(int nasid); +extern void tiocx_mmr_store(int nasid, u64 offset, u64 value); +extern u64 tiocx_mmr_load(int nasid, u64 offset); #endif // __KERNEL__ #endif // _ASM_IA64_SN_TIO_TIOCX__ -- GitLab From 1f35f432b9d116f5be4c428d71d39ed9b7d6ff50 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 17 Jan 2006 00:23:49 +0100 Subject: [PATCH 362/465] [PATCH] Fix drivers/block/ps2esdi.c compile Looks like fallout from the geo stuff. --- drivers/block/ps2esdi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c index 43415f69839..bea75f2cb21 100644 --- a/drivers/block/ps2esdi.c +++ b/drivers/block/ps2esdi.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include -- GitLab From 8dca6f33f026dc8a7fc2710b78a7521e899bd611 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Mon, 16 Jan 2006 15:58:55 -0700 Subject: [PATCH 363/465] [PATCH] hrtimer comment tweak Fix a comment which missed an update cycle somewhere. Signed-off-by: Jonathan Corbet Signed-off-by: Linus Torvalds --- kernel/hrtimer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 04ccab099e8..f5ca6142233 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -272,7 +272,7 @@ void unlock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags) * @interval: the interval to forward * * Forward the timer expiry so it will expire in the future. - * The number of overruns is added to the overrun field. + * Returns the number of overruns. */ unsigned long hrtimer_forward(struct hrtimer *timer, ktime_t interval) -- GitLab From 6aa4c0ef388201745adadfc7855b8a871f0e6122 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 16 Jan 2006 22:13:53 -0800 Subject: [PATCH 364/465] [PATCH] i386: remove gcc version check for CONFIG_REGPARM Since we do no longer support any gcc < 3.0, there's no need to check for it.. Signed-off-by: Adrian Bunk Cc: Sam Ravnborg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/Makefile | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/arch/i386/Makefile b/arch/i386/Makefile index bd2d53a9dd2..36bef6543ac 100644 --- a/arch/i386/Makefile +++ b/arch/i386/Makefile @@ -37,10 +37,7 @@ CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2) # CPU-specific tuning. Anything which can be shared with UML should go here. include $(srctree)/arch/i386/Makefile.cpu -# -mregparm=3 works ok on gcc-3.0 and later -# -cflags-$(CONFIG_REGPARM) += $(shell if [ $(call cc-version) -ge 0300 ] ; then \ - echo "-mregparm=3"; fi ;) +cflags-$(CONFIG_REGPARM) += -mregparm=3 # Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use # a lot more stack due to the lack of sharing of stacklots: -- GitLab From 96419b7c4d996d9f12ca9f7189f316ed2938074a Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 16 Jan 2006 22:13:55 -0800 Subject: [PATCH 365/465] [PATCH] fix arm26 THREAD_SIZE arm26 currently has a 256 kB THREAD_SIZE (sic). Looking at the comment in the code, this seems to be based on a misunderstanding. The comment says: this needs attention (see kernel/fork.c which gets a nice div by zero if this is lower than 8*32768 kernel/fork.c does: max_threads = mempages / (8 * THREAD_SIZE / PAGE_SIZE) Therefore, a division by 0 is impossible for all reasonable cases with THREAD_SIZE >= PAGE_SIZE. Since the minimum PAGE_SIZE Linux uses on the arm26 architecture is 16k, PAGE_SIZE should be sufficient for THREAD_SIZE. Signed-off-by: Adrian Bunk Signed-off-by: Ian Molton Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-arm26/thread_info.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/asm-arm26/thread_info.h b/include/asm-arm26/thread_info.h index a65e58a0a76..9b367ebe515 100644 --- a/include/asm-arm26/thread_info.h +++ b/include/asm-arm26/thread_info.h @@ -80,8 +80,7 @@ static inline struct thread_info *current_thread_info(void) return (struct thread_info *)(sp & ~0x1fff); } -/* FIXME - PAGE_SIZE < 32K */ -#define THREAD_SIZE (8*32768) // FIXME - this needs attention (see kernel/fork.c which gets a nice div by zero if this is lower than 8*32768 +#define THREAD_SIZE PAGE_SIZE #define task_pt_regs(task) ((struct pt_regs *)(task_stack_page(task) + THREAD_SIZE - 8) - 1) extern struct thread_info *alloc_thread_info(struct task_struct *task); -- GitLab From 511c3a2beefbb7d263063f2fef48615fba2d7255 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 16 Jan 2006 22:13:56 -0800 Subject: [PATCH 366/465] [PATCH] arm26: add L1_CACHE_SHIFT Fix reiserfs compilation as a side effect =) Signed-off-by: Alexey Dobriyan Acked-by: Ian Molton Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-arm26/cache.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/asm-arm26/cache.h b/include/asm-arm26/cache.h index f52ca1b808c..8c3abcf728f 100644 --- a/include/asm-arm26/cache.h +++ b/include/asm-arm26/cache.h @@ -4,7 +4,8 @@ #ifndef __ASMARM_CACHE_H #define __ASMARM_CACHE_H -#define L1_CACHE_BYTES 32 +#define L1_CACHE_SHIFT 5 +#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) #define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1)) #define SMP_CACHE_BYTES L1_CACHE_BYTES -- GitLab From 3868cca523e20a2600f6a9b1feebb69a6c8ccb68 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 16 Jan 2006 22:13:57 -0800 Subject: [PATCH 367/465] [PATCH] arm26: kernel/irq.c: fix compilation It's trying to "continue;" in "if" statement. Signed-off-by: Alexey Dobriyan Acked-by: Ian Molton Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm26/kernel/irq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm26/kernel/irq.c b/arch/arm26/kernel/irq.c index f3cc1036e5b..0934e6fba60 100644 --- a/arch/arm26/kernel/irq.c +++ b/arch/arm26/kernel/irq.c @@ -141,7 +141,7 @@ int show_interrupts(struct seq_file *p, void *v) if (i < NR_IRQS) { action = irq_desc[i].action; if (!action) - continue; + goto out; seq_printf(p, "%3d: %10u ", i, kstat_irqs(i)); seq_printf(p, " %s", action->name); for (action = action->next; action; action = action->next) { @@ -152,6 +152,7 @@ int show_interrupts(struct seq_file *p, void *v) show_fiq_list(p, v); seq_printf(p, "Err: %10lu\n", irq_err_count); } +out: return 0; } -- GitLab From 3001aa826ea6a4de12b437188c2a095991d2d142 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 16 Jan 2006 22:13:58 -0800 Subject: [PATCH 368/465] [PATCH] no longer mark MTD_OBSOLETE_CHIPS as BROKEN This patch removes the wrong dependency of MTD_OBSOLETE_CHIPS on BROKEN and marks the non-compiling MTD_AMDSTD and MTD_JEDEC drivers as BROKEN. Signed-off-by: Adrian Bunk Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/chips/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig index eafa23f5cbd..25f8217a671 100644 --- a/drivers/mtd/chips/Kconfig +++ b/drivers/mtd/chips/Kconfig @@ -259,7 +259,7 @@ config MTD_ABSENT with this driver will return -ENODEV upon access. config MTD_OBSOLETE_CHIPS - depends on MTD && BROKEN + depends on MTD bool "Older (theoretically obsoleted now) drivers for non-CFI chips" help This option does not enable any code directly, but will allow you to @@ -272,7 +272,7 @@ config MTD_OBSOLETE_CHIPS config MTD_AMDSTD tristate "AMD compatible flash chip support (non-CFI)" - depends on MTD && MTD_OBSOLETE_CHIPS + depends on MTD && MTD_OBSOLETE_CHIPS && BROKEN help This option enables support for flash chips using AMD-compatible commands, including some which are not CFI-compatible and hence @@ -290,7 +290,7 @@ config MTD_SHARP config MTD_JEDEC tristate "JEDEC device support" - depends on MTD && MTD_OBSOLETE_CHIPS + depends on MTD && MTD_OBSOLETE_CHIPS && BROKEN help Enable older older JEDEC flash interface devices for self programming flash. It is commonly used in older AMD chips. It is -- GitLab From fd279197b1df6b46076991ca0e1f7faa8f3d8028 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 16 Jan 2006 22:13:59 -0800 Subject: [PATCH 369/465] [PATCH] build kernel/intermodule.c only when required Build kernel/intermodule.c only when required. Signed-off-by: Adrian Bunk Cc: Sam Ravnborg Cc: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/chips/Kconfig | 1 + drivers/mtd/devices/Kconfig | 1 + init/Kconfig | 3 +++ kernel/Makefile | 3 ++- 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig index 25f8217a671..effa0d7a73a 100644 --- a/drivers/mtd/chips/Kconfig +++ b/drivers/mtd/chips/Kconfig @@ -31,6 +31,7 @@ config MTD_JEDECPROBE config MTD_GEN_PROBE tristate + select OBSOLETE_INTERMODULE config MTD_CFI_ADV_OPTIONS bool "Flash chip driver advanced configuration options" diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index 5038e90ceb1..dd628cb51e3 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig @@ -218,6 +218,7 @@ config MTD_DOC2001PLUS config MTD_DOCPROBE tristate select MTD_DOCECC + select OBSOLETE_INTERMODULE config MTD_DOCECC tristate diff --git a/init/Kconfig b/init/Kconfig index 7efa729d2cf..b9923b1434a 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -427,6 +427,9 @@ config SLOB default !SLAB bool +config OBSOLETE_INTERMODULE + tristate + menu "Loadable module support" config MODULES diff --git a/kernel/Makefile b/kernel/Makefile index 355126606d1..4ae0fbde815 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -6,7 +6,7 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \ exit.o itimer.o time.o softirq.o resource.o \ sysctl.o capability.o ptrace.o timer.o user.o \ signal.o sys.o kmod.o workqueue.o pid.o \ - rcupdate.o intermodule.o extable.o params.o posix-timers.o \ + rcupdate.o extable.o params.o posix-timers.o \ kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ hrtimer.o @@ -17,6 +17,7 @@ obj-$(CONFIG_SMP) += cpu.o spinlock.o obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o obj-$(CONFIG_UID16) += uid16.o obj-$(CONFIG_MODULES) += module.o +obj-$(CONFIG_OBSOLETE_INTERMODULE) += intermodule.o obj-$(CONFIG_KALLSYMS) += kallsyms.o obj-$(CONFIG_PM) += power/ obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o -- GitLab From 8f56a31ad616b13414cf764f620f75f45dac26e6 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 16 Jan 2006 22:14:00 -0800 Subject: [PATCH 370/465] [PATCH] drivers/char/esp.c spinlock fix There's incorrect spinlock usage in espserial_init(): autoconfig() uses info->lock before it's initialized. The fix is to initialize the spinlock earlier. Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/esp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/esp.c b/drivers/char/esp.c index dd5dc8fa490..3f3ac039f4d 100644 --- a/drivers/char/esp.c +++ b/drivers/char/esp.c @@ -2492,6 +2492,7 @@ static int __init espserial_init(void) } memset((void *)info, 0, sizeof(struct esp_struct)); + spin_lock_init(&info->lock); /* rx_trigger, tx_trigger are needed by autoconfig */ info->config.rx_trigger = rx_trigger; info->config.tx_trigger = tx_trigger; @@ -2528,7 +2529,6 @@ static int __init espserial_init(void) init_waitqueue_head(&info->close_wait); init_waitqueue_head(&info->delta_msr_wait); init_waitqueue_head(&info->break_wait); - spin_lock_init(&info->lock); ports = info; printk(KERN_INFO "ttyP%d at 0x%04x (irq = %d) is an ESP ", info->line, info->port, info->irq); -- GitLab From b142159fa5ffbad73b6927fafa5440148030f3f1 Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Mon, 16 Jan 2006 22:14:01 -0800 Subject: [PATCH 371/465] [PATCH] mips: add pm_power_off Adds pm_power_off() to MIPS. Signed-off-by: Yoichi Yuasa Cc: Ralf Baechle Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/mips/kernel/reset.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/mips/kernel/reset.c b/arch/mips/kernel/reset.c index ae2ba67b7ef..5e37df3111a 100644 --- a/arch/mips/kernel/reset.c +++ b/arch/mips/kernel/reset.c @@ -12,6 +12,9 @@ #include #include +void (*pm_power_off)(void); +EXPORT_SYMBOL(pm_power_off); + /* * Urgs ... Too many MIPS machines to handle this in a generic way. * So handle all using function pointers to machine specific @@ -33,6 +36,9 @@ void machine_halt(void) void machine_power_off(void) { + if (pm_power_off) + pm_power_off(); + _machine_power_off(); } -- GitLab From f63776d0dccb6eb5f38beeac3eb9db735f7b5879 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 16 Jan 2006 22:14:05 -0800 Subject: [PATCH 372/465] [PATCH] arm26: s/task_threas_info/task_thread_info/ Signed-off-by: Alexey Dobriyan Signed-off-by: Ian Molton Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm26/kernel/ptrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm26/kernel/ptrace.c b/arch/arm26/kernel/ptrace.c index 3c3371d4683..282e24d7932 100644 --- a/arch/arm26/kernel/ptrace.c +++ b/arch/arm26/kernel/ptrace.c @@ -527,7 +527,7 @@ static int ptrace_getfpregs(struct task_struct *tsk, void *ufp) static int ptrace_setfpregs(struct task_struct *tsk, void *ufp) { set_stopped_child_used_math(tsk); - return copy_from_user(&task_threas_info(tsk)->fpstate, ufp, + return copy_from_user(&task_thread_info(tsk)->fpstate, ufp, sizeof(struct user_fp)) ? -EFAULT : 0; } -- GitLab From 5ebdce726baf17eb66c5a1bf402ae6f161a082ed Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 16 Jan 2006 22:14:06 -0800 Subject: [PATCH 373/465] [PATCH] fix up sbuslib for new fb_comapt_ioctl prototype After ages my fb ioctl prototype cleanup finally got in. Unfortunately the patch are so old that the sbus compat_ioctl helper didn't exist back then, so it's not covered. This patch should fix that issue. Signed-off-by: Christoph Hellwig Cc: "David S. Miller" Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/sbuslib.c | 20 +++++++++----------- drivers/video/sbuslib.h | 4 ++-- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/video/sbuslib.c b/drivers/video/sbuslib.c index 3a74a63dd4f..55e6e2d60d3 100644 --- a/drivers/video/sbuslib.c +++ b/drivers/video/sbuslib.c @@ -216,10 +216,10 @@ static int fbiogetputcmap(struct file *file, struct fb_info *info, ret |= put_user(compat_ptr(addr), &p->blue); if (ret) return -EFAULT; - return info->fbops->fb_ioctl(file->f_dentry->d_inode, file, + return info->fbops->fb_ioctl(info, (cmd == FBIOPUTCMAP32) ? FBIOPUTCMAP_SPARC : FBIOGETCMAP_SPARC, - (unsigned long)p, info); + (unsigned long)p); } struct fbcursor32 { @@ -260,12 +260,11 @@ static int fbiogscursor(struct file *file, struct fb_info *info, ret |= put_user(compat_ptr(addr), &p->image); if (ret) return -EFAULT; - return info->fbops->fb_ioctl(file->f_dentry->d_inode, file, - FBIOSCURSOR, (unsigned long)p, info); + return info->fbops->fb_ioctl(info, FBIOSCURSOR, (unsigned long)p); } -long sbusfb_compat_ioctl(struct file *file, unsigned int cmd, - unsigned long arg, struct fb_info *info) +long sbusfb_compat_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg) { switch (cmd) { case FBIOGTYPE: @@ -278,14 +277,13 @@ long sbusfb_compat_ioctl(struct file *file, unsigned int cmd, case FBIOSCURPOS: case FBIOGCURPOS: case FBIOGCURMAX: - return info->fbops->fb_ioctl(file->f_dentry->d_inode, - file, cmd, arg, info); + return info->fbops->fb_ioctl(info, cmd, arg); case FBIOPUTCMAP32: - return fbiogetputcmap(file, info, cmd, arg); + return fbiogetputcmap(info, cmd, arg); case FBIOGETCMAP32: - return fbiogetputcmap(file, info, cmd, arg); + return fbiogetputcmap(info, cmd, arg); case FBIOSCURSOR32: - return fbiogscursor(file, info, arg); + return fbiogscursor(info, arg); default: return -ENOIOCTLCMD; } diff --git a/drivers/video/sbuslib.h b/drivers/video/sbuslib.h index b470e52ce9e..f753939013e 100644 --- a/drivers/video/sbuslib.h +++ b/drivers/video/sbuslib.h @@ -20,7 +20,7 @@ extern int sbusfb_mmap_helper(struct sbus_mmap_map *map, int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg, struct fb_info *info, int type, int fb_depth, unsigned long fb_size); -long sbusfb_compat_ioctl(struct file *file, unsigned int cmd, - unsigned long arg, struct fb_info *info); +long sbusfb_compat_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg); #endif /* _SBUSLIB_H */ -- GitLab From 0025835cf20e07056b8521b8c1d7d0bfe07e81f1 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 16 Jan 2006 22:14:08 -0800 Subject: [PATCH 374/465] [PATCH] sh: consolidate hp620/hp680/hp690 targets into hp6xx Most of the reasons for keeping these separate before was due to hp690 discontig, and since we have a workaround for that now (abusing some shadow space so everything is magically contiguous), there's no reason to keep the targets separate. Signed-off-by: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/sh/boards/hp6xx/Makefile | 6 + arch/sh/boards/hp6xx/hp620/Makefile | 6 - arch/sh/boards/hp6xx/hp620/mach.c | 52 --- arch/sh/boards/hp6xx/hp620/setup.c | 45 --- arch/sh/boards/hp6xx/hp680/Makefile | 6 - arch/sh/boards/hp6xx/hp690/Makefile | 6 - arch/sh/boards/hp6xx/hp690/mach.c | 48 --- arch/sh/boards/hp6xx/{hp680 => }/mach.c | 15 +- arch/sh/boards/hp6xx/{hp680 => }/setup.c | 18 +- .../{hp680_defconfig => hp6xx_defconfig} | 333 ++++++++++++++---- arch/sh/tools/mach-types | 5 +- drivers/input/touchscreen/Kconfig | 2 +- 12 files changed, 289 insertions(+), 253 deletions(-) create mode 100644 arch/sh/boards/hp6xx/Makefile delete mode 100644 arch/sh/boards/hp6xx/hp620/Makefile delete mode 100644 arch/sh/boards/hp6xx/hp620/mach.c delete mode 100644 arch/sh/boards/hp6xx/hp620/setup.c delete mode 100644 arch/sh/boards/hp6xx/hp680/Makefile delete mode 100644 arch/sh/boards/hp6xx/hp690/Makefile delete mode 100644 arch/sh/boards/hp6xx/hp690/mach.c rename arch/sh/boards/hp6xx/{hp680 => }/mach.c (79%) rename arch/sh/boards/hp6xx/{hp680 => }/setup.c (70%) rename arch/sh/configs/{hp680_defconfig => hp6xx_defconfig} (63%) diff --git a/arch/sh/boards/hp6xx/Makefile b/arch/sh/boards/hp6xx/Makefile new file mode 100644 index 00000000000..927fe0aa5df --- /dev/null +++ b/arch/sh/boards/hp6xx/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for the HP6xx specific parts of the kernel +# + +obj-y := mach.o setup.o + diff --git a/arch/sh/boards/hp6xx/hp620/Makefile b/arch/sh/boards/hp6xx/hp620/Makefile deleted file mode 100644 index 20691dbce34..00000000000 --- a/arch/sh/boards/hp6xx/hp620/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# -# Makefile for the HP620 specific parts of the kernel -# - -obj-y := mach.o setup.o - diff --git a/arch/sh/boards/hp6xx/hp620/mach.c b/arch/sh/boards/hp6xx/hp620/mach.c deleted file mode 100644 index 0392d82b4a7..00000000000 --- a/arch/sh/boards/hp6xx/hp620/mach.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * linux/arch/sh/boards/hp6xx/hp620/mach.c - * - * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Machine vector for the HP620 - */ - -#include - -#include -#include -#include - -#include -#include -#include - -/* - * The Machine Vector - */ - -struct sh_machine_vector mv_hp620 __initmv = { - .mv_nr_irqs = HD64461_IRQBASE+HD64461_IRQ_NUM, - - .mv_inb = hd64461_inb, - .mv_inw = hd64461_inw, - .mv_inl = hd64461_inl, - .mv_outb = hd64461_outb, - .mv_outw = hd64461_outw, - .mv_outl = hd64461_outl, - - .mv_inb_p = hd64461_inb_p, - .mv_inw_p = hd64461_inw, - .mv_inl_p = hd64461_inl, - .mv_outb_p = hd64461_outb_p, - .mv_outw_p = hd64461_outw, - .mv_outl_p = hd64461_outl, - - .mv_insb = hd64461_insb, - .mv_insw = hd64461_insw, - .mv_insl = hd64461_insl, - .mv_outsb = hd64461_outsb, - .mv_outsw = hd64461_outsw, - .mv_outsl = hd64461_outsl, - - .mv_irq_demux = hd64461_irq_demux, -}; -ALIAS_MV(hp620) diff --git a/arch/sh/boards/hp6xx/hp620/setup.c b/arch/sh/boards/hp6xx/hp620/setup.c deleted file mode 100644 index 045fc5da727..00000000000 --- a/arch/sh/boards/hp6xx/hp620/setup.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * linux/arch/sh/boards/hp6xx/hp620/setup.c - * - * Copyright (C) 2002 Andriy Skulysh, 2005 Kristoffer Ericson - * - * May be copied or modified under the terms of the GNU General Public - * License. See Linux/COPYING for more information. - * - * Setup code for an HP620. - * Due to similiarity with hp680/hp690 same inits are done (for now) - */ - -#include -#include -#include -#include -#include -#include - -const char *get_system_type(void) -{ - return "HP620"; -} - -int __init platform_setup(void) -{ - u16 v; - - v = inw(HD64461_STBCR); - v |= HD64461_STBCR_SURTST | HD64461_STBCR_SIRST | - HD64461_STBCR_STM1ST | HD64461_STBCR_STM0ST | - HD64461_STBCR_SAFEST | HD64461_STBCR_SPC0ST | - HD64461_STBCR_SMIAST | HD64461_STBCR_SAFECKE_OST | - HD64461_STBCR_SAFECKE_IST; - outw(v, HD64461_STBCR); - - v = inw(HD64461_GPADR); - v |= HD64461_GPADR_SPEAKER | HD64461_GPADR_PCMCIA0; - outw(v, HD64461_GPADR); - - sh_dac_disable(DAC_SPEAKER_VOLUME); - - return 0; -} - diff --git a/arch/sh/boards/hp6xx/hp680/Makefile b/arch/sh/boards/hp6xx/hp680/Makefile deleted file mode 100644 index 0beef11d9b1..00000000000 --- a/arch/sh/boards/hp6xx/hp680/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# -# Makefile for the HP680 specific parts of the kernel -# - -obj-y := mach.o setup.o - diff --git a/arch/sh/boards/hp6xx/hp690/Makefile b/arch/sh/boards/hp6xx/hp690/Makefile deleted file mode 100644 index fbbe95e75f8..00000000000 --- a/arch/sh/boards/hp6xx/hp690/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# -# Makefile for the HP690 specific parts of the kernel -# - -obj-y := mach.o - diff --git a/arch/sh/boards/hp6xx/hp690/mach.c b/arch/sh/boards/hp6xx/hp690/mach.c deleted file mode 100644 index 2a4c68783cd..00000000000 --- a/arch/sh/boards/hp6xx/hp690/mach.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * linux/arch/sh/boards/hp6xx/hp690/mach.c - * - * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Machine vector for the HP690 - */ - -#include - -#include -#include -#include - -#include -#include -#include - -struct sh_machine_vector mv_hp690 __initmv = { - .mv_nr_irqs = HD64461_IRQBASE+HD64461_IRQ_NUM, - - .mv_inb = hd64461_inb, - .mv_inw = hd64461_inw, - .mv_inl = hd64461_inl, - .mv_outb = hd64461_outb, - .mv_outw = hd64461_outw, - .mv_outl = hd64461_outl, - - .mv_inb_p = hd64461_inb_p, - .mv_inw_p = hd64461_inw, - .mv_inl_p = hd64461_inl, - .mv_outb_p = hd64461_outb_p, - .mv_outw_p = hd64461_outw, - .mv_outl_p = hd64461_outl, - - .mv_insb = hd64461_insb, - .mv_insw = hd64461_insw, - .mv_insl = hd64461_insl, - .mv_outsb = hd64461_outsb, - .mv_outsw = hd64461_outsw, - .mv_outsl = hd64461_outsl, - - .mv_irq_demux = hd64461_irq_demux, -}; -ALIAS_MV(hp690) diff --git a/arch/sh/boards/hp6xx/hp680/mach.c b/arch/sh/boards/hp6xx/mach.c similarity index 79% rename from arch/sh/boards/hp6xx/hp680/mach.c rename to arch/sh/boards/hp6xx/mach.c index d7348613604..08dbba910f7 100644 --- a/arch/sh/boards/hp6xx/hp680/mach.c +++ b/arch/sh/boards/hp6xx/mach.c @@ -1,5 +1,5 @@ /* - * linux/arch/sh/boards/hp6xx/hp680/mach.c + * linux/arch/sh/boards/hp6xx/mach.c * * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) * @@ -8,19 +8,12 @@ * * Machine vector for the HP680 */ - -#include - #include -#include -#include - +#include #include -#include -#include #include -struct sh_machine_vector mv_hp680 __initmv = { +struct sh_machine_vector mv_hp6xx __initmv = { .mv_nr_irqs = HD64461_IRQBASE + HD64461_IRQ_NUM, .mv_inb = hd64461_inb, @@ -50,4 +43,4 @@ struct sh_machine_vector mv_hp680 __initmv = { .mv_irq_demux = hd64461_irq_demux, }; -ALIAS_MV(hp680) +ALIAS_MV(hp6xx) diff --git a/arch/sh/boards/hp6xx/hp680/setup.c b/arch/sh/boards/hp6xx/setup.c similarity index 70% rename from arch/sh/boards/hp6xx/hp680/setup.c rename to arch/sh/boards/hp6xx/setup.c index 4170190f264..6d94a8e2e67 100644 --- a/arch/sh/boards/hp6xx/hp680/setup.c +++ b/arch/sh/boards/hp6xx/setup.c @@ -11,18 +11,19 @@ #include #include -#include #include +#include #include #include const char *get_system_type(void) { - return "HP680"; + return "HP6xx"; } int __init platform_setup(void) { + u8 v8; u16 v; v = inw(HD64461_STBCR); v |= HD64461_STBCR_SURTST | HD64461_STBCR_SIRST | @@ -30,12 +31,25 @@ int __init platform_setup(void) HD64461_STBCR_SAFEST | HD64461_STBCR_SPC0ST | HD64461_STBCR_SMIAST | HD64461_STBCR_SAFECKE_OST | HD64461_STBCR_SAFECKE_IST; +#ifndef CONFIG_HD64461_ENABLER + v |= HD64461_STBCR_SPC1ST; +#endif outw(v, HD64461_STBCR); v = inw(HD64461_GPADR); v |= HD64461_GPADR_SPEAKER | HD64461_GPADR_PCMCIA0; outw(v, HD64461_GPADR); + outw(HD64461_PCCGCR_VCC0 | HD64461_PCCSCR_VCC1, HD64461_PCC0GCR); + +#ifndef CONFIG_HD64461_ENABLER + outw(HD64461_PCCGCR_VCC0 | HD64461_PCCSCR_VCC1, HD64461_PCC1GCR); +#endif + + sh_dac_output(0, DAC_SPEAKER_VOLUME); sh_dac_disable(DAC_SPEAKER_VOLUME); + v8 = ctrl_inb(DACR); + v8 &= ~DACR_DAE; + ctrl_outb(v8,DACR); return 0; } diff --git a/arch/sh/configs/hp680_defconfig b/arch/sh/configs/hp6xx_defconfig similarity index 63% rename from arch/sh/configs/hp680_defconfig rename to arch/sh/configs/hp6xx_defconfig index c85d3655b53..b36f102cec8 100644 --- a/arch/sh/configs/hp680_defconfig +++ b/arch/sh/configs/hp6xx_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.11-sh -# Wed Mar 2 15:09:41 2005 +# Linux kernel version: 2.6.15-sh +# Wed Jan 4 15:32:56 2006 # CONFIG_SUPERH=y CONFIG_UID16=y @@ -17,37 +17,60 @@ CONFIG_EXPERIMENTAL=y # CONFIG_CLEAN_COMPILE is not set CONFIG_BROKEN=y CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 # # General setup # CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y # CONFIG_SYSVIPC is not set # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_SYSCTL is not set -# CONFIG_AUDIT is not set -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_HOTPLUG is not set +CONFIG_HOTPLUG=y # CONFIG_IKCONFIG is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SHMEM=y CONFIG_CC_ALIGN_FUNCTIONS=0 CONFIG_CC_ALIGN_LABELS=0 CONFIG_CC_ALIGN_LOOPS=0 CONFIG_CC_ALIGN_JUMPS=0 # CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 # # Loadable module support # # CONFIG_MODULES is not set +# +# Block layer +# +# CONFIG_LBD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + # # System type # @@ -58,9 +81,7 @@ CONFIG_CC_ALIGN_JUMPS=0 # CONFIG_SH_7751_SYSTEMH is not set # CONFIG_SH_STB1_HARP is not set # CONFIG_SH_STB1_OVERDRIVE is not set -# CONFIG_SH_HP620 is not set -CONFIG_SH_HP680=y -# CONFIG_SH_HP690 is not set +CONFIG_SH_HP6XX=y # CONFIG_SH_CQREEK is not set # CONFIG_SH_DMIDA is not set # CONFIG_SH_EC3104 is not set @@ -77,43 +98,90 @@ CONFIG_SH_HP680=y # CONFIG_SH_RTS7751R2D is not set # CONFIG_SH_EDOSK7705 is not set # CONFIG_SH_SH4202_MICRODEV is not set +# CONFIG_SH_LANDISK is not set +# CONFIG_SH_TITAN is not set # CONFIG_SH_UNKNOWN is not set -# CONFIG_CPU_SH2 is not set + +# +# Processor selection +# CONFIG_CPU_SH3=y -# CONFIG_CPU_SH4 is not set + +# +# SH-2 Processor Support +# # CONFIG_CPU_SUBTYPE_SH7604 is not set + +# +# SH-3 Processor Support +# # CONFIG_CPU_SUBTYPE_SH7300 is not set # CONFIG_CPU_SUBTYPE_SH7705 is not set # CONFIG_CPU_SUBTYPE_SH7707 is not set # CONFIG_CPU_SUBTYPE_SH7708 is not set CONFIG_CPU_SUBTYPE_SH7709=y + +# +# SH-4 Processor Support +# # CONFIG_CPU_SUBTYPE_SH7750 is not set +# CONFIG_CPU_SUBTYPE_SH7091 is not set +# CONFIG_CPU_SUBTYPE_SH7750R is not set +# CONFIG_CPU_SUBTYPE_SH7750S is not set # CONFIG_CPU_SUBTYPE_SH7751 is not set +# CONFIG_CPU_SUBTYPE_SH7751R is not set # CONFIG_CPU_SUBTYPE_SH7760 is not set -# CONFIG_CPU_SUBTYPE_SH73180 is not set +# CONFIG_CPU_SUBTYPE_SH4_202 is not set + +# +# ST40 Processor Support +# # CONFIG_CPU_SUBTYPE_ST40STB1 is not set # CONFIG_CPU_SUBTYPE_ST40GX1 is not set -# CONFIG_CPU_SUBTYPE_SH4_202 is not set + +# +# SH-4A Processor Support +# +# CONFIG_CPU_SUBTYPE_SH73180 is not set +# CONFIG_CPU_SUBTYPE_SH7770 is not set +# CONFIG_CPU_SUBTYPE_SH7780 is not set + +# +# Memory management options +# CONFIG_MMU=y -# CONFIG_CMDLINE_BOOL is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 + +# +# Cache configuration +# +# CONFIG_SH_DIRECT_MAPPED is not set +# CONFIG_SH_WRITETHROUGH is not set +# CONFIG_SH_OCRAM is not set CONFIG_MEMORY_START=0x0c000000 CONFIG_MEMORY_SIZE=0x00400000 -CONFIG_MEMORY_SET=y -# CONFIG_MEMORY_OVERRIDE is not set + +# +# Processor features +# +CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_SH_RTC=y # CONFIG_SH_DSP is not set CONFIG_SH_ADC=y -CONFIG_SH_HP600=y -CONFIG_ZERO_PAGE_OFFSET=0x00001000 -CONFIG_BOOT_LINK_OFFSET=0x00800000 -CONFIG_CPU_LITTLE_ENDIAN=y -# CONFIG_PREEMPT is not set -# CONFIG_UBC_WAKEUP is not set -# CONFIG_SH_WRITETHROUGH is not set -# CONFIG_SH_OCRAM is not set -# CONFIG_SMP is not set -CONFIG_SH_PCLK_CALC=y -CONFIG_SH_PCLK_FREQ=1193182 + +# +# Timer support +# +CONFIG_SH_TMU=y +CONFIG_SH_PCLK_FREQ_BOOL=y +CONFIG_SH_PCLK_FREQ=22110000 # # CPU Frequency scaling @@ -123,7 +191,10 @@ CONFIG_SH_PCLK_FREQ=1193182 # # DMA support # -# CONFIG_SH_DMA is not set +CONFIG_SH_DMA=y +CONFIG_NR_ONCHIP_DMA_CHANNELS=4 +# CONFIG_NR_DMA_CHANNELS_BOOL is not set +# CONFIG_DMA_PAGE_OPS is not set # # Companion Chips @@ -132,21 +203,47 @@ CONFIG_HD6446X_SERIES=y CONFIG_HD64461=y # CONFIG_HD64465 is not set CONFIG_HD64461_IRQ=36 -# CONFIG_HD64461_ENABLER is not set +CONFIG_HD64461_IOBASE=0xb0000000 +CONFIG_HD64461_ENABLER=y + +# +# Kernel features +# +# CONFIG_KEXEC is not set +# CONFIG_PREEMPT is not set +# CONFIG_SMP is not set # -# Bus options (PCI, PCMCIA, EISA, MCA, ISA) +# Boot options # +CONFIG_ZERO_PAGE_OFFSET=0x00001000 +CONFIG_BOOT_LINK_OFFSET=0x00800000 +# CONFIG_UBC_WAKEUP is not set +# CONFIG_CMDLINE_BOOL is not set + +# +# Bus options +# +CONFIG_ISA=y # CONFIG_PCI is not set # # PCCARD (PCMCIA/CardBus) support # -# CONFIG_PCCARD is not set +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y # # PC-card bridges # +# CONFIG_I82365 is not set +# CONFIG_TCIC is not set +CONFIG_HD64461_PCMCIA=y +CONFIG_HD64461_PCMCIA_SOCKETS=1 +CONFIG_PCMCIA_PROBE=y # # PCI Hotplug Support @@ -160,9 +257,9 @@ CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set # -# SH initrd options +# Networking # -# CONFIG_EMBEDDED_RAMDISK is not set +# CONFIG_NET is not set # # Device Drivers @@ -173,7 +270,11 @@ CONFIG_BINFMT_ELF=y # # CONFIG_STANDALONE is not set CONFIG_PREVENT_FIRMWARE_BUILD=y -# CONFIG_FW_LOADER is not set +CONFIG_FW_LOADER=y + +# +# Connector - unified userspace <-> kernelspace linker +# # # Memory Technology Devices (MTD) @@ -188,29 +289,19 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # # Plug and Play support # +# CONFIG_PNP is not set # # Block devices # -# CONFIG_BLK_DEV_FD is not set # CONFIG_BLK_DEV_COW_COMMON is not set # CONFIG_BLK_DEV_LOOP is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" -# CONFIG_LBD is not set # CONFIG_CDROM_PKTCDVD is not set -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y - # # ATA/ATAPI/MFM/RLL support # @@ -224,6 +315,7 @@ CONFIG_BLK_DEV_IDE=y # CONFIG_BLK_DEV_IDE_SATA is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDECS is not set # CONFIG_BLK_DEV_IDECD is not set # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set @@ -235,6 +327,7 @@ CONFIG_BLK_DEV_IDEDISK=y CONFIG_IDE_GENERIC=y CONFIG_IDE_SH=y # CONFIG_IDE_ARM is not set +# CONFIG_IDE_CHIPSETS is not set # CONFIG_BLK_DEV_IDEDMA is not set # CONFIG_IDEDMA_AUTO is not set # CONFIG_BLK_DEV_HD is not set @@ -242,8 +335,14 @@ CONFIG_IDE_SH=y # # SCSI device support # +# CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + # # Multi-device support (RAID and LVM) # @@ -252,6 +351,7 @@ CONFIG_IDE_SH=y # # Fusion MPT device support # +# CONFIG_FUSION is not set # # IEEE 1394 (FireWire) support @@ -263,9 +363,8 @@ CONFIG_IDE_SH=y # # -# Networking support +# Network device support # -# CONFIG_NET is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set @@ -295,17 +394,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_EVDEV is not set # CONFIG_INPUT_EVBUG is not set -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -# CONFIG_SERIO_I8042 is not set -# CONFIG_SERIO_SERPORT is not set -# CONFIG_SERIO_CT82C710 is not set -# CONFIG_SERIO_RAW is not set - # # Input Device Drivers # @@ -315,6 +403,15 @@ CONFIG_SERIO=y # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set +# +# Hardware I/O ports +# +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + # # Character devices # @@ -353,9 +450,21 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Ftape, the floppy tape device driver # -# CONFIG_DRM is not set + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_CARDMAN_4000 is not set +# CONFIG_CARDMAN_4040 is not set # CONFIG_RAW_DRIVER is not set +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + # # I2C support # @@ -366,10 +475,21 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_W1 is not set +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + # # Misc devices # +# +# Multimedia Capabilities Port drivers +# + # # Multimedia devices # @@ -383,27 +503,35 @@ CONFIG_LEGACY_PTY_COUNT=256 # Graphics support # CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set # CONFIG_FB_MODE_HELPERS is not set # CONFIG_FB_TILEBLITTING is not set # CONFIG_FB_EPSON1355 is not set +# CONFIG_FB_S1D13XXX is not set CONFIG_FB_HIT=y # CONFIG_FB_VIRTUAL is not set # # Console display driver support # -# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set CONFIG_FONTS=y # CONFIG_FONT_8x8 is not set # CONFIG_FONT_8x16 is not set # CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set CONFIG_FONT_PEARL_8x8=y # CONFIG_FONT_ACORN_8x8 is not set # CONFIG_FONT_MINI_4x6 is not set # CONFIG_FONT_SUN8x16 is not set # CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_10x18 is not set # # Logo configuration @@ -414,7 +542,22 @@ CONFIG_FONT_PEARL_8x8=y # # Sound # -# CONFIG_SOUND is not set +CONFIG_SOUND=y + +# +# Advanced Linux Sound Architecture +# +# CONFIG_SND is not set + +# +# Open Sound System +# +CONFIG_SOUND_PRIME=y +# CONFIG_OBSOLETE_OSS_DRIVER is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set +CONFIG_SOUND_SH_DAC_AUDIO=y +CONFIG_SOUND_SH_DAC_AUDIO_CHANNEL=1 # # USB support @@ -423,7 +566,7 @@ CONFIG_FONT_PEARL_8x8=y # CONFIG_USB_ARCH_HAS_OHCI is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' # # @@ -441,26 +584,30 @@ CONFIG_FONT_PEARL_8x8=y # # CONFIG_INFINIBAND is not set +# +# SN Devices +# + # # File systems # CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set # CONFIG_EXT3_FS is not set # CONFIG_JBD is not set # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set - -# -# XFS support -# +# CONFIG_FS_POSIX_ACL is not set # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set # # CD-ROM/DVD Filesystems @@ -471,8 +618,11 @@ CONFIG_DNOTIFY=y # # DOS/FAT/NT Filesystems # +CONFIG_FAT_FS=y # CONFIG_MSDOS_FS is not set -# CONFIG_VFAT_FS is not set +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_NTFS_FS is not set # @@ -481,14 +631,11 @@ CONFIG_DNOTIFY=y CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y CONFIG_SYSFS=y -CONFIG_DEVFS_FS=y -CONFIG_DEVFS_MOUNT=y -# CONFIG_DEVFS_DEBUG is not set -# CONFIG_DEVPTS_FS_XATTR is not set # CONFIG_TMPFS is not set # CONFIG_HUGETLBFS is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set # # Miscellaneous filesystems @@ -516,7 +663,46 @@ CONFIG_MSDOS_PARTITION=y # # Native Language Support # -# CONFIG_NLS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set # # Profiling support @@ -526,7 +712,9 @@ CONFIG_MSDOS_PARTITION=y # # Kernel hacking # +# CONFIG_PRINTK_TIME is not set # CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 # CONFIG_FRAME_POINTER is not set # CONFIG_SH_STANDARD_BIOS is not set # CONFIG_KGDB is not set @@ -550,5 +738,6 @@ CONFIG_MSDOS_PARTITION=y # Library routines # # CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types index 0693fbd1f95..182fe909257 100644 --- a/arch/sh/tools/mach-types +++ b/arch/sh/tools/mach-types @@ -10,10 +10,7 @@ SE SH_SOLUTION_ENGINE 7300SE SH_7300_SOLUTION_ENGINE 73180SE SH_73180_SOLUTION_ENGINE 7751SYSTEMH SH_7751_SYSTEMH -HP600 SH_HP600 -HP620 SH_HP620 -HP680 SH_HP680 -HP690 SH_HP690 +HP6XX SH_HP6XX HD64461 HD64461 HD64465 HD64465 SH2000 SH_SH2000 diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 2c674023a6a..b1b14f8d4dd 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -98,7 +98,7 @@ config TOUCHSCREEN_MK712 config TOUCHSCREEN_HP600 tristate "HP Jornada 680/690 touchscreen" - depends on SH_HP600 && SH_ADC + depends on SH_HP6XX && SH_ADC help Say Y here if you have a HP Jornada 680 or 690 and want to support the built-in touchscreen. -- GitLab From 0d831770b154a057562236e8cf50905c8f1ae1b0 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 16 Jan 2006 22:14:09 -0800 Subject: [PATCH 375/465] [PATCH] sh: DMA updates This extends the current SH DMA API somewhat to support a proper virtual channel abstraction, and also works to represent this through the driver model by giving each DMAC its own platform device. There's also a few other minor changes to support a few new CPU subtypes, and make TEI generation for the SH DMAC configurable. Signed-off-by: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/sh/drivers/dma/dma-api.c | 51 ++++++++---- arch/sh/drivers/dma/dma-g2.c | 3 +- arch/sh/drivers/dma/dma-isa.c | 20 ++--- arch/sh/drivers/dma/dma-pvr2.c | 3 +- arch/sh/drivers/dma/dma-sh.c | 134 +++++++++++++++++++------------- arch/sh/drivers/dma/dma-sh.h | 44 ++++++++--- arch/sh/drivers/dma/dma-sysfs.c | 31 ++++++-- arch/sh/kernel/cpu/bus.c | 2 + include/asm-sh/bus-sh.h | 1 + include/asm-sh/cpu-sh3/dma.h | 31 +++++++- include/asm-sh/cpu-sh4/dma.h | 52 ++++++++++--- include/asm-sh/dma-mapping.h | 25 +++--- include/asm-sh/dma.h | 14 +++- 13 files changed, 291 insertions(+), 120 deletions(-) diff --git a/arch/sh/drivers/dma/dma-api.c b/arch/sh/drivers/dma/dma-api.c index 96e3036ec2b..47c3e837599 100644 --- a/arch/sh/drivers/dma/dma-api.c +++ b/arch/sh/drivers/dma/dma-api.c @@ -3,7 +3,7 @@ * * SuperH-specific DMA management API * - * Copyright (C) 2003, 2004 Paul Mundt + * Copyright (C) 2003, 2004, 2005 Paul Mundt * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -15,6 +15,7 @@ #include #include #include +#include #include DEFINE_SPINLOCK(dma_spin_lock); @@ -55,16 +56,14 @@ static LIST_HEAD(registered_dmac_list); struct dma_info *get_dma_info(unsigned int chan) { - struct list_head *pos, *tmp; + struct dma_info *info; unsigned int total = 0; /* * Look for each DMAC's range to determine who the owner of * the channel is. */ - list_for_each_safe(pos, tmp, ®istered_dmac_list) { - struct dma_info *info = list_entry(pos, struct dma_info, list); - + list_for_each_entry(info, ®istered_dmac_list, list) { total += info->nr_channels; if (chan > total) continue; @@ -75,6 +74,20 @@ struct dma_info *get_dma_info(unsigned int chan) return NULL; } +static unsigned int get_nr_channels(void) +{ + struct dma_info *info; + unsigned int nr = 0; + + if (unlikely(list_empty(®istered_dmac_list))) + return nr; + + list_for_each_entry(info, ®istered_dmac_list, list) + nr += info->nr_channels; + + return nr; +} + struct dma_channel *get_dma_channel(unsigned int chan) { struct dma_info *info = get_dma_info(chan); @@ -173,7 +186,7 @@ int dma_xfer(unsigned int chan, unsigned long from, static int dma_read_proc(char *buf, char **start, off_t off, int len, int *eof, void *data) { - struct list_head *pos, *tmp; + struct dma_info *info; char *p = buf; if (list_empty(®istered_dmac_list)) @@ -182,8 +195,7 @@ static int dma_read_proc(char *buf, char **start, off_t off, /* * Iterate over each registered DMAC */ - list_for_each_safe(pos, tmp, ®istered_dmac_list) { - struct dma_info *info = list_entry(pos, struct dma_info, list); + list_for_each_entry(info, ®istered_dmac_list, list) { int i; /* @@ -205,9 +217,9 @@ static int dma_read_proc(char *buf, char **start, off_t off, #endif -int __init register_dmac(struct dma_info *info) +int register_dmac(struct dma_info *info) { - int i; + unsigned int total_channels, i; INIT_LIST_HEAD(&info->list); @@ -217,6 +229,11 @@ int __init register_dmac(struct dma_info *info) BUG_ON((info->flags & DMAC_CHANNELS_CONFIGURED) && !info->channels); + info->pdev = platform_device_register_simple((char *)info->name, -1, + NULL, 0); + if (IS_ERR(info->pdev)) + return PTR_ERR(info->pdev); + /* * Don't touch pre-configured channels */ @@ -232,10 +249,12 @@ int __init register_dmac(struct dma_info *info) memset(info->channels, 0, size); } + total_channels = get_nr_channels(); for (i = 0; i < info->nr_channels; i++) { struct dma_channel *chan = info->channels + i; chan->chan = i; + chan->vchan = i + total_channels; memcpy(chan->dev_id, "Unused", 7); @@ -245,9 +264,7 @@ int __init register_dmac(struct dma_info *info) init_MUTEX(&chan->sem); init_waitqueue_head(&chan->wait_queue); -#ifdef CONFIG_SYSFS - dma_create_sysfs_files(chan); -#endif + dma_create_sysfs_files(chan, info); } list_add(&info->list, ®istered_dmac_list); @@ -255,12 +272,18 @@ int __init register_dmac(struct dma_info *info) return 0; } -void __exit unregister_dmac(struct dma_info *info) +void unregister_dmac(struct dma_info *info) { + unsigned int i; + + for (i = 0; i < info->nr_channels; i++) + dma_remove_sysfs_files(info->channels + i, info); + if (!(info->flags & DMAC_CHANNELS_CONFIGURED)) kfree(info->channels); list_del(&info->list); + platform_device_unregister(info->pdev); } static int __init dma_api_init(void) diff --git a/arch/sh/drivers/dma/dma-g2.c b/arch/sh/drivers/dma/dma-g2.c index 231e3f6fb28..5afab6f56ec 100644 --- a/arch/sh/drivers/dma/dma-g2.c +++ b/arch/sh/drivers/dma/dma-g2.c @@ -140,7 +140,7 @@ static struct dma_ops g2_dma_ops = { }; static struct dma_info g2_dma_info = { - .name = "G2 DMA", + .name = "g2_dmac", .nr_channels = 4, .ops = &g2_dma_ops, .flags = DMAC_CHANNELS_TEI_CAPABLE, @@ -160,6 +160,7 @@ static int __init g2_dma_init(void) static void __exit g2_dma_exit(void) { free_irq(HW_EVENT_G2_DMA, 0); + unregister_dmac(&g2_dma_info); } subsys_initcall(g2_dma_init); diff --git a/arch/sh/drivers/dma/dma-isa.c b/arch/sh/drivers/dma/dma-isa.c index 1c9bc45b8bc..05a74ffdb68 100644 --- a/arch/sh/drivers/dma/dma-isa.c +++ b/arch/sh/drivers/dma/dma-isa.c @@ -25,14 +25,14 @@ * such, this code is meant for only the simplest of tasks (and shouldn't be * used in any new drivers at all). * - * It should also be noted that various functions here are labelled as - * being deprecated. This is due to the fact that the ops->xfer() method is - * the preferred way of doing things (as well as just grabbing the spinlock - * directly). As such, any users of this interface will be warned rather - * loudly. + * NOTE: ops->xfer() is the preferred way of doing things. However, there + * are some users of the ISA DMA API that exist in common code that we + * don't necessarily want to go out of our way to break, so we still + * allow for some compatability at that level. Any new code is strongly + * advised to run far away from the ISA DMA API and use the SH DMA API + * directly. */ - -unsigned long __deprecated claim_dma_lock(void) +unsigned long claim_dma_lock(void) { unsigned long flags; @@ -42,19 +42,19 @@ unsigned long __deprecated claim_dma_lock(void) } EXPORT_SYMBOL(claim_dma_lock); -void __deprecated release_dma_lock(unsigned long flags) +void release_dma_lock(unsigned long flags) { spin_unlock_irqrestore(&dma_spin_lock, flags); } EXPORT_SYMBOL(release_dma_lock); -void __deprecated disable_dma(unsigned int chan) +void disable_dma(unsigned int chan) { /* Nothing */ } EXPORT_SYMBOL(disable_dma); -void __deprecated enable_dma(unsigned int chan) +void enable_dma(unsigned int chan) { struct dma_info *info = get_dma_info(chan); struct dma_channel *channel = &info->channels[chan]; diff --git a/arch/sh/drivers/dma/dma-pvr2.c b/arch/sh/drivers/dma/dma-pvr2.c index 2e1d58f2d1b..df604975ccc 100644 --- a/arch/sh/drivers/dma/dma-pvr2.c +++ b/arch/sh/drivers/dma/dma-pvr2.c @@ -80,7 +80,7 @@ static struct dma_ops pvr2_dma_ops = { }; static struct dma_info pvr2_dma_info = { - .name = "PowerVR 2 DMA", + .name = "pvr2_dmac", .nr_channels = 1, .ops = &pvr2_dma_ops, .flags = DMAC_CHANNELS_TEI_CAPABLE, @@ -98,6 +98,7 @@ static void __exit pvr2_dma_exit(void) { free_dma(PVR2_CASCADE_CHAN); free_irq(HW_EVENT_PVR2_DMA, 0); + unregister_dmac(&pvr2_dma_info); } subsys_initcall(pvr2_dma_init); diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c index 31dacd4444b..cca26c4c9d1 100644 --- a/arch/sh/drivers/dma/dma-sh.c +++ b/arch/sh/drivers/dma/dma-sh.c @@ -5,6 +5,7 @@ * * Copyright (C) 2000 Takashi YOSHII * Copyright (C) 2003, 2004 Paul Mundt + * Copyright (C) 2005 Andriy Skulysh * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -16,51 +17,28 @@ #include #include #include +#include #include #include #include #include #include "dma-sh.h" -/* - * The SuperH DMAC supports a number of transmit sizes, we list them here, - * with their respective values as they appear in the CHCR registers. - * - * Defaults to a 64-bit transfer size. - */ -enum { - XMIT_SZ_64BIT, - XMIT_SZ_8BIT, - XMIT_SZ_16BIT, - XMIT_SZ_32BIT, - XMIT_SZ_256BIT, -}; - -/* - * The DMA count is defined as the number of bytes to transfer. - */ -static unsigned int ts_shift[] = { - [XMIT_SZ_64BIT] = 3, - [XMIT_SZ_8BIT] = 0, - [XMIT_SZ_16BIT] = 1, - [XMIT_SZ_32BIT] = 2, - [XMIT_SZ_256BIT] = 5, -}; - static inline unsigned int get_dmte_irq(unsigned int chan) { - unsigned int irq; + unsigned int irq = 0; /* * Normally we could just do DMTE0_IRQ + chan outright, though in the * case of the 7751R, the DMTE IRQs for channels > 4 start right above * the SCIF */ - if (chan < 4) { irq = DMTE0_IRQ + chan; } else { +#ifdef DMTE4_IRQ irq = DMTE4_IRQ + chan - 4; +#endif } return irq; @@ -78,9 +56,7 @@ static inline unsigned int calc_xmit_shift(struct dma_channel *chan) { u32 chcr = ctrl_inl(CHCR[chan->chan]); - chcr >>= 4; - - return ts_shift[chcr & 0x0007]; + return ts_shift[(chcr & CHCR_TS_MASK)>>CHCR_TS_SHIFT]; } /* @@ -109,8 +85,13 @@ static irqreturn_t dma_tei(int irq, void *dev_id, struct pt_regs *regs) static int sh_dmac_request_dma(struct dma_channel *chan) { + char name[32]; + + snprintf(name, sizeof(name), "DMAC Transfer End (Channel %d)", + chan->chan); + return request_irq(get_dmte_irq(chan->chan), dma_tei, - SA_INTERRUPT, "DMAC Transfer End", chan); + SA_INTERRUPT, name, chan); } static void sh_dmac_free_dma(struct dma_channel *chan) @@ -118,10 +99,18 @@ static void sh_dmac_free_dma(struct dma_channel *chan) free_irq(get_dmte_irq(chan->chan), chan); } -static void sh_dmac_configure_channel(struct dma_channel *chan, unsigned long chcr) +static void +sh_dmac_configure_channel(struct dma_channel *chan, unsigned long chcr) { if (!chcr) - chcr = RS_DUAL; + chcr = RS_DUAL | CHCR_IE; + + if (chcr & CHCR_IE) { + chcr &= ~CHCR_IE; + chan->flags |= DMA_TEI_CAPABLE; + } else { + chan->flags &= ~DMA_TEI_CAPABLE; + } ctrl_outl(chcr, CHCR[chan->chan]); @@ -130,22 +119,32 @@ static void sh_dmac_configure_channel(struct dma_channel *chan, unsigned long ch static void sh_dmac_enable_dma(struct dma_channel *chan) { - int irq = get_dmte_irq(chan->chan); + int irq; u32 chcr; chcr = ctrl_inl(CHCR[chan->chan]); - chcr |= CHCR_DE | CHCR_IE; + chcr |= CHCR_DE; + + if (chan->flags & DMA_TEI_CAPABLE) + chcr |= CHCR_IE; + ctrl_outl(chcr, CHCR[chan->chan]); - enable_irq(irq); + if (chan->flags & DMA_TEI_CAPABLE) { + irq = get_dmte_irq(chan->chan); + enable_irq(irq); + } } static void sh_dmac_disable_dma(struct dma_channel *chan) { - int irq = get_dmte_irq(chan->chan); + int irq; u32 chcr; - disable_irq(irq); + if (chan->flags & DMA_TEI_CAPABLE) { + irq = get_dmte_irq(chan->chan); + disable_irq(irq); + } chcr = ctrl_inl(CHCR[chan->chan]); chcr &= ~(CHCR_DE | CHCR_TE | CHCR_IE); @@ -158,7 +157,7 @@ static int sh_dmac_xfer_dma(struct dma_channel *chan) * If we haven't pre-configured the channel with special flags, use * the defaults. */ - if (!(chan->flags & DMA_CONFIGURED)) + if (unlikely(!(chan->flags & DMA_CONFIGURED))) sh_dmac_configure_channel(chan, 0); sh_dmac_disable_dma(chan); @@ -178,9 +177,11 @@ static int sh_dmac_xfer_dma(struct dma_channel *chan) * cascading to the PVR2 DMAC. In this case, we still need to write * SAR and DAR, regardless of value, in order for cascading to work. */ - if (chan->sar || (mach_is_dreamcast() && chan->chan == 2)) + if (chan->sar || (mach_is_dreamcast() && + chan->chan == PVR2_CASCADE_CHAN)) ctrl_outl(chan->sar, SAR[chan->chan]); - if (chan->dar || (mach_is_dreamcast() && chan->chan == 2)) + if (chan->dar || (mach_is_dreamcast() && + chan->chan == PVR2_CASCADE_CHAN)) ctrl_outl(chan->dar, DAR[chan->chan]); ctrl_outl(chan->count >> calc_xmit_shift(chan), DMATCR[chan->chan]); @@ -198,17 +199,38 @@ static int sh_dmac_get_dma_residue(struct dma_channel *chan) return ctrl_inl(DMATCR[chan->chan]) << calc_xmit_shift(chan); } -#if defined(CONFIG_CPU_SH4) -static irqreturn_t dma_err(int irq, void *dev_id, struct pt_regs *regs) +#ifdef CONFIG_CPU_SUBTYPE_SH7780 +#define dmaor_read_reg() ctrl_inw(DMAOR) +#define dmaor_write_reg(data) ctrl_outw(data, DMAOR) +#else +#define dmaor_read_reg() ctrl_inl(DMAOR) +#define dmaor_write_reg(data) ctrl_outl(data, DMAOR) +#endif + +static inline int dmaor_reset(void) { - unsigned long dmaor = ctrl_inl(DMAOR); + unsigned long dmaor = dmaor_read_reg(); + + /* Try to clear the error flags first, incase they are set */ + dmaor &= ~(DMAOR_NMIF | DMAOR_AE); + dmaor_write_reg(dmaor); - printk("DMAE: DMAOR=%lx\n", dmaor); + dmaor |= DMAOR_INIT; + dmaor_write_reg(dmaor); - ctrl_outl(ctrl_inl(DMAOR)&~DMAOR_NMIF, DMAOR); - ctrl_outl(ctrl_inl(DMAOR)&~DMAOR_AE, DMAOR); - ctrl_outl(ctrl_inl(DMAOR)|DMAOR_DME, DMAOR); + /* See if we got an error again */ + if ((dmaor_read_reg() & (DMAOR_AE | DMAOR_NMIF))) { + printk(KERN_ERR "dma-sh: Can't initialize DMAOR.\n"); + return -EINVAL; + } + return 0; +} + +#if defined(CONFIG_CPU_SH4) +static irqreturn_t dma_err(int irq, void *dev_id, struct pt_regs *regs) +{ + dmaor_reset(); disable_irq(irq); return IRQ_HANDLED; @@ -224,8 +246,8 @@ static struct dma_ops sh_dmac_ops = { }; static struct dma_info sh_dmac_info = { - .name = "SuperH DMAC", - .nr_channels = 4, + .name = "sh_dmac", + .nr_channels = CONFIG_NR_ONCHIP_DMA_CHANNELS, .ops = &sh_dmac_ops, .flags = DMAC_CHANNELS_TEI_CAPABLE, }; @@ -248,7 +270,13 @@ static int __init sh_dmac_init(void) make_ipr_irq(irq, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY); } - ctrl_outl(0x8000 | DMAOR_DME, DMAOR); + /* + * Initialize DMAOR, and clean up any error flags that may have + * been set. + */ + i = dmaor_reset(); + if (i < 0) + return i; return register_dmac(info); } @@ -258,10 +286,12 @@ static void __exit sh_dmac_exit(void) #ifdef CONFIG_CPU_SH4 free_irq(DMAE_IRQ, 0); #endif + unregister_dmac(&sh_dmac_info); } subsys_initcall(sh_dmac_init); module_exit(sh_dmac_exit); +MODULE_AUTHOR("Takashi YOSHII, Paul Mundt, Andriy Skulysh"); +MODULE_DESCRIPTION("SuperH On-Chip DMAC Support"); MODULE_LICENSE("GPL"); - diff --git a/arch/sh/drivers/dma/dma-sh.h b/arch/sh/drivers/dma/dma-sh.h index dd9d547539a..0f591fbc922 100644 --- a/arch/sh/drivers/dma/dma-sh.h +++ b/arch/sh/drivers/dma/dma-sh.h @@ -11,6 +11,8 @@ #ifndef __DMA_SH_H #define __DMA_SH_H +#include + /* Definitions for the SuperH DMAC */ #define REQ_L 0x00000000 #define REQ_E 0x00080000 @@ -26,27 +28,47 @@ #define SM_DEC 0x00002000 #define RS_IN 0x00000200 #define RS_OUT 0x00000300 -#define TM_BURST 0x0000080 -#define TS_8 0x00000010 -#define TS_16 0x00000020 -#define TS_32 0x00000030 -#define TS_64 0x00000000 #define TS_BLK 0x00000040 #define CHCR_DE 0x00000001 #define CHCR_TE 0x00000002 #define CHCR_IE 0x00000004 -/* Define the default configuration for dual address memory-memory transfer. - * The 0x400 value represents auto-request, external->external. - */ -#define RS_DUAL (DM_INC | SM_INC | 0x400 | TS_32) - -#define DMAOR_COD 0x00000008 +/* DMAOR definitions */ #define DMAOR_AE 0x00000004 #define DMAOR_NMIF 0x00000002 #define DMAOR_DME 0x00000001 +/* + * Define the default configuration for dual address memory-memory transfer. + * The 0x400 value represents auto-request, external->external. + */ +#define RS_DUAL (DM_INC | SM_INC | 0x400 | TS_32) + #define MAX_DMAC_CHANNELS (CONFIG_NR_ONCHIP_DMA_CHANNELS) +/* + * Subtypes that have fewer channels than this simply need to change + * CONFIG_NR_ONCHIP_DMA_CHANNELS. Likewise, subtypes with a larger number + * of channels should expand on this. + * + * For most subtypes we can easily figure these values out with some + * basic calculation, unfortunately on other subtypes these are more + * scattered, so we just leave it unrolled for simplicity. + */ +#define SAR ((unsigned long[]){SH_DMAC_BASE + 0x00, SH_DMAC_BASE + 0x10, \ + SH_DMAC_BASE + 0x20, SH_DMAC_BASE + 0x30, \ + SH_DMAC_BASE + 0x50, SH_DMAC_BASE + 0x60}) +#define DAR ((unsigned long[]){SH_DMAC_BASE + 0x04, SH_DMAC_BASE + 0x14, \ + SH_DMAC_BASE + 0x24, SH_DMAC_BASE + 0x34, \ + SH_DMAC_BASE + 0x54, SH_DMAC_BASE + 0x64}) +#define DMATCR ((unsigned long[]){SH_DMAC_BASE + 0x08, SH_DMAC_BASE + 0x18, \ + SH_DMAC_BASE + 0x28, SH_DMAC_BASE + 0x38, \ + SH_DMAC_BASE + 0x58, SH_DMAC_BASE + 0x68}) +#define CHCR ((unsigned long[]){SH_DMAC_BASE + 0x0c, SH_DMAC_BASE + 0x1c, \ + SH_DMAC_BASE + 0x2c, SH_DMAC_BASE + 0x3c, \ + SH_DMAC_BASE + 0x5c, SH_DMAC_BASE + 0x6c}) + +#define DMAOR (SH_DMAC_BASE + 0x40) + #endif /* __DMA_SH_H */ diff --git a/arch/sh/drivers/dma/dma-sysfs.c b/arch/sh/drivers/dma/dma-sysfs.c index 6e3b58bd879..70a5d82eb2f 100644 --- a/arch/sh/drivers/dma/dma-sysfs.c +++ b/arch/sh/drivers/dma/dma-sysfs.c @@ -3,7 +3,7 @@ * * sysfs interface for SH DMA API * - * Copyright (C) 2004 Paul Mundt + * Copyright (C) 2004, 2005 Paul Mundt * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -12,7 +12,9 @@ #include #include #include +#include #include +#include #include #include @@ -77,7 +79,7 @@ static ssize_t dma_store_config(struct sys_device *dev, unsigned long config; config = simple_strtoul(buf, NULL, 0); - dma_configure_channel(channel->chan, config); + dma_configure_channel(channel->vchan, config); return count; } @@ -111,12 +113,13 @@ static SYSDEV_ATTR(field, S_IRUGO, dma_show_##field, NULL); dma_ro_attr(count, "0x%08x\n"); dma_ro_attr(flags, "0x%08lx\n"); -int __init dma_create_sysfs_files(struct dma_channel *chan) +int dma_create_sysfs_files(struct dma_channel *chan, struct dma_info *info) { struct sys_device *dev = &chan->dev; + char name[16]; int ret; - dev->id = chan->chan; + dev->id = chan->vchan; dev->cls = &dma_sysclass; ret = sysdev_register(dev); @@ -129,6 +132,24 @@ int __init dma_create_sysfs_files(struct dma_channel *chan) sysdev_create_file(dev, &attr_flags); sysdev_create_file(dev, &attr_config); - return 0; + snprintf(name, sizeof(name), "dma%d", chan->chan); + return sysfs_create_link(&info->pdev->dev.kobj, &dev->kobj, name); +} + +void dma_remove_sysfs_files(struct dma_channel *chan, struct dma_info *info) +{ + struct sys_device *dev = &chan->dev; + char name[16]; + + sysdev_remove_file(dev, &attr_dev_id); + sysdev_remove_file(dev, &attr_count); + sysdev_remove_file(dev, &attr_mode); + sysdev_remove_file(dev, &attr_flags); + sysdev_remove_file(dev, &attr_config); + + snprintf(name, sizeof(name), "dma%d", chan->chan); + sysfs_remove_link(&info->pdev->dev.kobj, name); + + sysdev_unregister(dev); } diff --git a/arch/sh/kernel/cpu/bus.c b/arch/sh/kernel/cpu/bus.c index 3278d234bb1..fc6c4bd40c6 100644 --- a/arch/sh/kernel/cpu/bus.c +++ b/arch/sh/kernel/cpu/bus.c @@ -109,6 +109,8 @@ int sh_device_register(struct sh_dev *dev) /* This is needed for USB OHCI to work */ if (dev->dma_mask) dev->dev.dma_mask = dev->dma_mask; + if (dev->coherent_dma_mask) + dev->dev.coherent_dma_mask = dev->coherent_dma_mask; snprintf(dev->dev.bus_id, BUS_ID_SIZE, "%s%u", dev->name, dev->dev_id); diff --git a/include/asm-sh/bus-sh.h b/include/asm-sh/bus-sh.h index 83c5d2fd057..e42d63b65cb 100644 --- a/include/asm-sh/bus-sh.h +++ b/include/asm-sh/bus-sh.h @@ -21,6 +21,7 @@ struct sh_dev { void *mapbase; unsigned int irq[6]; u64 *dma_mask; + u64 coherent_dma_mask; }; #define to_sh_dev(d) container_of((d), struct sh_dev, dev) diff --git a/include/asm-sh/cpu-sh3/dma.h b/include/asm-sh/cpu-sh3/dma.h index b972e715f9e..954801b4602 100644 --- a/include/asm-sh/cpu-sh3/dma.h +++ b/include/asm-sh/cpu-sh3/dma.h @@ -3,5 +3,34 @@ #define SH_DMAC_BASE 0xa4000020 -#endif /* __ASM_CPU_SH3_DMA_H */ +/* Definitions for the SuperH DMAC */ +#define TM_BURST 0x00000020 +#define TS_8 0x00000000 +#define TS_16 0x00000008 +#define TS_32 0x00000010 +#define TS_128 0x00000018 + +#define CHCR_TS_MASK 0x18 +#define CHCR_TS_SHIFT 3 + +#define DMAOR_INIT DMAOR_DME +/* + * The SuperH DMAC supports a number of transmit sizes, we list them here, + * with their respective values as they appear in the CHCR registers. + */ +enum { + XMIT_SZ_8BIT, + XMIT_SZ_16BIT, + XMIT_SZ_32BIT, + XMIT_SZ_128BIT, +}; + +static unsigned int ts_shift[] __attribute__ ((used)) = { + [XMIT_SZ_8BIT] = 0, + [XMIT_SZ_16BIT] = 1, + [XMIT_SZ_32BIT] = 2, + [XMIT_SZ_128BIT] = 4, +}; + +#endif /* __ASM_CPU_SH3_DMA_H */ diff --git a/include/asm-sh/cpu-sh4/dma.h b/include/asm-sh/cpu-sh4/dma.h index e2b91adf821..0dfe61f1480 100644 --- a/include/asm-sh/cpu-sh4/dma.h +++ b/include/asm-sh/cpu-sh4/dma.h @@ -1,17 +1,49 @@ #ifndef __ASM_CPU_SH4_DMA_H #define __ASM_CPU_SH4_DMA_H +#ifdef CONFIG_CPU_SH4A +#define SH_DMAC_BASE 0xfc808020 +#else #define SH_DMAC_BASE 0xffa00000 +#endif -#define SAR ((unsigned long[]){SH_DMAC_BASE + 0x00, SH_DMAC_BASE + 0x10, \ - SH_DMAC_BASE + 0x20, SH_DMAC_BASE + 0x30}) -#define DAR ((unsigned long[]){SH_DMAC_BASE + 0x04, SH_DMAC_BASE + 0x14, \ - SH_DMAC_BASE + 0x24, SH_DMAC_BASE + 0x34}) -#define DMATCR ((unsigned long[]){SH_DMAC_BASE + 0x08, SH_DMAC_BASE + 0x18, \ - SH_DMAC_BASE + 0x28, SH_DMAC_BASE + 0x38}) -#define CHCR ((unsigned long[]){SH_DMAC_BASE + 0x0c, SH_DMAC_BASE + 0x1c, \ - SH_DMAC_BASE + 0x2c, SH_DMAC_BASE + 0x3c}) -#define DMAOR (SH_DMAC_BASE + 0x40) +/* Definitions for the SuperH DMAC */ +#define TM_BURST 0x0000080 +#define TS_8 0x00000010 +#define TS_16 0x00000020 +#define TS_32 0x00000030 +#define TS_64 0x00000000 -#endif /* __ASM_CPU_SH4_DMA_H */ +#define CHCR_TS_MASK 0x30 +#define CHCR_TS_SHIFT 4 + +#define DMAOR_COD 0x00000008 + +#define DMAOR_INIT ( 0x8000 | DMAOR_DME ) +/* + * The SuperH DMAC supports a number of transmit sizes, we list them here, + * with their respective values as they appear in the CHCR registers. + * + * Defaults to a 64-bit transfer size. + */ +enum { + XMIT_SZ_64BIT, + XMIT_SZ_8BIT, + XMIT_SZ_16BIT, + XMIT_SZ_32BIT, + XMIT_SZ_256BIT, +}; + +/* + * The DMA count is defined as the number of bytes to transfer. + */ +static unsigned int ts_shift[] __attribute__ ((used)) = { + [XMIT_SZ_64BIT] = 3, + [XMIT_SZ_8BIT] = 0, + [XMIT_SZ_16BIT] = 1, + [XMIT_SZ_32BIT] = 2, + [XMIT_SZ_256BIT] = 5, +}; + +#endif /* __ASM_CPU_SH4_DMA_H */ diff --git a/include/asm-sh/dma-mapping.h b/include/asm-sh/dma-mapping.h index d3fa5c2b889..48f1f42c5d1 100644 --- a/include/asm-sh/dma-mapping.h +++ b/include/asm-sh/dma-mapping.h @@ -4,6 +4,7 @@ #include #include #include +#include #include extern struct bus_type pci_bus_type; @@ -141,24 +142,24 @@ static inline void dma_sync_sg(struct device *dev, struct scatterlist *sg, } } -static inline void dma_sync_single_for_cpu(struct device *dev, - dma_addr_t dma_handle, size_t size, - enum dma_data_direction dir) +static void dma_sync_single_for_cpu(struct device *dev, + dma_addr_t dma_handle, size_t size, + enum dma_data_direction dir) __attribute__ ((alias("dma_sync_single"))); -static inline void dma_sync_single_for_device(struct device *dev, - dma_addr_t dma_handle, size_t size, - enum dma_data_direction dir) +static void dma_sync_single_for_device(struct device *dev, + dma_addr_t dma_handle, size_t size, + enum dma_data_direction dir) __attribute__ ((alias("dma_sync_single"))); -static inline void dma_sync_sg_for_cpu(struct device *dev, - struct scatterlist *sg, int nelems, - enum dma_data_direction dir) +static void dma_sync_sg_for_cpu(struct device *dev, + struct scatterlist *sg, int nelems, + enum dma_data_direction dir) __attribute__ ((alias("dma_sync_sg"))); -static inline void dma_sync_sg_for_device(struct device *dev, - struct scatterlist *sg, int nelems, - enum dma_data_direction dir) +static void dma_sync_sg_for_device(struct device *dev, + struct scatterlist *sg, int nelems, + enum dma_data_direction dir) __attribute__ ((alias("dma_sync_sg"))); static inline int dma_get_cache_alignment(void) diff --git a/include/asm-sh/dma.h b/include/asm-sh/dma.h index 8e9436093ca..a118a0d4305 100644 --- a/include/asm-sh/dma.h +++ b/include/asm-sh/dma.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -54,8 +55,8 @@ enum { * DMA channel capabilities / flags */ enum { - DMA_CONFIGURED = 0x00, DMA_TEI_CAPABLE = 0x01, + DMA_CONFIGURED = 0x02, }; extern spinlock_t dma_spin_lock; @@ -74,7 +75,8 @@ struct dma_ops { struct dma_channel { char dev_id[16]; - unsigned int chan; + unsigned int chan; /* Physical channel number */ + unsigned int vchan; /* Virtual channel number */ unsigned int mode; unsigned int count; @@ -91,6 +93,8 @@ struct dma_channel { }; struct dma_info { + struct platform_device *pdev; + const char *name; unsigned int nr_channels; unsigned long flags; @@ -130,7 +134,11 @@ extern void unregister_dmac(struct dma_info *info); #ifdef CONFIG_SYSFS /* arch/sh/drivers/dma/dma-sysfs.c */ -extern int dma_create_sysfs_files(struct dma_channel *); +extern int dma_create_sysfs_files(struct dma_channel *, struct dma_info *); +extern void dma_remove_sysfs_files(struct dma_channel *, struct dma_info *); +#else +#define dma_create_sysfs_file(channel, info) do { } while (0) +#define dma_remove_sysfs_file(channel, info) do { } while (0) #endif #ifdef CONFIG_PCI -- GitLab From 9d44190eae97ad4c9ce30f1084e1b0dabd646df5 Mon Sep 17 00:00:00 2001 From: kogiidena Date: Mon, 16 Jan 2006 22:14:10 -0800 Subject: [PATCH 376/465] [PATCH] sh: kexec() support This adds kexec() support for SH. Signed-off-by: kogiidena Signed-off-by: Paul Mundt Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/sh/kernel/Makefile | 4 +- arch/sh/kernel/machine_kexec.c | 112 +++++++++++++++++++++++++++++++ arch/sh/kernel/process.c | 10 +++ arch/sh/kernel/relocate_kernel.S | 102 ++++++++++++++++++++++++++++ include/asm-sh/kexec.h | 33 +++++++++ include/linux/kexec.h | 1 + 6 files changed, 259 insertions(+), 3 deletions(-) create mode 100644 arch/sh/kernel/machine_kexec.c create mode 100644 arch/sh/kernel/relocate_kernel.S create mode 100644 include/asm-sh/kexec.h diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index 8b819698df1..7a86eeb2265 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile @@ -17,6 +17,4 @@ obj-$(CONFIG_SH_KGDB) += kgdb_stub.o kgdb_jmp.o obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o - -USE_STANDARD_AS_RULE := true - +obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c new file mode 100644 index 00000000000..43546525f28 --- /dev/null +++ b/arch/sh/kernel/machine_kexec.c @@ -0,0 +1,112 @@ +/* + * machine_kexec.c - handle transition of Linux booting another kernel + * Copyright (C) 2002-2003 Eric Biederman + * + * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz + * LANDISK/sh4 supported by kogiidena + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef NORET_TYPE void (*relocate_new_kernel_t)( + unsigned long indirection_page, + unsigned long reboot_code_buffer, + unsigned long start_address, + unsigned long vbr_reg) ATTRIB_NORET; + +const extern unsigned char relocate_new_kernel[]; +const extern unsigned int relocate_new_kernel_size; +extern void *gdb_vbr_vector; + +/* + * Provide a dummy crash_notes definition while crash dump arrives to ppc. + * This prevents breakage of crash_notes attribute in kernel/ksysfs.c. + */ +void *crash_notes = NULL; + +void machine_shutdown(void) +{ +} + +void machine_crash_shutdown(struct pt_regs *regs) +{ +} + +/* + * Do what every setup is needed on image and the + * reboot code buffer to allow us to avoid allocations + * later. + */ +int machine_kexec_prepare(struct kimage *image) +{ + return 0; +} + +void machine_kexec_cleanup(struct kimage *image) +{ +} + +static void kexec_info(struct kimage *image) +{ + int i; + printk("kexec information\n"); + for (i = 0; i < image->nr_segments; i++) { + printk(" segment[%d]: 0x%08x - 0x%08x (0x%08x)\n", + i, + (unsigned int)image->segment[i].mem, + (unsigned int)image->segment[i].mem + image->segment[i].memsz, + (unsigned int)image->segment[i].memsz); + } + printk(" start : 0x%08x\n\n", (unsigned int)image->start); +} + + +/* + * Do not allocate memory (or fail in any way) in machine_kexec(). + * We are past the point of no return, committed to rebooting now. + */ +NORET_TYPE void machine_kexec(struct kimage *image) +{ + + unsigned long page_list; + unsigned long reboot_code_buffer; + unsigned long vbr_reg; + relocate_new_kernel_t rnk; + +#if defined(CONFIG_SH_STANDARD_BIOS) + vbr_reg = ((unsigned long )gdb_vbr_vector) - 0x100; +#else + vbr_reg = 0x80000000; // dummy +#endif + /* Interrupts aren't acceptable while we reboot */ + local_irq_disable(); + + page_list = image->head; + + /* we need both effective and real address here */ + reboot_code_buffer = + (unsigned long)page_address(image->control_code_page); + + /* copy our kernel relocation code to the control code page */ + memcpy((void *)reboot_code_buffer, relocate_new_kernel, + relocate_new_kernel_size); + + kexec_info(image); + flush_cache_all(); + + /* now call it */ + rnk = (relocate_new_kernel_t) reboot_code_buffer; + (*rnk)(page_list, reboot_code_buffer, image->start, vbr_reg); +} + diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index aac15e42d03..a4dc2b532e1 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c @@ -71,6 +71,16 @@ void cpu_idle(void) void machine_restart(char * __unused) { + +#ifdef CONFIG_KEXEC + struct kimage *image; + image = xchg(&kexec_image, 0); + if (image) { + machine_shutdown(); + machine_kexec(image); + } +#endif + /* SR.BL=1 and invoke address error to let CPU reset (manual reset) */ asm volatile("ldc %0, sr\n\t" "mov.l @%1, %0" : : "r" (0x10000000), "r" (0x80000001)); diff --git a/arch/sh/kernel/relocate_kernel.S b/arch/sh/kernel/relocate_kernel.S new file mode 100644 index 00000000000..b0695cffec6 --- /dev/null +++ b/arch/sh/kernel/relocate_kernel.S @@ -0,0 +1,102 @@ +/* + * relocate_kernel.S - put the kernel image in place to boot + * 2005.9.17 kogiidena@eggplant.ddo.jp + * + * LANDISK/sh4 is supported. Maybe, SH archtecture works well. + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ + +#include +#include + +#define PAGE_SIZE 4096 /* must be same value as in */ + + + .globl relocate_new_kernel +relocate_new_kernel: + /* r4 = indirection_page */ + /* r5 = reboot_code_buffer */ + /* r6 = start_address */ + /* r7 = vbr_reg */ + + mov.l 10f,r8 /* 4096 */ + mov.l 11f,r9 /* 0xa0000000 */ + + /* stack setting */ + add r8,r5 + mov r5,r15 + + bra 1f + mov r4,r0 /* cmd = indirection_page */ +0: + mov.l @r4+,r0 /* cmd = *ind++ */ + +1: /* addr = (cmd | 0xa0000000) & 0xfffffff0 */ + mov r0,r2 + or r9,r2 + mov #-16,r1 + and r1,r2 + + /* if(cmd & IND_DESTINATION) dst = addr */ + tst #1,r0 + bt 2f + bra 0b + mov r2,r5 + +2: /* else if(cmd & IND_INDIRECTION) ind = addr */ + tst #2,r0 + bt 3f + bra 0b + mov r2,r4 + +3: /* else if(cmd & IND_DONE) goto 6 */ + tst #4,r0 + bt 4f + bra 6f + nop + +4: /* else if(cmd & IND_SOURCE) memcpy(dst,addr,PAGE_SIZE) */ + tst #8,r0 + bt 0b + + mov r8,r3 + shlr2 r3 + shlr2 r3 +5: + dt r3 + mov.l @r2+,r1 /* 16n+0 */ + mov.l r1,@r5 + add #4,r5 + mov.l @r2+,r1 /* 16n+4 */ + mov.l r1,@r5 + add #4,r5 + mov.l @r2+,r1 /* 16n+8 */ + mov.l r1,@r5 + add #4,r5 + mov.l @r2+,r1 /* 16n+12 */ + mov.l r1,@r5 + add #4,r5 + bf 5b + + bra 0b + nop +6: +#ifdef CONFIG_SH_STANDARD_BIOS + ldc r7, vbr +#endif + jmp @r6 + nop + + .align 2 +10: + .long PAGE_SIZE +11: + .long 0xa0000000 + +relocate_new_kernel_end: + + .globl relocate_new_kernel_size +relocate_new_kernel_size: + .long relocate_new_kernel_end - relocate_new_kernel diff --git a/include/asm-sh/kexec.h b/include/asm-sh/kexec.h new file mode 100644 index 00000000000..9dfe59f6fcb --- /dev/null +++ b/include/asm-sh/kexec.h @@ -0,0 +1,33 @@ +#ifndef _SH_KEXEC_H +#define _SH_KEXEC_H + +/* + * KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return. + * I.e. Maximum page that is mapped directly into kernel memory, + * and kmap is not required. + * + * Someone correct me if FIXADDR_START - PAGEOFFSET is not the correct + * calculation for the amount of memory directly mappable into the + * kernel memory space. + */ + +/* Maximum physical address we can use pages from */ +#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL) +/* Maximum address we can reach in physical address mode */ +#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL) +/* Maximum address we can use for the control code buffer */ +#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE + +#define KEXEC_CONTROL_CODE_SIZE 4096 + +/* The native architecture */ +#define KEXEC_ARCH KEXEC_ARCH_SH + +#ifndef __ASSEMBLY__ + +extern void machine_shutdown(void); +extern void *crash_notes; + +#endif /* __ASSEMBLY__ */ + +#endif /* _SH_KEXEC_H */ diff --git a/include/linux/kexec.h b/include/linux/kexec.h index 94abc07cb16..a311f58c8a7 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h @@ -119,6 +119,7 @@ extern struct kimage *kexec_image; #define KEXEC_ARCH_PPC64 (21 << 16) #define KEXEC_ARCH_IA_64 (50 << 16) #define KEXEC_ARCH_S390 (22 << 16) +#define KEXEC_ARCH_SH (42 << 16) #define KEXEC_FLAGS (KEXEC_ON_CRASH) /* List of defined/legal kexec flags */ -- GitLab From bf3a00f88c926635932c91afd90b4a0907dfbe78 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 16 Jan 2006 22:14:14 -0800 Subject: [PATCH 377/465] [PATCH] sh: IRQ handler updates This moves the various IRQ controller drivers into a new subdirectory, and also extends the INTC2 IRQ handler to also deal with SH7760 and SH7780 interrupts, rather than just ST-40. The old CONFIG_SH_GENERIC has also been removed from the IRQ definitions, as new ports are expected to be based off of CONFIG_SH_UNKNOWN. Since there are plenty of incompatible machvecs, CONFIG_SH_GENERIC doesn't make sense anymore. Signed-off-by: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/sh/kernel/cpu/Makefile | 9 +- arch/sh/kernel/cpu/irq/Makefile | 7 + .../kernel/cpu/{irq_imask.c => irq/imask.c} | 16 +- arch/sh/kernel/cpu/irq/intc2.c | 284 ++++++++++++++ arch/sh/kernel/cpu/{irq_ipr.c => irq/ipr.c} | 217 +++-------- arch/sh/kernel/cpu/irq/pint.c | 169 +++++++++ arch/sh/kernel/cpu/sh4/irq_intc2.c | 222 ----------- arch/sh/kernel/irq.c | 64 ++-- include/asm-sh/irq-sh7780.h | 349 ++++++++++++++++++ include/asm-sh/irq.h | 143 +++---- 10 files changed, 963 insertions(+), 517 deletions(-) create mode 100644 arch/sh/kernel/cpu/irq/Makefile rename arch/sh/kernel/cpu/{irq_imask.c => irq/imask.c} (95%) create mode 100644 arch/sh/kernel/cpu/irq/intc2.c rename arch/sh/kernel/cpu/{irq_ipr.c => irq/ipr.c} (56%) create mode 100644 arch/sh/kernel/cpu/irq/pint.c delete mode 100644 arch/sh/kernel/cpu/sh4/irq_intc2.c create mode 100644 include/asm-sh/irq-sh7780.h diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile index cd43714df61..5bfc33bec5d 100644 --- a/arch/sh/kernel/cpu/Makefile +++ b/arch/sh/kernel/cpu/Makefile @@ -2,15 +2,12 @@ # Makefile for the Linux/SuperH CPU-specifc backends. # -obj-y := irq_ipr.o irq_imask.o init.o bus.o +obj-y += irq/ init.o bus.o clock.o obj-$(CONFIG_CPU_SH2) += sh2/ obj-$(CONFIG_CPU_SH3) += sh3/ obj-$(CONFIG_CPU_SH4) += sh4/ -obj-$(CONFIG_SH_RTC) += rtc.o +obj-$(CONFIG_SH_RTC) += rtc.o obj-$(CONFIG_UBC_WAKEUP) += ubc.o -obj-$(CONFIG_SH_ADC) += adc.o - -USE_STANDARD_AS_RULE := true - +obj-$(CONFIG_SH_ADC) += adc.o diff --git a/arch/sh/kernel/cpu/irq/Makefile b/arch/sh/kernel/cpu/irq/Makefile new file mode 100644 index 00000000000..e3cccea15e1 --- /dev/null +++ b/arch/sh/kernel/cpu/irq/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for the Linux/SuperH CPU-specifc IRQ handlers. +# +obj-y += ipr.o imask.o + +obj-$(CONFIG_CPU_HAS_PINT_IRQ) += pint.o +obj-$(CONFIG_CPU_HAS_INTC2_IRQ) += intc2.o diff --git a/arch/sh/kernel/cpu/irq_imask.c b/arch/sh/kernel/cpu/irq/imask.c similarity index 95% rename from arch/sh/kernel/cpu/irq_imask.c rename to arch/sh/kernel/cpu/irq/imask.c index a963d00a971..baed9a550d3 100644 --- a/arch/sh/kernel/cpu/irq_imask.c +++ b/arch/sh/kernel/cpu/irq/imask.c @@ -1,16 +1,12 @@ -/* $Id: irq_imask.c,v 1.1.2.1 2002/11/17 10:53:43 mrbrown Exp $ - * - * linux/arch/sh/kernel/irq_imask.c +/* + * arch/sh/kernel/cpu/irq/imask.c * * Copyright (C) 1999, 2000 Niibe Yutaka * * Simple interrupt handling using IMASK of SR register. * */ - /* NOTE: Will not work on level 15 */ - - #include #include #include @@ -19,13 +15,11 @@ #include #include #include - -#include -#include - #include #include #include +#include +#include /* Bitmap of IRQ masked */ static unsigned long imask_mask = 0x7fff; @@ -40,7 +34,7 @@ static void end_imask_irq(unsigned int irq); #define IMASK_PRIORITY 15 static unsigned int startup_imask_irq(unsigned int irq) -{ +{ /* Nothing to do */ return 0; /* never anything pending */ } diff --git a/arch/sh/kernel/cpu/irq/intc2.c b/arch/sh/kernel/cpu/irq/intc2.c new file mode 100644 index 00000000000..06e8afab32e --- /dev/null +++ b/arch/sh/kernel/cpu/irq/intc2.c @@ -0,0 +1,284 @@ +/* + * Interrupt handling for INTC2-based IRQ. + * + * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) + * Copyright (C) 2005, 2006 Paul Mundt (lethal@linux-sh.org) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * These are the "new Hitachi style" interrupts, as present on the + * Hitachi 7751, the STM ST40 STB1, SH7760, and SH7780. + */ + +#include +#include +#include +#include +#include +#include + +struct intc2_data { + unsigned char msk_offset; + unsigned char msk_shift; + + int (*clear_irq) (int); +}; + +static struct intc2_data intc2_data[NR_INTC2_IRQS]; + +static void enable_intc2_irq(unsigned int irq); +static void disable_intc2_irq(unsigned int irq); + +/* shutdown is same as "disable" */ +#define shutdown_intc2_irq disable_intc2_irq + +static void mask_and_ack_intc2(unsigned int); +static void end_intc2_irq(unsigned int irq); + +static unsigned int startup_intc2_irq(unsigned int irq) +{ + enable_intc2_irq(irq); + return 0; /* never anything pending */ +} + +static struct hw_interrupt_type intc2_irq_type = { + .typename = "INTC2-IRQ", + .startup = startup_intc2_irq, + .shutdown = shutdown_intc2_irq, + .enable = enable_intc2_irq, + .disable = disable_intc2_irq, + .ack = mask_and_ack_intc2, + .end = end_intc2_irq +}; + +static void disable_intc2_irq(unsigned int irq) +{ + int irq_offset = irq - INTC2_FIRST_IRQ; + int msk_shift, msk_offset; + + /* Sanity check */ + if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS)) + return; + + msk_shift = intc2_data[irq_offset].msk_shift; + msk_offset = intc2_data[irq_offset].msk_offset; + + ctrl_outl(1 << msk_shift, + INTC2_BASE + INTC2_INTMSK_OFFSET + msk_offset); +} + +static void enable_intc2_irq(unsigned int irq) +{ + int irq_offset = irq - INTC2_FIRST_IRQ; + int msk_shift, msk_offset; + + /* Sanity check */ + if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS)) + return; + + msk_shift = intc2_data[irq_offset].msk_shift; + msk_offset = intc2_data[irq_offset].msk_offset; + + ctrl_outl(1 << msk_shift, + INTC2_BASE + INTC2_INTMSKCLR_OFFSET + msk_offset); +} + +static void mask_and_ack_intc2(unsigned int irq) +{ + disable_intc2_irq(irq); +} + +static void end_intc2_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_intc2_irq(irq); + + if (unlikely(intc2_data[irq - INTC2_FIRST_IRQ].clear_irq)) + intc2_data[irq - INTC2_FIRST_IRQ].clear_irq(irq); +} + +/* + * Setup an INTC2 style interrupt. + * NOTE: Unlike IPR interrupts, parameters are not shifted by this code, + * allowing the use of the numbers straight out of the datasheet. + * For example: + * PIO1 which is INTPRI00[19,16] and INTMSK00[13] + * would be: ^ ^ ^ ^ + * | | | | + * make_intc2_irq(84, 0, 16, 0, 13); + */ +void make_intc2_irq(unsigned int irq, + unsigned int ipr_offset, unsigned int ipr_shift, + unsigned int msk_offset, unsigned int msk_shift, + unsigned int priority) +{ + int irq_offset = irq - INTC2_FIRST_IRQ; + unsigned int flags; + unsigned long ipr; + + if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS)) + return; + + disable_irq_nosync(irq); + + /* Fill the data we need */ + intc2_data[irq_offset].msk_offset = msk_offset; + intc2_data[irq_offset].msk_shift = msk_shift; + intc2_data[irq_offset].clear_irq = NULL; + + /* Set the priority level */ + local_irq_save(flags); + + ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET + ipr_offset); + ipr &= ~(0xf << ipr_shift); + ipr |= priority << ipr_shift; + ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET + ipr_offset); + + local_irq_restore(flags); + + irq_desc[irq].handler = &intc2_irq_type; + + disable_intc2_irq(irq); +} + +static struct intc2_init { + unsigned short irq; + unsigned char ipr_offset, ipr_shift; + unsigned char msk_offset, msk_shift; + unsigned char priority; +} intc2_init_data[] __initdata = { +#if defined(CONFIG_CPU_SUBTYPE_ST40) + {64, 0, 0, 0, 0, 13}, /* PCI serr */ + {65, 0, 4, 0, 1, 13}, /* PCI err */ + {66, 0, 4, 0, 2, 13}, /* PCI ad */ + {67, 0, 4, 0, 3, 13}, /* PCI pwd down */ + {72, 0, 8, 0, 5, 13}, /* DMAC INT0 */ + {73, 0, 8, 0, 6, 13}, /* DMAC INT1 */ + {74, 0, 8, 0, 7, 13}, /* DMAC INT2 */ + {75, 0, 8, 0, 8, 13}, /* DMAC INT3 */ + {76, 0, 8, 0, 9, 13}, /* DMAC INT4 */ + {78, 0, 8, 0, 11, 13}, /* DMAC ERR */ + {80, 0, 12, 0, 12, 13}, /* PIO0 */ + {84, 0, 16, 0, 13, 13}, /* PIO1 */ + {88, 0, 20, 0, 14, 13}, /* PIO2 */ + {112, 4, 0, 4, 0, 13}, /* Mailbox */ + #ifdef CONFIG_CPU_SUBTYPE_ST40GX1 + {116, 4, 4, 4, 4, 13}, /* SSC0 */ + {120, 4, 8, 4, 8, 13}, /* IR Blaster */ + {124, 4, 12, 4, 12, 13}, /* USB host */ + {128, 4, 16, 4, 16, 13}, /* Video processor BLITTER */ + {132, 4, 20, 4, 20, 13}, /* UART0 */ + {134, 4, 20, 4, 22, 13}, /* UART2 */ + {136, 4, 24, 4, 24, 13}, /* IO_PIO0 */ + {140, 4, 28, 4, 28, 13}, /* EMPI */ + {144, 8, 0, 8, 0, 13}, /* MAFE */ + {148, 8, 4, 8, 4, 13}, /* PWM */ + {152, 8, 8, 8, 8, 13}, /* SSC1 */ + {156, 8, 12, 8, 12, 13}, /* IO_PIO1 */ + {160, 8, 16, 8, 16, 13}, /* USB target */ + {164, 8, 20, 8, 20, 13}, /* UART1 */ + {168, 8, 24, 8, 24, 13}, /* Teletext */ + {172, 8, 28, 8, 28, 13}, /* VideoSync VTG */ + {173, 8, 28, 8, 29, 13}, /* VideoSync DVP0 */ + {174, 8, 28, 8, 30, 13}, /* VideoSync DVP1 */ +#endif +#elif defined(CONFIG_CPU_SUBTYPE_SH7760) +/* + * SH7760 INTC2-Style interrupts, vectors IRQ48-111 INTEVT 0x800-0xFE0 + */ + /* INTPRIO0 | INTMSK0 */ + {48, 0, 28, 0, 31, 3}, /* IRQ 4 */ + {49, 0, 24, 0, 30, 3}, /* IRQ 3 */ + {50, 0, 20, 0, 29, 3}, /* IRQ 2 */ + {51, 0, 16, 0, 28, 3}, /* IRQ 1 */ + /* 52-55 (INTEVT 0x880-0x8E0) unused/reserved */ + /* INTPRIO4 | INTMSK0 */ + {56, 4, 28, 0, 25, 3}, /* HCAN2_CHAN0 */ + {57, 4, 24, 0, 24, 3}, /* HCAN2_CHAN1 */ + {58, 4, 20, 0, 23, 3}, /* I2S_CHAN0 */ + {59, 4, 16, 0, 22, 3}, /* I2S_CHAN1 */ + {60, 4, 12, 0, 21, 3}, /* AC97_CHAN0 */ + {61, 4, 8, 0, 20, 3}, /* AC97_CHAN1 */ + {62, 4, 4, 0, 19, 3}, /* I2C_CHAN0 */ + {63, 4, 0, 0, 18, 3}, /* I2C_CHAN1 */ + /* INTPRIO8 | INTMSK0 */ + {52, 8, 16, 0, 11, 3}, /* SCIF0_ERI_IRQ */ + {53, 8, 16, 0, 10, 3}, /* SCIF0_RXI_IRQ */ + {54, 8, 16, 0, 9, 3}, /* SCIF0_BRI_IRQ */ + {55, 8, 16, 0, 8, 3}, /* SCIF0_TXI_IRQ */ + {64, 8, 28, 0, 17, 3}, /* USBHI_IRQ */ + {65, 8, 24, 0, 16, 3}, /* LCDC */ + /* 66, 67 unused */ + {68, 8, 20, 0, 14, 13}, /* DMABRGI0_IRQ */ + {69, 8, 20, 0, 13, 13}, /* DMABRGI1_IRQ */ + {70, 8, 20, 0, 12, 13}, /* DMABRGI2_IRQ */ + /* 71 unused */ + {72, 8, 12, 0, 7, 3}, /* SCIF1_ERI_IRQ */ + {73, 8, 12, 0, 6, 3}, /* SCIF1_RXI_IRQ */ + {74, 8, 12, 0, 5, 3}, /* SCIF1_BRI_IRQ */ + {75, 8, 12, 0, 4, 3}, /* SCIF1_TXI_IRQ */ + {76, 8, 8, 0, 3, 3}, /* SCIF2_ERI_IRQ */ + {77, 8, 8, 0, 2, 3}, /* SCIF2_RXI_IRQ */ + {78, 8, 8, 0, 1, 3}, /* SCIF2_BRI_IRQ */ + {79, 8, 8, 0, 0, 3}, /* SCIF2_TXI_IRQ */ + /* | INTMSK4 */ + {80, 8, 4, 4, 23, 3}, /* SIM_ERI */ + {81, 8, 4, 4, 22, 3}, /* SIM_RXI */ + {82, 8, 4, 4, 21, 3}, /* SIM_TXI */ + {83, 8, 4, 4, 20, 3}, /* SIM_TEI */ + {84, 8, 0, 4, 19, 3}, /* HSPII */ + /* INTPRIOC | INTMSK4 */ + /* 85-87 unused/reserved */ + {88, 12, 20, 4, 18, 3}, /* MMCI0 */ + {89, 12, 20, 4, 17, 3}, /* MMCI1 */ + {90, 12, 20, 4, 16, 3}, /* MMCI2 */ + {91, 12, 20, 4, 15, 3}, /* MMCI3 */ + {92, 12, 12, 4, 6, 3}, /* MFI (unsure, bug? in my 7760 manual*/ + /* 93-107 reserved/undocumented */ + {108,12, 4, 4, 1, 3}, /* ADC */ + {109,12, 0, 4, 0, 3}, /* CMTI */ + /* 110-111 reserved/unused */ +#elif defined(CONFIG_CPU_SUBTYPE_SH7780) + { TIMER_IRQ, 0, 24, 0, INTC_TMU0_MSK, 2}, +#ifdef CONFIG_SH_RTC + { RTC_IRQ, 4, 0, 0, INTC_RTC_MSK, TIMER_PRIORITY }, +#endif + { SCIF0_ERI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, + { SCIF0_RXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, + { SCIF0_BRI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, + { SCIF0_TXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, + + { SCIF1_ERI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, + { SCIF1_RXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, + { SCIF1_BRI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, + { SCIF1_TXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, + + { PCIC0_IRQ, 0x10, 8, 0, INTC_PCIC0_MSK, PCIC0_PRIORITY }, + { PCIC1_IRQ, 0x10, 0, 0, INTC_PCIC1_MSK, PCIC1_PRIORITY }, + { PCIC2_IRQ, 0x14, 24, 0, INTC_PCIC2_MSK, PCIC2_PRIORITY }, + { PCIC3_IRQ, 0x14, 16, 0, INTC_PCIC3_MSK, PCIC3_PRIORITY }, + { PCIC4_IRQ, 0x14, 8, 0, INTC_PCIC4_MSK, PCIC4_PRIORITY }, +#endif +}; + +void __init init_IRQ_intc2(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(intc2_init_data); i++) { + struct intc2_init *p = intc2_init_data + i; + make_intc2_irq(p->irq, p->ipr_offset, p->ipr_shift, + p-> msk_offset, p->msk_shift, p->priority); + } +} + +/* Adds a termination callback to the interrupt */ +void intc2_add_clear_irq(int irq, int (*fn)(int)) +{ + if (unlikely(irq < INTC2_FIRST_IRQ)) + return; + + intc2_data[irq - INTC2_FIRST_IRQ].clear_irq = fn; +} + diff --git a/arch/sh/kernel/cpu/irq_ipr.c b/arch/sh/kernel/cpu/irq/ipr.c similarity index 56% rename from arch/sh/kernel/cpu/irq_ipr.c rename to arch/sh/kernel/cpu/irq/ipr.c index 71f92096132..fdbd718ae5c 100644 --- a/arch/sh/kernel/cpu/irq_ipr.c +++ b/arch/sh/kernel/cpu/irq/ipr.c @@ -1,6 +1,5 @@ -/* $Id: irq_ipr.c,v 1.1.2.1 2002/11/17 10:53:43 mrbrown Exp $ - * - * linux/arch/sh/kernel/irq_ipr.c +/* + * arch/sh/kernel/cpu/irq/ipr.c * * Copyright (C) 1999 Niibe Yutaka & Takeshi Yaegashi * Copyright (C) 2000 Kazumoto Kojima @@ -109,7 +108,8 @@ static void end_ipr_irq(unsigned int irq) enable_ipr_irq(irq); } -void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority) +void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, + int priority, int maskpos) { disable_irq_nosync(irq); ipr_data[irq].addr = addr; @@ -120,126 +120,47 @@ void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority) disable_ipr_irq(irq); } -#if defined(CONFIG_CPU_SUBTYPE_SH7705) || \ - defined(CONFIG_CPU_SUBTYPE_SH7707) || \ - defined(CONFIG_CPU_SUBTYPE_SH7709) -static unsigned char pint_map[256]; -static unsigned long portcr_mask = 0; - -static void enable_pint_irq(unsigned int irq); -static void disable_pint_irq(unsigned int irq); - -/* shutdown is same as "disable" */ -#define shutdown_pint_irq disable_pint_irq - -static void mask_and_ack_pint(unsigned int); -static void end_pint_irq(unsigned int irq); - -static unsigned int startup_pint_irq(unsigned int irq) -{ - enable_pint_irq(irq); - return 0; /* never anything pending */ -} - -static struct hw_interrupt_type pint_irq_type = { - .typename = "PINT-IRQ", - .startup = startup_pint_irq, - .shutdown = shutdown_pint_irq, - .enable = enable_pint_irq, - .disable = disable_pint_irq, - .ack = mask_and_ack_pint, - .end = end_pint_irq -}; - -static void disable_pint_irq(unsigned int irq) -{ - unsigned long val, flags; - - local_irq_save(flags); - val = ctrl_inw(INTC_INTER); - val &= ~(1 << (irq - PINT_IRQ_BASE)); - ctrl_outw(val, INTC_INTER); /* disable PINTn */ - portcr_mask &= ~(3 << (irq - PINT_IRQ_BASE)*2); - local_irq_restore(flags); -} - -static void enable_pint_irq(unsigned int irq) -{ - unsigned long val, flags; - - local_irq_save(flags); - val = ctrl_inw(INTC_INTER); - val |= 1 << (irq - PINT_IRQ_BASE); - ctrl_outw(val, INTC_INTER); /* enable PINTn */ - portcr_mask |= 3 << (irq - PINT_IRQ_BASE)*2; - local_irq_restore(flags); -} - -static void mask_and_ack_pint(unsigned int irq) -{ - disable_pint_irq(irq); -} - -static void end_pint_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_pint_irq(irq); -} - -void make_pint_irq(unsigned int irq) -{ - disable_irq_nosync(irq); - irq_desc[irq].handler = &pint_irq_type; - disable_pint_irq(irq); -} -#endif - void __init init_IRQ(void) { -#if defined(CONFIG_CPU_SUBTYPE_SH7705) || \ - defined(CONFIG_CPU_SUBTYPE_SH7707) || \ - defined(CONFIG_CPU_SUBTYPE_SH7709) - int i; -#endif - - make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY); - make_ipr_irq(TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY); +#ifndef CONFIG_CPU_SUBTYPE_SH7780 + make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY, 0); + make_ipr_irq(TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY, 0); #if defined(CONFIG_SH_RTC) - make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY); + make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY, 0); #endif #ifdef SCI_ERI_IRQ - make_ipr_irq(SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); - make_ipr_irq(SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); - make_ipr_irq(SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); + make_ipr_irq(SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY, 0); + make_ipr_irq(SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY, 0); + make_ipr_irq(SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY, 0); #endif #ifdef SCIF1_ERI_IRQ - make_ipr_irq(SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY); - make_ipr_irq(SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY); - make_ipr_irq(SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY); - make_ipr_irq(SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY); + make_ipr_irq(SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0); + make_ipr_irq(SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0); + make_ipr_irq(SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0); + make_ipr_irq(SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0); #endif #if defined(CONFIG_CPU_SUBTYPE_SH7300) - make_ipr_irq(SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY); - make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY); - make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY); - make_ipr_irq(VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY); + make_ipr_irq(SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY, 0); + make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY, 0); + make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY, 0); + make_ipr_irq(VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY, 0); #endif #ifdef SCIF_ERI_IRQ - make_ipr_irq(SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); - make_ipr_irq(SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); - make_ipr_irq(SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); - make_ipr_irq(SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); + make_ipr_irq(SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0); + make_ipr_irq(SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0); + make_ipr_irq(SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0); + make_ipr_irq(SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0); #endif #ifdef IRDA_ERI_IRQ - make_ipr_irq(IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); - make_ipr_irq(IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); - make_ipr_irq(IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); - make_ipr_irq(IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); + make_ipr_irq(IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0); + make_ipr_irq(IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0); + make_ipr_irq(IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0); + make_ipr_irq(IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0); #endif #if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \ @@ -254,86 +175,32 @@ void __init init_IRQ(void) * You should set corresponding bits of PFC to "00" * to enable these interrupts. */ - make_ipr_irq(IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY); - make_ipr_irq(IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY); - make_ipr_irq(IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY); - make_ipr_irq(IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY); - make_ipr_irq(IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY); - make_ipr_irq(IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY); -#if !defined(CONFIG_CPU_SUBTYPE_SH7300) - make_ipr_irq(PINT0_IRQ, PINT0_IPR_ADDR, PINT0_IPR_POS, PINT0_PRIORITY); - make_ipr_irq(PINT8_IRQ, PINT8_IPR_ADDR, PINT8_IPR_POS, PINT8_PRIORITY); - enable_ipr_irq(PINT0_IRQ); - enable_ipr_irq(PINT8_IRQ); + make_ipr_irq(IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY, 0); + make_ipr_irq(IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY, 0); + make_ipr_irq(IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY, 0); + make_ipr_irq(IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY, 0); + make_ipr_irq(IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY, 0); + make_ipr_irq(IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY, 0); +#endif +#endif - for(i = 0; i < 16; i++) - make_pint_irq(PINT_IRQ_BASE + i); - for(i = 0; i < 256; i++) - { - if(i & 1) pint_map[i] = 0; - else if(i & 2) pint_map[i] = 1; - else if(i & 4) pint_map[i] = 2; - else if(i & 8) pint_map[i] = 3; - else if(i & 0x10) pint_map[i] = 4; - else if(i & 0x20) pint_map[i] = 5; - else if(i & 0x40) pint_map[i] = 6; - else if(i & 0x80) pint_map[i] = 7; - } -#endif /* !CONFIG_CPU_SUBTYPE_SH7300 */ -#endif /* CONFIG_CPU_SUBTYPE_SH7707 || CONFIG_CPU_SUBTYPE_SH7709 || CONFIG_CPU_SUBTYPE_SH7300*/ +#ifdef CONFIG_CPU_HAS_PINT_IRQ + init_IRQ_pint(); +#endif -#ifdef CONFIG_CPU_SUBTYPE_ST40 +#ifdef CONFIG_CPU_HAS_INTC2_IRQ init_IRQ_intc2(); #endif - /* Perform the machine specific initialisation */ - if (sh_mv.mv_init_irq != NULL) { + if (sh_mv.mv_init_irq != NULL) sh_mv.mv_init_irq(); - } } -#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \ - defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705) + +#if !defined(CONFIG_CPU_HAS_PINT_IRQ) int ipr_irq_demux(int irq) { -#if !defined(CONFIG_CPU_SUBTYPE_SH7300) - unsigned long creg, dreg, d, sav; - - if(irq == PINT0_IRQ) - { -#if defined(CONFIG_CPU_SUBTYPE_SH7707) - creg = PORT_PACR; - dreg = PORT_PADR; -#else - creg = PORT_PCCR; - dreg = PORT_PCDR; -#endif - sav = ctrl_inw(creg); - ctrl_outw(sav | portcr_mask, creg); - d = (~ctrl_inb(dreg) ^ ctrl_inw(INTC_ICR2)) & ctrl_inw(INTC_INTER) & 0xff; - ctrl_outw(sav, creg); - if(d == 0) return irq; - return PINT_IRQ_BASE + pint_map[d]; - } - else if(irq == PINT8_IRQ) - { -#if defined(CONFIG_CPU_SUBTYPE_SH7707) - creg = PORT_PBCR; - dreg = PORT_PBDR; -#else - creg = PORT_PFCR; - dreg = PORT_PFDR; -#endif - sav = ctrl_inw(creg); - ctrl_outw(sav | (portcr_mask >> 16), creg); - d = (~ctrl_inb(dreg) ^ (ctrl_inw(INTC_ICR2) >> 8)) & (ctrl_inw(INTC_INTER) >> 8) & 0xff; - ctrl_outw(sav, creg); - if(d == 0) return irq; - return PINT_IRQ_BASE + 8 + pint_map[d]; - } -#endif return irq; } #endif EXPORT_SYMBOL(make_ipr_irq); - diff --git a/arch/sh/kernel/cpu/irq/pint.c b/arch/sh/kernel/cpu/irq/pint.c new file mode 100644 index 00000000000..95d6024fe1a --- /dev/null +++ b/arch/sh/kernel/cpu/irq/pint.c @@ -0,0 +1,169 @@ +/* + * arch/sh/kernel/cpu/irq/pint.c - Interrupt handling for PINT-based IRQs. + * + * Copyright (C) 1999 Niibe Yutaka & Takeshi Yaegashi + * Copyright (C) 2000 Kazumoto Kojima + * Copyright (C) 2003 Takashi Kusuda + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include + +#include +#include +#include + +static unsigned char pint_map[256]; +static unsigned long portcr_mask; + +static void enable_pint_irq(unsigned int irq); +static void disable_pint_irq(unsigned int irq); + +/* shutdown is same as "disable" */ +#define shutdown_pint_irq disable_pint_irq + +static void mask_and_ack_pint(unsigned int); +static void end_pint_irq(unsigned int irq); + +static unsigned int startup_pint_irq(unsigned int irq) +{ + enable_pint_irq(irq); + return 0; /* never anything pending */ +} + +static struct hw_interrupt_type pint_irq_type = { + .typename = "PINT-IRQ", + .startup = startup_pint_irq, + .shutdown = shutdown_pint_irq, + .enable = enable_pint_irq, + .disable = disable_pint_irq, + .ack = mask_and_ack_pint, + .end = end_pint_irq +}; + +static void disable_pint_irq(unsigned int irq) +{ + unsigned long val, flags; + + local_irq_save(flags); + val = ctrl_inw(INTC_INTER); + val &= ~(1 << (irq - PINT_IRQ_BASE)); + ctrl_outw(val, INTC_INTER); /* disable PINTn */ + portcr_mask &= ~(3 << (irq - PINT_IRQ_BASE)*2); + local_irq_restore(flags); +} + +static void enable_pint_irq(unsigned int irq) +{ + unsigned long val, flags; + + local_irq_save(flags); + val = ctrl_inw(INTC_INTER); + val |= 1 << (irq - PINT_IRQ_BASE); + ctrl_outw(val, INTC_INTER); /* enable PINTn */ + portcr_mask |= 3 << (irq - PINT_IRQ_BASE)*2; + local_irq_restore(flags); +} + +static void mask_and_ack_pint(unsigned int irq) +{ + disable_pint_irq(irq); +} + +static void end_pint_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_pint_irq(irq); +} + +void make_pint_irq(unsigned int irq) +{ + disable_irq_nosync(irq); + irq_desc[irq].handler = &pint_irq_type; + disable_pint_irq(irq); +} + +void __init init_IRQ_pint(void) +{ + int i; + + make_ipr_irq(PINT0_IRQ, PINT0_IPR_ADDR, PINT0_IPR_POS, PINT0_PRIORITY); + make_ipr_irq(PINT8_IRQ, PINT8_IPR_ADDR, PINT8_IPR_POS, PINT8_PRIORITY); + + enable_irq(PINT0_IRQ); + enable_irq(PINT8_IRQ); + + for(i = 0; i < 16; i++) + make_pint_irq(PINT_IRQ_BASE + i); + + for(i = 0; i < 256; i++) { + if (i & 1) + pint_map[i] = 0; + else if (i & 2) + pint_map[i] = 1; + else if (i & 4) + pint_map[i] = 2; + else if (i & 8) + pint_map[i] = 3; + else if (i & 0x10) + pint_map[i] = 4; + else if (i & 0x20) + pint_map[i] = 5; + else if (i & 0x40) + pint_map[i] = 6; + else if (i & 0x80) + pint_map[i] = 7; + } +} + +int ipr_irq_demux(int irq) +{ + unsigned long creg, dreg, d, sav; + + if (irq == PINT0_IRQ) { +#if defined(CONFIG_CPU_SUBTYPE_SH7707) + creg = PORT_PACR; + dreg = PORT_PADR; +#else + creg = PORT_PCCR; + dreg = PORT_PCDR; +#endif + sav = ctrl_inw(creg); + ctrl_outw(sav | portcr_mask, creg); + d = (~ctrl_inb(dreg) ^ ctrl_inw(INTC_ICR2)) & + ctrl_inw(INTC_INTER) & 0xff; + ctrl_outw(sav, creg); + + if (d == 0) + return irq; + + return PINT_IRQ_BASE + pint_map[d]; + } else if (irq == PINT8_IRQ) { +#if defined(CONFIG_CPU_SUBTYPE_SH7707) + creg = PORT_PBCR; + dreg = PORT_PBDR; +#else + creg = PORT_PFCR; + dreg = PORT_PFDR; +#endif + sav = ctrl_inw(creg); + ctrl_outw(sav | (portcr_mask >> 16), creg); + d = (~ctrl_inb(dreg) ^ (ctrl_inw(INTC_ICR2) >> 8)) & + (ctrl_inw(INTC_INTER) >> 8) & 0xff; + ctrl_outw(sav, creg); + + if (d == 0) + return irq; + + return PINT_IRQ_BASE + 8 + pint_map[d]; + } + + return irq; +} + diff --git a/arch/sh/kernel/cpu/sh4/irq_intc2.c b/arch/sh/kernel/cpu/sh4/irq_intc2.c deleted file mode 100644 index f6b16ba0193..00000000000 --- a/arch/sh/kernel/cpu/sh4/irq_intc2.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * linux/arch/sh/kernel/irq_intc2.c - * - * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Interrupt handling for INTC2-based IRQ. - * - * These are the "new Hitachi style" interrupts, as present on the - * Hitachi 7751 and the STM ST40 STB1. - */ - -#include -#include -#include - -#include -#include -#include - - -struct intc2_data { - unsigned char msk_offset; - unsigned char msk_shift; -#ifdef CONFIG_CPU_SUBTYPE_ST40 - int (*clear_irq) (int); -#endif -}; - - -static struct intc2_data intc2_data[NR_INTC2_IRQS]; - -static void enable_intc2_irq(unsigned int irq); -static void disable_intc2_irq(unsigned int irq); - -/* shutdown is same as "disable" */ -#define shutdown_intc2_irq disable_intc2_irq - -static void mask_and_ack_intc2(unsigned int); -static void end_intc2_irq(unsigned int irq); - -static unsigned int startup_intc2_irq(unsigned int irq) -{ - enable_intc2_irq(irq); - return 0; /* never anything pending */ -} - -static struct hw_interrupt_type intc2_irq_type = { - .typename = "INTC2-IRQ", - .startup = startup_intc2_irq, - .shutdown = shutdown_intc2_irq, - .enable = enable_intc2_irq, - .disable = disable_intc2_irq, - .ack = mask_and_ack_intc2, - .end = end_intc2_irq -}; - -static void disable_intc2_irq(unsigned int irq) -{ - int irq_offset = irq - INTC2_FIRST_IRQ; - int msk_shift, msk_offset; - - // Sanity check - if((irq_offset<0) || (irq_offset>=NR_INTC2_IRQS)) - return; - - msk_shift = intc2_data[irq_offset].msk_shift; - msk_offset = intc2_data[irq_offset].msk_offset; - - ctrl_outl(1<=NR_INTC2_IRQS)) - return; - - msk_shift = intc2_data[irq_offset].msk_shift; - msk_offset = intc2_data[irq_offset].msk_offset; - - ctrl_outl(1<=NR_INTC2_IRQS)) - return; - - disable_irq_nosync(irq); - - /* Fill the data we need */ - intc2_data[irq_offset].msk_offset = msk_offset; - intc2_data[irq_offset].msk_shift = msk_shift; -#ifdef CONFIG_CPU_SUBTYPE_ST40 - intc2_data[irq_offset].clear_irq = NULL; -#endif - - /* Set the priority level */ - local_irq_save(flags); - - ipr=ctrl_inl(INTC2_BASE+INTC2_INTPRI_OFFSET+ipr_offset); - ipr&=~(0xf<irq, p->ipr_offset, p->ipr_shift, - p-> msk_offset, p->msk_shift, 13); - } -} - -/* Adds a termination callback to the interrupt */ -void intc2_add_clear_irq(int irq, int (*fn)(int)) -{ - if (irq < INTC2_FIRST_IRQ) - return; - - intc2_data[irq - INTC2_FIRST_IRQ].clear_irq = fn; -} - -#endif /* CONFIG_CPU_SUBTYPE_ST40 */ diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index 54c171225b7..6883c00728c 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -8,38 +8,13 @@ * SuperH version: Copyright (C) 1999 Niibe Yutaka */ -/* - * IRQs are in fact implemented a bit like signal handlers for the kernel. - * Naturally it's not a 1:1 relation, but there are similarities. - */ - -#include -#include -#include -#include -#include -#include -#include -#include +#include #include -#include -#include -#include -#include -#include -#include -#include +#include #include -#include -#include - -#include -#include -#include -#include #include -#include - +#include +#include /* * 'what should we do if we get a hw irq event on an illegal vector'. @@ -66,7 +41,7 @@ int show_interrupts(struct seq_file *p, void *v) seq_putc(p, '\n'); } - if (i < ACTUAL_NR_IRQS) { + if (i < NR_IRQS) { spin_lock_irqsave(&irq_desc[i].lock, flags); action = irq_desc[i].action; if (!action) @@ -86,19 +61,32 @@ unlock: } #endif + asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, struct pt_regs regs) -{ - int irq; +{ + int irq = r4; irq_enter(); - asm volatile("stc r2_bank, %0\n\t" - "shlr2 %0\n\t" - "shlr2 %0\n\t" - "shlr %0\n\t" - "add #-16, %0\n\t" - :"=z" (irq)); + +#ifdef CONFIG_CPU_HAS_INTEVT + __asm__ __volatile__ ( +#ifdef CONFIG_CPU_HAS_SR_RB + "stc r2_bank, %0\n\t" +#else + "mov.l @%1, %0\n\t" +#endif + "shlr2 %0\n\t" + "shlr2 %0\n\t" + "shlr %0\n\t" + "add #-16, %0\n\t" + : "=z" (irq), "=r" (r4) + : "1" (INTEVT) + : "memory" + ); +#endif + irq = irq_demux(irq); __do_IRQ(irq, ®s); irq_exit(); diff --git a/include/asm-sh/irq-sh7780.h b/include/asm-sh/irq-sh7780.h new file mode 100644 index 00000000000..8c8ca128108 --- /dev/null +++ b/include/asm-sh/irq-sh7780.h @@ -0,0 +1,349 @@ +#ifndef __ASM_SH_IRQ_SH7780_H +#define __ASM_SH_IRQ_SH7780_H + +/* + * linux/include/asm-sh/irq-sh7780.h + * + * Copyright (C) 2004 Takashi SHUDO + */ + +#ifdef CONFIG_IDE +# ifndef IRQ_CFCARD +# define IRQ_CFCARD 14 +# endif +# ifndef IRQ_PCMCIA +# define IRQ_PCMCIA 15 +# endif +#endif + +#define INTC_BASE 0xffd00000 +#define INTC_ICR0 (INTC_BASE+0x0) +#define INTC_ICR1 (INTC_BASE+0x1c) +#define INTC_INTPRI (INTC_BASE+0x10) +#define INTC_INTREQ (INTC_BASE+0x24) +#define INTC_INTMSK0 (INTC_BASE+0x44) +#define INTC_INTMSK1 (INTC_BASE+0x48) +#define INTC_INTMSK2 (INTC_BASE+0x40080) +#define INTC_INTMSKCLR0 (INTC_BASE+0x64) +#define INTC_INTMSKCLR1 (INTC_BASE+0x68) +#define INTC_INTMSKCLR2 (INTC_BASE+0x40084) +#define INTC_NMIFCR (INTC_BASE+0xc0) +#define INTC_USERIMASK (INTC_BASE+0x30000) + +#define INTC_INT2PRI0 (INTC_BASE+0x40000) +#define INTC_INT2PRI1 (INTC_BASE+0x40004) +#define INTC_INT2PRI2 (INTC_BASE+0x40008) +#define INTC_INT2PRI3 (INTC_BASE+0x4000c) +#define INTC_INT2PRI4 (INTC_BASE+0x40010) +#define INTC_INT2PRI5 (INTC_BASE+0x40014) +#define INTC_INT2PRI6 (INTC_BASE+0x40018) +#define INTC_INT2PRI7 (INTC_BASE+0x4001c) +#define INTC_INT2A0 (INTC_BASE+0x40030) +#define INTC_INT2A1 (INTC_BASE+0x40034) +#define INTC_INT2MSKR (INTC_BASE+0x40038) +#define INTC_INT2MSKCR (INTC_BASE+0x4003c) +#define INTC_INT2B0 (INTC_BASE+0x40040) +#define INTC_INT2B1 (INTC_BASE+0x40044) +#define INTC_INT2B2 (INTC_BASE+0x40048) +#define INTC_INT2B3 (INTC_BASE+0x4004c) +#define INTC_INT2B4 (INTC_BASE+0x40050) +#define INTC_INT2B5 (INTC_BASE+0x40054) +#define INTC_INT2B6 (INTC_BASE+0x40058) +#define INTC_INT2B7 (INTC_BASE+0x4005c) +#define INTC_INT2GPIC (INTC_BASE+0x40090) +/* + NOTE: + *_IRQ = (INTEVT2 - 0x200)/0x20 +*/ +/* IRQ 0-7 line external int*/ +#define IRQ0_IRQ 2 +#define IRQ0_IPR_ADDR INTC_INTPRI +#define IRQ0_IPR_POS 7 +#define IRQ0_PRIORITY 2 + +#define IRQ1_IRQ 4 +#define IRQ1_IPR_ADDR INTC_INTPRI +#define IRQ1_IPR_POS 6 +#define IRQ1_PRIORITY 2 + +#define IRQ2_IRQ 6 +#define IRQ2_IPR_ADDR INTC_INTPRI +#define IRQ2_IPR_POS 5 +#define IRQ2_PRIORITY 2 + +#define IRQ3_IRQ 8 +#define IRQ3_IPR_ADDR INTC_INTPRI +#define IRQ3_IPR_POS 4 +#define IRQ3_PRIORITY 2 + +#define IRQ4_IRQ 10 +#define IRQ4_IPR_ADDR INTC_INTPRI +#define IRQ4_IPR_POS 3 +#define IRQ4_PRIORITY 2 + +#define IRQ5_IRQ 12 +#define IRQ5_IPR_ADDR INTC_INTPRI +#define IRQ5_IPR_POS 2 +#define IRQ5_PRIORITY 2 + +#define IRQ6_IRQ 14 +#define IRQ6_IPR_ADDR INTC_INTPRI +#define IRQ6_IPR_POS 1 +#define IRQ6_PRIORITY 2 + +#define IRQ7_IRQ 0 +#define IRQ7_IPR_ADDR INTC_INTPRI +#define IRQ7_IPR_POS 0 +#define IRQ7_PRIORITY 2 + +/* TMU */ +/* ch0 */ +#define TMU_IRQ 28 +#define TMU_IPR_ADDR INTC_INT2PRI0 +#define TMU_IPR_POS 3 +#define TMU_PRIORITY 2 + +#define TIMER_IRQ 28 +#define TIMER_IPR_ADDR INTC_INT2PRI0 +#define TIMER_IPR_POS 3 +#define TIMER_PRIORITY 2 + +/* ch 1*/ +#define TMU_CH1_IRQ 29 +#define TMU_CH1_IPR_ADDR INTC_INT2PRI0 +#define TMU_CH1_IPR_POS 2 +#define TMU_CH1_PRIORITY 2 + +#define TIMER1_IRQ 29 +#define TIMER1_IPR_ADDR INTC_INT2PRI0 +#define TIMER1_IPR_POS 2 +#define TIMER1_PRIORITY 2 + +/* ch 2*/ +#define TMU_CH2_IRQ 30 +#define TMU_CH2_IPR_ADDR INTC_INT2PRI0 +#define TMU_CH2_IPR_POS 1 +#define TMU_CH2_PRIORITY 2 +/* ch 2 Input capture */ +#define TMU_CH2IC_IRQ 31 +#define TMU_CH2IC_IPR_ADDR INTC_INT2PRI0 +#define TMU_CH2IC_IPR_POS 0 +#define TMU_CH2IC_PRIORITY 2 +/* ch 3 */ +#define TMU_CH3_IRQ 96 +#define TMU_CH3_IPR_ADDR INTC_INT2PRI1 +#define TMU_CH3_IPR_POS 3 +#define TMU_CH3_PRIORITY 2 +/* ch 4 */ +#define TMU_CH4_IRQ 97 +#define TMU_CH4_IPR_ADDR INTC_INT2PRI1 +#define TMU_CH4_IPR_POS 2 +#define TMU_CH4_PRIORITY 2 +/* ch 5*/ +#define TMU_CH5_IRQ 98 +#define TMU_CH5_IPR_ADDR INTC_INT2PRI1 +#define TMU_CH5_IPR_POS 1 +#define TMU_CH5_PRIORITY 2 + +#define RTC_IRQ 22 +#define RTC_IPR_ADDR INTC_INT2PRI1 +#define RTC_IPR_POS 0 +#define RTC_PRIORITY TIMER_PRIORITY + +/* SCIF0 */ +#define SCIF0_ERI_IRQ 40 +#define SCIF0_RXI_IRQ 41 +#define SCIF0_BRI_IRQ 42 +#define SCIF0_TXI_IRQ 43 +#define SCIF0_IPR_ADDR INTC_INT2PRI2 +#define SCIF0_IPR_POS 3 +#define SCIF0_PRIORITY 3 + +/* SCIF1 */ +#define SCIF1_ERI_IRQ 76 +#define SCIF1_RXI_IRQ 77 +#define SCIF1_BRI_IRQ 78 +#define SCIF1_TXI_IRQ 79 +#define SCIF1_IPR_ADDR INTC_INT2PRI2 +#define SCIF1_IPR_POS 2 +#define SCIF1_PRIORITY 3 + +#define WDT_IRQ 27 +#define WDT_IPR_ADDR INTC_INT2PRI2 +#define WDT_IPR_POS 1 +#define WDT_PRIORITY 2 + +/* DMAC(0) */ +#define DMINT0_IRQ 34 +#define DMINT1_IRQ 35 +#define DMINT2_IRQ 36 +#define DMINT3_IRQ 37 +#define DMINT4_IRQ 44 +#define DMINT5_IRQ 45 +#define DMINT6_IRQ 46 +#define DMINT7_IRQ 47 +#define DMAE_IRQ 38 +#define DMA0_IPR_ADDR INTC_INT2PRI3 +#define DMA0_IPR_POS 2 +#define DMA0_PRIORITY 7 + +/* DMAC(1) */ +#define DMINT8_IRQ 92 +#define DMINT9_IRQ 93 +#define DMINT10_IRQ 94 +#define DMINT11_IRQ 95 +#define DMA1_IPR_ADDR INTC_INT2PRI3 +#define DMA1_IPR_POS 1 +#define DMA1_PRIORITY 7 + +#define DMTE0_IRQ DMINT0_IRQ +#define DMTE4_IRQ DMINT4_IRQ +#define DMA_IPR_ADDR DMA0_IPR_ADDR +#define DMA_IPR_POS DMA0_IPR_POS +#define DMA_PRIORITY DMA0_PRIORITY + +/* CMT */ +#define CMT_IRQ 56 +#define CMT_IPR_ADDR INTC_INT2PRI4 +#define CMT_IPR_POS 3 +#define CMT_PRIORITY 0 + +/* HAC */ +#define HAC_IRQ 60 +#define HAC_IPR_ADDR INTC_INT2PRI4 +#define HAC_IPR_POS 2 +#define CMT_PRIORITY 0 + +/* PCIC(0) */ +#define PCIC0_IRQ 64 +#define PCIC0_IPR_ADDR INTC_INT2PRI4 +#define PCIC0_IPR_POS 1 +#define PCIC0_PRIORITY 2 + +/* PCIC(1) */ +#define PCIC1_IRQ 65 +#define PCIC1_IPR_ADDR INTC_INT2PRI4 +#define PCIC1_IPR_POS 0 +#define PCIC1_PRIORITY 2 + +/* PCIC(2) */ +#define PCIC2_IRQ 66 +#define PCIC2_IPR_ADDR INTC_INT2PRI5 +#define PCIC2_IPR_POS 3 +#define PCIC2_PRIORITY 2 + +/* PCIC(3) */ +#define PCIC3_IRQ 67 +#define PCIC3_IPR_ADDR INTC_INT2PRI5 +#define PCIC3_IPR_POS 2 +#define PCIC3_PRIORITY 2 + +/* PCIC(4) */ +#define PCIC4_IRQ 68 +#define PCIC4_IPR_ADDR INTC_INT2PRI5 +#define PCIC4_IPR_POS 1 +#define PCIC4_PRIORITY 2 + +/* PCIC(5) */ +#define PCICERR_IRQ 69 +#define PCICPWD3_IRQ 70 +#define PCICPWD2_IRQ 71 +#define PCICPWD1_IRQ 72 +#define PCICPWD0_IRQ 73 +#define PCIC5_IPR_ADDR INTC_INT2PRI5 +#define PCIC5_IPR_POS 0 +#define PCIC5_PRIORITY 2 + +/* SIOF */ +#define SIOF_IRQ 80 +#define SIOF_IPR_ADDR INTC_INT2PRI6 +#define SIOF_IPR_POS 3 +#define SIOF_PRIORITY 3 + +/* HSPI */ +#define HSPI_IRQ 84 +#define HSPI_IPR_ADDR INTC_INT2PRI6 +#define HSPI_IPR_POS 2 +#define HSPI_PRIORITY 3 + +/* MMCIF */ +#define MMCIF_FSTAT_IRQ 88 +#define MMCIF_TRAN_IRQ 89 +#define MMCIF_ERR_IRQ 90 +#define MMCIF_FRDY_IRQ 91 +#define MMCIF_IPR_ADDR INTC_INT2PRI6 +#define MMCIF_IPR_POS 1 +#define HSPI_PRIORITY 3 + +/* SSI */ +#define SSI_IRQ 100 +#define SSI_IPR_ADDR INTC_INT2PRI6 +#define SSI_IPR_POS 0 +#define SSI_PRIORITY 3 + +/* FLCTL */ +#define FLCTL_FLSTE_IRQ 104 +#define FLCTL_FLTEND_IRQ 105 +#define FLCTL_FLTRQ0_IRQ 106 +#define FLCTL_FLTRQ1_IRQ 107 +#define FLCTL_IPR_ADDR INTC_INT2PRI7 +#define FLCTL_IPR_POS 3 +#define FLCTL_PRIORITY 3 + +/* GPIO */ +#define GPIO0_IRQ 108 +#define GPIO1_IRQ 109 +#define GPIO2_IRQ 110 +#define GPIO3_IRQ 111 +#define GPIO_IPR_ADDR INTC_INT2PRI7 +#define GPIO_IPR_POS 2 +#define GPIO_PRIORITY 3 + +/* ONCHIP_NR_IRQS */ +#define NR_IRQS 150 /* 111 + 16 */ + +/* In a generic kernel, NR_IRQS is an upper bound, and we should use + * ACTUAL_NR_IRQS (which uses the machine vector) to get the correct value. + */ +#define ACTUAL_NR_IRQS NR_IRQS + +extern void disable_irq(unsigned int); +extern void disable_irq_nosync(unsigned int); +extern void enable_irq(unsigned int); + +/* + * Simple Mask Register Support + */ +extern void make_maskreg_irq(unsigned int irq); +extern unsigned short *irq_mask_register; + +/* + * Function for "on chip support modules". + */ +extern void make_imask_irq(unsigned int irq); + +#define INTC_TMU0_MSK 0 +#define INTC_TMU3_MSK 1 +#define INTC_RTC_MSK 2 +#define INTC_SCIF0_MSK 3 +#define INTC_SCIF1_MSK 4 +#define INTC_WDT_MSK 5 +#define INTC_HUID_MSK 7 +#define INTC_DMAC0_MSK 8 +#define INTC_DMAC1_MSK 9 +#define INTC_CMT_MSK 12 +#define INTC_HAC_MSK 13 +#define INTC_PCIC0_MSK 14 +#define INTC_PCIC1_MSK 15 +#define INTC_PCIC2_MSK 16 +#define INTC_PCIC3_MSK 17 +#define INTC_PCIC4_MSK 18 +#define INTC_PCIC5_MSK 19 +#define INTC_SIOF_MSK 20 +#define INTC_HSPI_MSK 21 +#define INTC_MMCIF_MSK 22 +#define INTC_SSI_MSK 23 +#define INTC_FLCTL_MSK 24 +#define INTC_GPIO_MSK 25 + +#endif /* __ASM_SH_IRQ_SH7780_H */ diff --git a/include/asm-sh/irq.h b/include/asm-sh/irq.h index 614a8c13b72..060ec3c2720 100644 --- a/include/asm-sh/irq.h +++ b/include/asm-sh/irq.h @@ -15,13 +15,20 @@ #include #include /* for pt_regs */ -#if defined(CONFIG_SH_HP600) || \ +#if defined(CONFIG_SH_HP6XX) || \ defined(CONFIG_SH_RTS7751R2D) || \ defined(CONFIG_SH_HS7751RVOIP) || \ - defined(CONFIG_SH_SH03) + defined(CONFIG_SH_HS7751RVOIP) || \ + defined(CONFIG_SH_SH03) || \ + defined(CONFIG_SH_R7780RP) || \ + defined(CONFIG_SH_LANDISK) #include #endif +#ifndef CONFIG_CPU_SUBTYPE_SH7780 + +#define INTC_DMAC0_MSK 0 + #if defined(CONFIG_CPU_SH3) #define INTC_IPRA 0xfffffee2UL #define INTC_IPRB 0xfffffee4UL @@ -235,8 +242,9 @@ #define SCIF1_IPR_ADDR INTC_IPRB #define SCIF1_IPR_POS 1 #define SCIF1_PRIORITY 3 -#endif -#endif +#endif /* ST40STB1 */ + +#endif /* 775x / SH4-202 / ST40STB1 */ /* NR_IRQS is made from three components: * 1. ONCHIP_NR_IRQS - number of IRLS + on-chip peripherial modules @@ -245,37 +253,35 @@ */ /* 1. ONCHIP_NR_IRQS */ -#ifdef CONFIG_SH_GENERIC +#if defined(CONFIG_CPU_SUBTYPE_SH7604) +# define ONCHIP_NR_IRQS 24 // Actually 21 +#elif defined(CONFIG_CPU_SUBTYPE_SH7707) +# define ONCHIP_NR_IRQS 64 +# define PINT_NR_IRQS 16 +#elif defined(CONFIG_CPU_SUBTYPE_SH7708) +# define ONCHIP_NR_IRQS 32 +#elif defined(CONFIG_CPU_SUBTYPE_SH7709) || \ + defined(CONFIG_CPU_SUBTYPE_SH7705) +# define ONCHIP_NR_IRQS 64 // Actually 61 +# define PINT_NR_IRQS 16 +#elif defined(CONFIG_CPU_SUBTYPE_SH7750) +# define ONCHIP_NR_IRQS 48 // Actually 44 +#elif defined(CONFIG_CPU_SUBTYPE_SH7751) +# define ONCHIP_NR_IRQS 72 +#elif defined(CONFIG_CPU_SUBTYPE_SH7760) +# define ONCHIP_NR_IRQS 112 /* XXX */ +#elif defined(CONFIG_CPU_SUBTYPE_SH4_202) +# define ONCHIP_NR_IRQS 72 +#elif defined(CONFIG_CPU_SUBTYPE_ST40STB1) +# define ONCHIP_NR_IRQS 144 +#elif defined(CONFIG_CPU_SUBTYPE_SH7300) +# define ONCHIP_NR_IRQS 109 +#elif defined(CONFIG_SH_UNKNOWN) /* Most be last */ # define ONCHIP_NR_IRQS 144 -#else -# if defined(CONFIG_CPU_SUBTYPE_SH7604) -# define ONCHIP_NR_IRQS 24 // Actually 21 -# elif defined(CONFIG_CPU_SUBTYPE_SH7707) -# define ONCHIP_NR_IRQS 64 -# define PINT_NR_IRQS 16 -# elif defined(CONFIG_CPU_SUBTYPE_SH7708) -# define ONCHIP_NR_IRQS 32 -# elif defined(CONFIG_CPU_SUBTYPE_SH7709) || \ - defined(CONFIG_CPU_SUBTYPE_SH7705) -# define ONCHIP_NR_IRQS 64 // Actually 61 -# define PINT_NR_IRQS 16 -# elif defined(CONFIG_CPU_SUBTYPE_SH7750) -# define ONCHIP_NR_IRQS 48 // Actually 44 -# elif defined(CONFIG_CPU_SUBTYPE_SH7751) -# define ONCHIP_NR_IRQS 72 -# elif defined(CONFIG_CPU_SUBTYPE_SH7760) -# define ONCHIP_NR_IRQS 110 -# elif defined(CONFIG_CPU_SUBTYPE_SH4_202) -# define ONCHIP_NR_IRQS 72 -# elif defined(CONFIG_CPU_SUBTYPE_ST40STB1) -# define ONCHIP_NR_IRQS 144 -# elif defined(CONFIG_CPU_SUBTYPE_SH7300) -# define ONCHIP_NR_IRQS 109 -# endif #endif /* 2. PINT_NR_IRQS */ -#ifdef CONFIG_SH_GENERIC +#ifdef CONFIG_SH_UNKNOWN # define PINT_NR_IRQS 16 #else # ifndef PINT_NR_IRQS @@ -288,22 +294,22 @@ #endif /* 3. OFFCHIP_NR_IRQS */ -#ifdef CONFIG_SH_GENERIC +#if defined(CONFIG_HD64461) +# define OFFCHIP_NR_IRQS 18 +#elif defined (CONFIG_SH_BIGSUR) /* must be before CONFIG_HD64465 */ +# define OFFCHIP_NR_IRQS 48 +#elif defined(CONFIG_HD64465) # define OFFCHIP_NR_IRQS 16 +#elif defined (CONFIG_SH_EC3104) +# define OFFCHIP_NR_IRQS 16 +#elif defined (CONFIG_SH_DREAMCAST) +# define OFFCHIP_NR_IRQS 96 +#elif defined (CONFIG_SH_TITAN) +# define OFFCHIP_NR_IRQS 4 +#elif defined(CONFIG_SH_UNKNOWN) +# define OFFCHIP_NR_IRQS 16 /* Must also be last */ #else -# if defined(CONFIG_HD64461) -# define OFFCHIP_NR_IRQS 18 -# elif defined (CONFIG_SH_BIGSUR) /* must be before CONFIG_HD64465 */ -# define OFFCHIP_NR_IRQS 48 -# elif defined(CONFIG_HD64465) -# define OFFCHIP_NR_IRQS 16 -# elif defined (CONFIG_SH_EC3104) -# define OFFCHIP_NR_IRQS 16 -# elif defined (CONFIG_SH_DREAMCAST) -# define OFFCHIP_NR_IRQS 96 -# else -# define OFFCHIP_NR_IRQS 0 -# endif +# define OFFCHIP_NR_IRQS 0 #endif #if OFFCHIP_NR_IRQS > 0 @@ -313,16 +319,6 @@ /* NR_IRQS. 1+2+3 */ #define NR_IRQS (ONCHIP_NR_IRQS + PINT_NR_IRQS + OFFCHIP_NR_IRQS) -/* In a generic kernel, NR_IRQS is an upper bound, and we should use - * ACTUAL_NR_IRQS (which uses the machine vector) to get the correct value. - */ -#ifdef CONFIG_SH_GENERIC -# define ACTUAL_NR_IRQS (sh_mv.mv_nr_irqs) -#else -# define ACTUAL_NR_IRQS NR_IRQS -#endif - - extern void disable_irq(unsigned int); extern void disable_irq_nosync(unsigned int); extern void enable_irq(unsigned int); @@ -542,9 +538,6 @@ extern int ipr_irq_demux(int irq); extern int ipr_irq_demux(int irq); #define __irq_demux(irq) ipr_irq_demux(irq) - -#else -#define __irq_demux(irq) irq #endif /* CONFIG_CPU_SUBTYPE_SH7707 || CONFIG_CPU_SUBTYPE_SH7709 */ #if defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751) || \ @@ -557,18 +550,35 @@ extern int ipr_irq_demux(int irq); #define INTC_ICR_IRLM (1<<7) #endif -#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 +#else +#include +#endif +/* SH with INTC2-style interrupts */ +#ifdef CONFIG_CPU_HAS_INTC2_IRQ +#if defined(CONFIG_CPU_SUBTYPE_ST40STB1) +#define INTC2_BASE 0xfe080000 #define INTC2_FIRST_IRQ 64 -#define NR_INTC2_IRQS 25 - +#define INTC2_INTREQ_OFFSET 0x20 +#define INTC2_INTMSK_OFFSET 0x40 +#define INTC2_INTMSKCLR_OFFSET 0x60 +#define NR_INTC2_IRQS 25 +#elif defined(CONFIG_CPU_SUBTYPE_SH7760) #define INTC2_BASE 0xfe080000 -#define INTC2_INTC2MODE (INTC2_BASE+0x80) - -#define INTC2_INTPRI_OFFSET 0x00 +#define INTC2_FIRST_IRQ 48 /* INTEVT 0x800 */ #define INTC2_INTREQ_OFFSET 0x20 #define INTC2_INTMSK_OFFSET 0x40 #define INTC2_INTMSKCLR_OFFSET 0x60 +#define NR_INTC2_IRQS 64 +#elif defined(CONFIG_CPU_SUBTYPE_SH7780) +#define INTC2_BASE 0xffd40000 +#define INTC2_FIRST_IRQ 22 +#define INTC2_INTMSK_OFFSET (0x38) +#define INTC2_INTMSKCLR_OFFSET (0x3c) +#define NR_INTC2_IRQS 60 +#endif + +#define INTC2_INTPRI_OFFSET 0x00 void make_intc2_irq(unsigned int irq, unsigned int ipr_offset, unsigned int ipr_shift, @@ -577,13 +587,16 @@ void make_intc2_irq(unsigned int irq, void init_IRQ_intc2(void); void intc2_add_clear_irq(int irq, int (*fn)(int)); -#endif /* CONFIG_CPU_SUBTYPE_ST40STB1 */ +#endif static inline int generic_irq_demux(int irq) { return irq; } +#ifndef __irq_demux +#define __irq_demux(irq) (irq) +#endif #define irq_canonicalize(irq) (irq) #define irq_demux(irq) __irq_demux(sh_mv.mv_irq_demux(irq)) -- GitLab From b66c1a3919abb40f9bd8fb92a0d9fd77eb899c54 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 16 Jan 2006 22:14:15 -0800 Subject: [PATCH 378/465] [PATCH] sh: I/O routine cleanups and ioremap() overhaul This introduces a few changes in the way that the I/O routines are defined on SH, specifically so that things like the iomap API properly wrap through the machvec for board-specific quirks. In addition to this, the old p3_ioremap() work is converted to a more generic __ioremap() that will map through the PMB if it's available, or fall back on page tables for everything else. An alpha-like IO_CONCAT is also added so we can start to clean up the board-specific io.h mess, which will be handled in board update patches.. Signed-off-by: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/sh/kernel/io.c | 41 ++++-- arch/sh/kernel/io_generic.c | 192 +++++++++++------------- arch/sh/mm/ioremap.c | 99 ++++++++++--- include/asm-sh/io.h | 283 +++++++++++++++++++++--------------- include/asm-sh/io_generic.h | 96 ++++++------ include/asm-sh/machvec.h | 66 ++++----- 6 files changed, 440 insertions(+), 337 deletions(-) diff --git a/arch/sh/kernel/io.c b/arch/sh/kernel/io.c index d9932f25993..71c9fde2fd9 100644 --- a/arch/sh/kernel/io.c +++ b/arch/sh/kernel/io.c @@ -2,58 +2,73 @@ * linux/arch/sh/kernel/io.c * * Copyright (C) 2000 Stuart Menefy + * Copyright (C) 2005 Paul Mundt * * Provide real functions which expand to whatever the header file defined. * Also definitions of machine independent IO functions. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. */ - -#include #include +#include +#include /* * Copy data from IO memory space to "real" memory space. * This needs to be optimized. */ -void memcpy_fromio(void * to, unsigned long from, unsigned long count) +void memcpy_fromio(void *to, volatile void __iomem *from, unsigned long count) { char *p = to; while (count) { count--; - *p = readb(from); + *p = readb((void __iomem *)from); p++; from++; } } - +EXPORT_SYMBOL(memcpy_fromio); + /* * Copy data from "real" memory space to IO memory space. * This needs to be optimized. */ -void memcpy_toio(unsigned long to, const void * from, unsigned long count) +void memcpy_toio(volatile void __iomem *to, const void *from, unsigned long count) { const char *p = from; while (count) { count--; - writeb(*p, to); + writeb(*p, (void __iomem *)to); p++; to++; } } - +EXPORT_SYMBOL(memcpy_toio); + /* * "memset" on IO memory space. * This needs to be optimized. */ -void memset_io(unsigned long dst, int c, unsigned long count) +void memset_io(volatile void __iomem *dst, int c, unsigned long count) { while (count) { count--; - writeb(c, dst); + writeb(c, (void __iomem *)dst); dst++; } } - -EXPORT_SYMBOL(memcpy_fromio); -EXPORT_SYMBOL(memcpy_toio); EXPORT_SYMBOL(memset_io); +void __iomem *ioport_map(unsigned long port, unsigned int nr) +{ + return sh_mv.mv_ioport_map(port, nr); +} +EXPORT_SYMBOL(ioport_map); + +void ioport_unmap(void __iomem *addr) +{ + sh_mv.mv_ioport_unmap(addr); +} +EXPORT_SYMBOL(ioport_unmap); diff --git a/arch/sh/kernel/io_generic.c b/arch/sh/kernel/io_generic.c index a911b0149d1..28ec7487de8 100644 --- a/arch/sh/kernel/io_generic.c +++ b/arch/sh/kernel/io_generic.c @@ -3,6 +3,7 @@ * linux/arch/sh/kernel/io_generic.c * * Copyright (C) 2000 Niibe Yutaka + * Copyright (C) 2005 Paul Mundt * * Generic I/O routine. These can be used where a machine specific version * is not required. @@ -10,21 +11,20 @@ * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. - * */ - +#include #include #include -#include -#if defined(CONFIG_CPU_SH3) +#ifdef CONFIG_CPU_SH3 +/* SH3 has a PCMCIA bug that needs a dummy read from area 6 for a + * workaround. */ /* I'm not sure SH7709 has this kind of bug */ -#define SH3_PCMCIA_BUG_WORKAROUND 1 -#define DUMMY_READ_AREA6 0xba000000 +#define dummy_read() ctrl_inb(0xba000000) +#else +#define dummy_read() #endif -#define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x)) - unsigned long generic_io_base; static inline void delay(void) @@ -32,40 +32,40 @@ static inline void delay(void) ctrl_inw(0xa0000000); } -unsigned char generic_inb(unsigned long port) +u8 generic_inb(unsigned long port) { - return *(volatile unsigned char*)PORT2ADDR(port); + return ctrl_inb((unsigned long __force)ioport_map(port, 1)); } -unsigned short generic_inw(unsigned long port) +u16 generic_inw(unsigned long port) { - return *(volatile unsigned short*)PORT2ADDR(port); + return ctrl_inw((unsigned long __force)ioport_map(port, 2)); } -unsigned int generic_inl(unsigned long port) +u32 generic_inl(unsigned long port) { - return *(volatile unsigned long*)PORT2ADDR(port); + return ctrl_inl((unsigned long __force)ioport_map(port, 4)); } -unsigned char generic_inb_p(unsigned long port) +u8 generic_inb_p(unsigned long port) { - unsigned long v = *(volatile unsigned char*)PORT2ADDR(port); + unsigned long v = generic_inb(port); delay(); return v; } -unsigned short generic_inw_p(unsigned long port) +u16 generic_inw_p(unsigned long port) { - unsigned long v = *(volatile unsigned short*)PORT2ADDR(port); + unsigned long v = generic_inw(port); delay(); return v; } -unsigned int generic_inl_p(unsigned long port) +u32 generic_inl_p(unsigned long port) { - unsigned long v = *(volatile unsigned long*)PORT2ADDR(port); + unsigned long v = generic_inl(port); delay(); return v; @@ -77,75 +77,70 @@ unsigned int generic_inl_p(unsigned long port) * convert the port address to real address once. */ -void generic_insb(unsigned long port, void *buffer, unsigned long count) +void generic_insb(unsigned long port, void *dst, unsigned long count) { - volatile unsigned char *port_addr; - unsigned char *buf=buffer; - - port_addr = (volatile unsigned char *)PORT2ADDR(port); + volatile u8 *port_addr; + u8 *buf = dst; - while(count--) - *buf++ = *port_addr; + port_addr = (volatile u8 *)ioport_map(port, 1); + while (count--) + *buf++ = *port_addr; } -void generic_insw(unsigned long port, void *buffer, unsigned long count) +void generic_insw(unsigned long port, void *dst, unsigned long count) { - volatile unsigned short *port_addr; - unsigned short *buf=buffer; + volatile u16 *port_addr; + u16 *buf = dst; - port_addr = (volatile unsigned short *)PORT2ADDR(port); + port_addr = (volatile u16 *)ioport_map(port, 2); + while (count--) + *buf++ = *port_addr; - while(count--) - *buf++ = *port_addr; -#ifdef SH3_PCMCIA_BUG_WORKAROUND - ctrl_inb (DUMMY_READ_AREA6); -#endif + dummy_read(); } -void generic_insl(unsigned long port, void *buffer, unsigned long count) +void generic_insl(unsigned long port, void *dst, unsigned long count) { - volatile unsigned long *port_addr; - unsigned long *buf=buffer; + volatile u32 *port_addr; + u32 *buf = dst; - port_addr = (volatile unsigned long *)PORT2ADDR(port); + port_addr = (volatile u32 *)ioport_map(port, 4); + while (count--) + *buf++ = *port_addr; - while(count--) - *buf++ = *port_addr; -#ifdef SH3_PCMCIA_BUG_WORKAROUND - ctrl_inb (DUMMY_READ_AREA6); -#endif + dummy_read(); } -void generic_outb(unsigned char b, unsigned long port) +void generic_outb(u8 b, unsigned long port) { - *(volatile unsigned char*)PORT2ADDR(port) = b; + ctrl_outb(b, (unsigned long __force)ioport_map(port, 1)); } -void generic_outw(unsigned short b, unsigned long port) +void generic_outw(u16 b, unsigned long port) { - *(volatile unsigned short*)PORT2ADDR(port) = b; + ctrl_outw(b, (unsigned long __force)ioport_map(port, 2)); } -void generic_outl(unsigned int b, unsigned long port) +void generic_outl(u32 b, unsigned long port) { - *(volatile unsigned long*)PORT2ADDR(port) = b; + ctrl_outl(b, (unsigned long __force)ioport_map(port, 4)); } -void generic_outb_p(unsigned char b, unsigned long port) +void generic_outb_p(u8 b, unsigned long port) { - *(volatile unsigned char*)PORT2ADDR(port) = b; + generic_outb(b, port); delay(); } -void generic_outw_p(unsigned short b, unsigned long port) +void generic_outw_p(u16 b, unsigned long port) { - *(volatile unsigned short*)PORT2ADDR(port) = b; + generic_outw(b, port); delay(); } -void generic_outl_p(unsigned int b, unsigned long port) +void generic_outl_p(u32 b, unsigned long port) { - *(volatile unsigned long*)PORT2ADDR(port) = b; + generic_outl(b, port); delay(); } @@ -154,90 +149,77 @@ void generic_outl_p(unsigned int b, unsigned long port) * address. However as the port address doesn't change we only need to * convert the port address to real address once. */ - -void generic_outsb(unsigned long port, const void *buffer, unsigned long count) +void generic_outsb(unsigned long port, const void *src, unsigned long count) { - volatile unsigned char *port_addr; - const unsigned char *buf=buffer; + volatile u8 *port_addr; + const u8 *buf = src; - port_addr = (volatile unsigned char *)PORT2ADDR(port); + port_addr = (volatile u8 __force *)ioport_map(port, 1); - while(count--) - *port_addr = *buf++; + while (count--) + *port_addr = *buf++; } -void generic_outsw(unsigned long port, const void *buffer, unsigned long count) +void generic_outsw(unsigned long port, const void *src, unsigned long count) { - volatile unsigned short *port_addr; - const unsigned short *buf=buffer; + volatile u16 *port_addr; + const u16 *buf = src; - port_addr = (volatile unsigned short *)PORT2ADDR(port); + port_addr = (volatile u16 __force *)ioport_map(port, 2); - while(count--) - *port_addr = *buf++; + while (count--) + *port_addr = *buf++; -#ifdef SH3_PCMCIA_BUG_WORKAROUND - ctrl_inb (DUMMY_READ_AREA6); -#endif + dummy_read(); } -void generic_outsl(unsigned long port, const void *buffer, unsigned long count) +void generic_outsl(unsigned long port, const void *src, unsigned long count) { - volatile unsigned long *port_addr; - const unsigned long *buf=buffer; + volatile u32 *port_addr; + const u32 *buf = src; - port_addr = (volatile unsigned long *)PORT2ADDR(port); + port_addr = (volatile u32 __force *)ioport_map(port, 4); + while (count--) + *port_addr = *buf++; - while(count--) - *port_addr = *buf++; - -#ifdef SH3_PCMCIA_BUG_WORKAROUND - ctrl_inb (DUMMY_READ_AREA6); -#endif -} - -unsigned char generic_readb(unsigned long addr) -{ - return *(volatile unsigned char*)addr; + dummy_read(); } -unsigned short generic_readw(unsigned long addr) +u8 generic_readb(void __iomem *addr) { - return *(volatile unsigned short*)addr; + return ctrl_inb((unsigned long __force)addr); } -unsigned int generic_readl(unsigned long addr) +u16 generic_readw(void __iomem *addr) { - return *(volatile unsigned long*)addr; + return ctrl_inw((unsigned long __force)addr); } -void generic_writeb(unsigned char b, unsigned long addr) +u32 generic_readl(void __iomem *addr) { - *(volatile unsigned char*)addr = b; + return ctrl_inl((unsigned long __force)addr); } -void generic_writew(unsigned short b, unsigned long addr) +void generic_writeb(u8 b, void __iomem *addr) { - *(volatile unsigned short*)addr = b; + ctrl_outb(b, (unsigned long __force)addr); } -void generic_writel(unsigned int b, unsigned long addr) +void generic_writew(u16 b, void __iomem *addr) { - *(volatile unsigned long*)addr = b; + ctrl_outw(b, (unsigned long __force)addr); } -void * generic_ioremap(unsigned long offset, unsigned long size) +void generic_writel(u32 b, void __iomem *addr) { - return (void *) P2SEGADDR(offset); + ctrl_outl(b, (unsigned long __force)addr); } -EXPORT_SYMBOL(generic_ioremap); -void generic_iounmap(void *addr) +void __iomem *generic_ioport_map(unsigned long addr, unsigned int size) { + return (void __iomem *)(addr + generic_io_base); } -EXPORT_SYMBOL(generic_iounmap); -unsigned long generic_isa_port2addr(unsigned long offset) +void generic_ioport_unmap(void __iomem *addr) { - return offset + generic_io_base; } diff --git a/arch/sh/mm/ioremap.c b/arch/sh/mm/ioremap.c index e794e27a72f..96fa4a999e2 100644 --- a/arch/sh/mm/ioremap.c +++ b/arch/sh/mm/ioremap.c @@ -6,13 +6,19 @@ * 640k-1MB IO memory area on PC's * * (C) Copyright 1995 1996 Linus Torvalds + * (C) Copyright 2005, 2006 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file "COPYING" in the main directory of this + * archive for more details. */ - #include +#include #include #include #include #include +#include #include #include @@ -80,9 +86,15 @@ int remap_area_pages(unsigned long address, unsigned long phys_addr, if (address >= end) BUG(); do { + pud_t *pud; pmd_t *pmd; - pmd = pmd_alloc(&init_mm, dir, address); + error = -ENOMEM; + + pud = pud_alloc(&init_mm, dir, address); + if (!pud) + break; + pmd = pmd_alloc(&init_mm, pud, address); if (!pmd) break; if (remap_area_pmd(pmd, address, end - address, @@ -96,10 +108,6 @@ int remap_area_pages(unsigned long address, unsigned long phys_addr, return error; } -/* - * Generic mapping function (not visible outside): - */ - /* * Remap an arbitrary physical address space into the kernel virtual * address space. Needed when the kernel wants to access high addresses @@ -109,11 +117,11 @@ int remap_area_pages(unsigned long address, unsigned long phys_addr, * have to convert them into an offset in a page-aligned mapping, but the * caller shouldn't need to know that small detail. */ -void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags) +void __iomem *__ioremap(unsigned long phys_addr, unsigned long size, + unsigned long flags) { - void * addr; struct vm_struct * area; - unsigned long offset, last_addr; + unsigned long offset, last_addr, addr, orig_addr; /* Don't allow wraparound or zero size */ last_addr = phys_addr + size - 1; @@ -124,7 +132,7 @@ void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long fla * Don't remap the low PCI/ISA area, it's always mapped.. */ if (phys_addr >= 0xA0000 && last_addr < 0x100000) - return phys_to_virt(phys_addr); + return (void __iomem *)phys_to_virt(phys_addr); /* * Don't allow anybody to remap normal RAM that we're using.. @@ -146,16 +154,71 @@ void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long fla if (!area) return NULL; area->phys_addr = phys_addr; - addr = area->addr; - if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) { - vunmap(addr); - return NULL; + orig_addr = addr = (unsigned long)area->addr; + +#ifdef CONFIG_32BIT + /* + * First try to remap through the PMB once a valid VMA has been + * established. Smaller allocations (or the rest of the size + * remaining after a PMB mapping due to the size not being + * perfectly aligned on a PMB size boundary) are then mapped + * through the UTLB using conventional page tables. + * + * PMB entries are all pre-faulted. + */ + if (unlikely(size >= 0x1000000)) { + unsigned long mapped = pmb_remap(addr, phys_addr, size, flags); + + if (likely(mapped)) { + addr += mapped; + phys_addr += mapped; + size -= mapped; + } } - return (void *) (offset + (char *)addr); +#endif + + if (likely(size)) + if (remap_area_pages(addr, phys_addr, size, flags)) { + vunmap((void *)orig_addr); + return NULL; + } + + return (void __iomem *)(offset + (char *)orig_addr); } +EXPORT_SYMBOL(__ioremap); -void p3_iounmap(void *addr) +void __iounmap(void __iomem *addr) { - if (addr > high_memory) - vfree((void *)(PAGE_MASK & (unsigned long)addr)); + unsigned long vaddr = (unsigned long __force)addr; + struct vm_struct *p; + + if (PXSEG(vaddr) < P3SEG) + return; + +#ifdef CONFIG_32BIT + /* + * Purge any PMB entries that may have been established for this + * mapping, then proceed with conventional VMA teardown. + * + * XXX: Note that due to the way that remove_vm_area() does + * matching of the resultant VMA, we aren't able to fast-forward + * the address past the PMB space until the end of the VMA where + * the page tables reside. As such, unmap_vm_area() will be + * forced to linearly scan over the area until it finds the page + * tables where PTEs that need to be unmapped actually reside, + * which is far from optimal. Perhaps we need to use a separate + * VMA for the PMB mappings? + * -- PFM. + */ + pmb_unmap(vaddr); +#endif + + p = remove_vm_area((void *)(vaddr & PAGE_MASK)); + if (!p) { + printk(KERN_ERR "%s: bad address %p\n", __FUNCTION__, addr); + return; + } + + kfree(p); } +EXPORT_SYMBOL(__iounmap); diff --git a/include/asm-sh/io.h b/include/asm-sh/io.h index 6bc343fee7a..b0b2937b6f8 100644 --- a/include/asm-sh/io.h +++ b/include/asm-sh/io.h @@ -11,7 +11,7 @@ * For read{b,w,l} and write{b,w,l} there are also __raw versions, which * do not have a memory barrier after them. * - * In addition, we have + * In addition, we have * ctrl_in{b,w,l}/ctrl_out{b,w,l} for SuperH specific I/O. * which are processor specific. */ @@ -23,19 +23,27 @@ * inb by default expands to _inb, but the machine specific code may * define it to __inb if it chooses. */ - +#include #include #include #include #include -#include +#include +#include + +#ifdef __KERNEL__ /* * Depending on which platform we are running on, we need different * I/O functions. */ +#define __IO_PREFIX generic +#include + +#define maybebadio(port) \ + printk(KERN_ERR "bad PC-like io %s:%u for port 0x%lx at 0x%08x\n", \ + __FUNCTION__, __LINE__, (port), (u32)__builtin_return_address(0)) -#ifdef __KERNEL__ /* * Since boards are able to define their own set of I/O routines through * their respective machine vector, we always wrap through the mv. @@ -44,113 +52,120 @@ * a given routine, it will be wrapped to generic code at run-time. */ -# define __inb(p) sh_mv.mv_inb((p)) -# define __inw(p) sh_mv.mv_inw((p)) -# define __inl(p) sh_mv.mv_inl((p)) -# define __outb(x,p) sh_mv.mv_outb((x),(p)) -# define __outw(x,p) sh_mv.mv_outw((x),(p)) -# define __outl(x,p) sh_mv.mv_outl((x),(p)) - -# define __inb_p(p) sh_mv.mv_inb_p((p)) -# define __inw_p(p) sh_mv.mv_inw_p((p)) -# define __inl_p(p) sh_mv.mv_inl_p((p)) -# define __outb_p(x,p) sh_mv.mv_outb_p((x),(p)) -# define __outw_p(x,p) sh_mv.mv_outw_p((x),(p)) -# define __outl_p(x,p) sh_mv.mv_outl_p((x),(p)) - -# define __insb(p,b,c) sh_mv.mv_insb((p), (b), (c)) -# define __insw(p,b,c) sh_mv.mv_insw((p), (b), (c)) -# define __insl(p,b,c) sh_mv.mv_insl((p), (b), (c)) -# define __outsb(p,b,c) sh_mv.mv_outsb((p), (b), (c)) -# define __outsw(p,b,c) sh_mv.mv_outsw((p), (b), (c)) -# define __outsl(p,b,c) sh_mv.mv_outsl((p), (b), (c)) - -# define __readb(a) sh_mv.mv_readb((a)) -# define __readw(a) sh_mv.mv_readw((a)) -# define __readl(a) sh_mv.mv_readl((a)) -# define __writeb(v,a) sh_mv.mv_writeb((v),(a)) -# define __writew(v,a) sh_mv.mv_writew((v),(a)) -# define __writel(v,a) sh_mv.mv_writel((v),(a)) - -# define __ioremap(a,s) sh_mv.mv_ioremap((a), (s)) -# define __iounmap(a) sh_mv.mv_iounmap((a)) - -# define __isa_port2addr(a) sh_mv.mv_isa_port2addr(a) - -# define inb __inb -# define inw __inw -# define inl __inl -# define outb __outb -# define outw __outw -# define outl __outl - -# define inb_p __inb_p -# define inw_p __inw_p -# define inl_p __inl_p -# define outb_p __outb_p -# define outw_p __outw_p -# define outl_p __outl_p - -# define insb __insb -# define insw __insw -# define insl __insl -# define outsb __outsb -# define outsw __outsw -# define outsl __outsl - -# define __raw_readb __readb -# define __raw_readw __readw -# define __raw_readl __readl -# define __raw_writeb __writeb -# define __raw_writew __writew -# define __raw_writel __writel +#define __inb(p) sh_mv.mv_inb((p)) +#define __inw(p) sh_mv.mv_inw((p)) +#define __inl(p) sh_mv.mv_inl((p)) +#define __outb(x,p) sh_mv.mv_outb((x),(p)) +#define __outw(x,p) sh_mv.mv_outw((x),(p)) +#define __outl(x,p) sh_mv.mv_outl((x),(p)) + +#define __inb_p(p) sh_mv.mv_inb_p((p)) +#define __inw_p(p) sh_mv.mv_inw_p((p)) +#define __inl_p(p) sh_mv.mv_inl_p((p)) +#define __outb_p(x,p) sh_mv.mv_outb_p((x),(p)) +#define __outw_p(x,p) sh_mv.mv_outw_p((x),(p)) +#define __outl_p(x,p) sh_mv.mv_outl_p((x),(p)) + +#define __insb(p,b,c) sh_mv.mv_insb((p), (b), (c)) +#define __insw(p,b,c) sh_mv.mv_insw((p), (b), (c)) +#define __insl(p,b,c) sh_mv.mv_insl((p), (b), (c)) +#define __outsb(p,b,c) sh_mv.mv_outsb((p), (b), (c)) +#define __outsw(p,b,c) sh_mv.mv_outsw((p), (b), (c)) +#define __outsl(p,b,c) sh_mv.mv_outsl((p), (b), (c)) + +#define __readb(a) sh_mv.mv_readb((a)) +#define __readw(a) sh_mv.mv_readw((a)) +#define __readl(a) sh_mv.mv_readl((a)) +#define __writeb(v,a) sh_mv.mv_writeb((v),(a)) +#define __writew(v,a) sh_mv.mv_writew((v),(a)) +#define __writel(v,a) sh_mv.mv_writel((v),(a)) + +#define inb __inb +#define inw __inw +#define inl __inl +#define outb __outb +#define outw __outw +#define outl __outl + +#define inb_p __inb_p +#define inw_p __inw_p +#define inl_p __inl_p +#define outb_p __outb_p +#define outw_p __outw_p +#define outl_p __outl_p + +#define insb __insb +#define insw __insw +#define insl __insl +#define outsb __outsb +#define outsw __outsw +#define outsl __outsl + +#define __raw_readb(a) __readb((void __iomem *)(a)) +#define __raw_readw(a) __readw((void __iomem *)(a)) +#define __raw_readl(a) __readl((void __iomem *)(a)) +#define __raw_writeb(v, a) __writeb(v, (void __iomem *)(a)) +#define __raw_writew(v, a) __writew(v, (void __iomem *)(a)) +#define __raw_writel(v, a) __writel(v, (void __iomem *)(a)) /* * The platform header files may define some of these macros to use * the inlined versions where appropriate. These macros may also be * redefined by userlevel programs. */ -#ifdef __raw_readb -# define readb(a) ({ unsigned long r_ = __raw_readb((unsigned long)a); mb(); r_; }) +#ifdef __readb +# define readb(a) ({ unsigned long r_ = __raw_readb(a); mb(); r_; }) #endif #ifdef __raw_readw -# define readw(a) ({ unsigned long r_ = __raw_readw((unsigned long)a); mb(); r_; }) +# define readw(a) ({ unsigned long r_ = __raw_readw(a); mb(); r_; }) #endif #ifdef __raw_readl -# define readl(a) ({ unsigned long r_ = __raw_readl((unsigned long)a); mb(); r_; }) +# define readl(a) ({ unsigned long r_ = __raw_readl(a); mb(); r_; }) #endif #ifdef __raw_writeb -# define writeb(v,a) ({ __raw_writeb((v),(unsigned long)(a)); mb(); }) +# define writeb(v,a) ({ __raw_writeb((v),(a)); mb(); }) #endif #ifdef __raw_writew -# define writew(v,a) ({ __raw_writew((v),(unsigned long)(a)); mb(); }) +# define writew(v,a) ({ __raw_writew((v),(a)); mb(); }) #endif #ifdef __raw_writel -# define writel(v,a) ({ __raw_writel((v),(unsigned long)(a)); mb(); }) +# define writel(v,a) ({ __raw_writel((v),(a)); mb(); }) #endif #define readb_relaxed(a) readb(a) #define readw_relaxed(a) readw(a) #define readl_relaxed(a) readl(a) -#define mmiowb() +/* Simple MMIO */ +#define ioread8(a) readb(a) +#define ioread16(a) readw(a) +#define ioread16be(a) be16_to_cpu(__raw_readw((a))) +#define ioread32(a) readl(a) +#define ioread32be(a) be32_to_cpu(__raw_readl((a))) -/* - * If the platform has PC-like I/O, this function converts the offset into - * an address. - */ -static __inline__ unsigned long isa_port2addr(unsigned long offset) -{ - return __isa_port2addr(offset); -} +#define iowrite8(v,a) writeb((v),(a)) +#define iowrite16(v,a) writew((v),(a)) +#define iowrite16be(v,a) __raw_writew(cpu_to_be16((v)),(a)) +#define iowrite32(v,a) writel((v),(a)) +#define iowrite32be(v,a) __raw_writel(cpu_to_be32((v)),(a)) + +#define ioread8_rep(a,d,c) insb((a),(d),(c)) +#define ioread16_rep(a,d,c) insw((a),(d),(c)) +#define ioread32_rep(a,d,c) insl((a),(d),(c)) + +#define iowrite8_rep(a,s,c) outsb((a),(s),(c)) +#define iowrite16_rep(a,s,c) outsw((a),(s),(c)) +#define iowrite32_rep(a,s,c) outsl((a),(s),(c)) + +#define mmiowb() wmb() /* synco on SH-4A, otherwise a nop */ /* * This function provides a method for the generic case where a board-specific - * isa_port2addr simply needs to return the port + some arbitrary port base. + * ioport_map simply needs to return the port + some arbitrary port base. * * We use this at board setup time to implicitly set the port base, and - * as a result, we can use the generic isa_port2addr. + * as a result, we can use the generic ioport_map. */ static inline void __set_io_port_base(unsigned long pbase) { @@ -159,51 +174,52 @@ static inline void __set_io_port_base(unsigned long pbase) generic_io_base = pbase; } -#define isa_readb(a) readb(isa_port2addr(a)) -#define isa_readw(a) readw(isa_port2addr(a)) -#define isa_readl(a) readl(isa_port2addr(a)) -#define isa_writeb(b,a) writeb(b,isa_port2addr(a)) -#define isa_writew(w,a) writew(w,isa_port2addr(a)) -#define isa_writel(l,a) writel(l,isa_port2addr(a)) +#define isa_readb(a) readb(ioport_map(a, 1)) +#define isa_readw(a) readw(ioport_map(a, 2)) +#define isa_readl(a) readl(ioport_map(a, 4)) +#define isa_writeb(b,a) writeb(b,ioport_map(a, 1)) +#define isa_writew(w,a) writew(w,ioport_map(a, 2)) +#define isa_writel(l,a) writel(l,ioport_map(a, 4)) + #define isa_memset_io(a,b,c) \ - memset((void *)(isa_port2addr((unsigned long)a)),(b),(c)) + memset((void *)(ioport_map((unsigned long)(a), 1)),(b),(c)) #define isa_memcpy_fromio(a,b,c) \ - memcpy((a),(void *)(isa_port2addr((unsigned long)(b))),(c)) + memcpy((a),(void *)(ioport_map((unsigned long)(b), 1)),(c)) #define isa_memcpy_toio(a,b,c) \ - memcpy((void *)(isa_port2addr((unsigned long)(a))),(b),(c)) + memcpy((void *)(ioport_map((unsigned long)(a), 1)),(b),(c)) /* We really want to try and get these to memcpy etc */ -extern void memcpy_fromio(void *, unsigned long, unsigned long); -extern void memcpy_toio(unsigned long, const void *, unsigned long); -extern void memset_io(unsigned long, int, unsigned long); +extern void memcpy_fromio(void *, volatile void __iomem *, unsigned long); +extern void memcpy_toio(volatile void __iomem *, const void *, unsigned long); +extern void memset_io(volatile void __iomem *, int, unsigned long); /* SuperH on-chip I/O functions */ -static __inline__ unsigned char ctrl_inb(unsigned long addr) +static inline unsigned char ctrl_inb(unsigned long addr) { return *(volatile unsigned char*)addr; } -static __inline__ unsigned short ctrl_inw(unsigned long addr) +static inline unsigned short ctrl_inw(unsigned long addr) { return *(volatile unsigned short*)addr; } -static __inline__ unsigned int ctrl_inl(unsigned long addr) +static inline unsigned int ctrl_inl(unsigned long addr) { return *(volatile unsigned long*)addr; } -static __inline__ void ctrl_outb(unsigned char b, unsigned long addr) +static inline void ctrl_outb(unsigned char b, unsigned long addr) { *(volatile unsigned char*)addr = b; } -static __inline__ void ctrl_outw(unsigned short b, unsigned long addr) +static inline void ctrl_outw(unsigned short b, unsigned long addr) { *(volatile unsigned short*)addr = b; } -static __inline__ void ctrl_outl(unsigned int b, unsigned long addr) +static inline void ctrl_outl(unsigned int b, unsigned long addr) { *(volatile unsigned long*)addr = b; } @@ -214,12 +230,12 @@ static __inline__ void ctrl_outl(unsigned int b, unsigned long addr) * Change virtual addresses to physical addresses and vv. * These are trivial on the 1:1 Linux/SuperH mapping */ -static __inline__ unsigned long virt_to_phys(volatile void * address) +static inline unsigned long virt_to_phys(volatile void *address) { return PHYSADDR(address); } -static __inline__ void * phys_to_virt(unsigned long address) +static inline void *phys_to_virt(unsigned long address) { return (void *)P1SEGADDR(address); } @@ -234,27 +250,60 @@ static __inline__ void * phys_to_virt(unsigned long address) * differently. On the x86 architecture, we just read/write the * memory location directly. * - * On SH, we have the whole physical address space mapped at all times - * (as MIPS does), so "ioremap()" and "iounmap()" do not need to do - * anything. (This isn't true for all machines but we still handle - * these cases with wired TLB entries anyway ...) + * On SH, we traditionally have the whole physical address space mapped + * at all times (as MIPS does), so "ioremap()" and "iounmap()" do not + * need to do anything but place the address in the proper segment. This + * is true for P1 and P2 addresses, as well as some P3 ones. However, + * most of the P3 addresses and newer cores using extended addressing + * need to map through page tables, so the ioremap() implementation + * becomes a bit more complicated. See arch/sh/mm/ioremap.c for + * additional notes on this. * * We cheat a bit and always return uncachable areas until we've fixed - * the drivers to handle caching properly. + * the drivers to handle caching properly. */ -static __inline__ void * ioremap(unsigned long offset, unsigned long size) +#ifdef CONFIG_MMU +void __iomem *__ioremap(unsigned long offset, unsigned long size, + unsigned long flags); +void __iounmap(void __iomem *addr); +#else +#define __ioremap(offset, size, flags) ((void __iomem *)(offset)) +#define __iounmap(addr) do { } while (0) +#endif /* CONFIG_MMU */ + +static inline void __iomem * +__ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags) { - return __ioremap(offset, size); + unsigned long last_addr = offset + size - 1; + + /* + * For P1 and P2 space this is trivial, as everything is already + * mapped. Uncached access for P1 addresses are done through P2. + * In the P3 case or for addresses outside of the 29-bit space, + * mapping must be done by the PMB or by using page tables. + */ + if (likely(PXSEG(offset) < P3SEG && PXSEG(last_addr) < P3SEG)) { + if (unlikely(flags & _PAGE_CACHABLE)) + return (void __iomem *)P1SEGADDR(offset); + + return (void __iomem *)P2SEGADDR(offset); + } + + return __ioremap(offset, size, flags); } -static __inline__ void iounmap(void *addr) -{ - return __iounmap(addr); -} - -#define ioremap_nocache(off,size) ioremap(off,size) - -static __inline__ int check_signature(unsigned long io_addr, +#define ioremap(offset, size) \ + __ioremap_mode((offset), (size), 0) +#define ioremap_nocache(offset, size) \ + __ioremap_mode((offset), (size), 0) +#define ioremap_cache(offset, size) \ + __ioremap_mode((offset), (size), _PAGE_CACHABLE) +#define p3_ioremap(offset, size, flags) \ + __ioremap((offset), (size), (flags)) +#define iounmap(addr) \ + __iounmap((addr)) + +static inline int check_signature(char __iomem *io_addr, const unsigned char *signature, int length) { int retval = 0; diff --git a/include/asm-sh/io_generic.h b/include/asm-sh/io_generic.h index be14587342f..92fc6070d7b 100644 --- a/include/asm-sh/io_generic.h +++ b/include/asm-sh/io_generic.h @@ -1,51 +1,49 @@ /* - * include/asm-sh/io_generic.h - * - * Copyright 2000 Stuart Menefy (stuart.menefy@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Generic IO functions + * Trivial I/O routine definitions, intentionally meant to be included + * multiple times. Ugly I/O routine concatenation helpers taken from + * alpha. Must be included _before_ io.h to avoid preprocessor-induced + * routine mismatch. */ - -#ifndef _ASM_SH_IO_GENERIC_H -#define _ASM_SH_IO_GENERIC_H - -extern unsigned long generic_io_base; - -extern unsigned char generic_inb(unsigned long port); -extern unsigned short generic_inw(unsigned long port); -extern unsigned int generic_inl(unsigned long port); - -extern void generic_outb(unsigned char value, unsigned long port); -extern void generic_outw(unsigned short value, unsigned long port); -extern void generic_outl(unsigned int value, unsigned long port); - -extern unsigned char generic_inb_p(unsigned long port); -extern unsigned short generic_inw_p(unsigned long port); -extern unsigned int generic_inl_p(unsigned long port); -extern void generic_outb_p(unsigned char value, unsigned long port); -extern void generic_outw_p(unsigned short value, unsigned long port); -extern void generic_outl_p(unsigned int value, unsigned long port); - -extern void generic_insb(unsigned long port, void *addr, unsigned long count); -extern void generic_insw(unsigned long port, void *addr, unsigned long count); -extern void generic_insl(unsigned long port, void *addr, unsigned long count); -extern void generic_outsb(unsigned long port, const void *addr, unsigned long count); -extern void generic_outsw(unsigned long port, const void *addr, unsigned long count); -extern void generic_outsl(unsigned long port, const void *addr, unsigned long count); - -extern unsigned char generic_readb(unsigned long addr); -extern unsigned short generic_readw(unsigned long addr); -extern unsigned int generic_readl(unsigned long addr); -extern void generic_writeb(unsigned char b, unsigned long addr); -extern void generic_writew(unsigned short b, unsigned long addr); -extern void generic_writel(unsigned int b, unsigned long addr); - -extern void *generic_ioremap(unsigned long offset, unsigned long size); -extern void generic_iounmap(void *addr); - -extern unsigned long generic_isa_port2addr(unsigned long offset); - -#endif /* _ASM_SH_IO_GENERIC_H */ +#define IO_CONCAT(a,b) _IO_CONCAT(a,b) +#define _IO_CONCAT(a,b) a ## _ ## b + +#ifndef __IO_PREFIX +#error "Don't include this header without a valid system prefix" +#endif + +u8 IO_CONCAT(__IO_PREFIX,inb)(unsigned long); +u16 IO_CONCAT(__IO_PREFIX,inw)(unsigned long); +u32 IO_CONCAT(__IO_PREFIX,inl)(unsigned long); + +void IO_CONCAT(__IO_PREFIX,outb)(u8, unsigned long); +void IO_CONCAT(__IO_PREFIX,outw)(u16, unsigned long); +void IO_CONCAT(__IO_PREFIX,outl)(u32, unsigned long); + +u8 IO_CONCAT(__IO_PREFIX,inb_p)(unsigned long); +u16 IO_CONCAT(__IO_PREFIX,inw_p)(unsigned long); +u32 IO_CONCAT(__IO_PREFIX,inl_p)(unsigned long); +void IO_CONCAT(__IO_PREFIX,outb_p)(u8, unsigned long); +void IO_CONCAT(__IO_PREFIX,outw_p)(u16, unsigned long); +void IO_CONCAT(__IO_PREFIX,outl_p)(u32, unsigned long); + +void IO_CONCAT(__IO_PREFIX,insb)(unsigned long, void *dst, unsigned long count); +void IO_CONCAT(__IO_PREFIX,insw)(unsigned long, void *dst, unsigned long count); +void IO_CONCAT(__IO_PREFIX,insl)(unsigned long, void *dst, unsigned long count); +void IO_CONCAT(__IO_PREFIX,outsb)(unsigned long, const void *src, unsigned long count); +void IO_CONCAT(__IO_PREFIX,outsw)(unsigned long, const void *src, unsigned long count); +void IO_CONCAT(__IO_PREFIX,outsl)(unsigned long, const void *src, unsigned long count); + +u8 IO_CONCAT(__IO_PREFIX,readb)(void __iomem *); +u16 IO_CONCAT(__IO_PREFIX,readw)(void __iomem *); +u32 IO_CONCAT(__IO_PREFIX,readl)(void __iomem *); +void IO_CONCAT(__IO_PREFIX,writeb)(u8, void __iomem *); +void IO_CONCAT(__IO_PREFIX,writew)(u16, void __iomem *); +void IO_CONCAT(__IO_PREFIX,writel)(u32, void __iomem *); + +void *IO_CONCAT(__IO_PREFIX,ioremap)(unsigned long offset, unsigned long size); +void IO_CONCAT(__IO_PREFIX,iounmap)(void *addr); + +void __iomem *IO_CONCAT(__IO_PREFIX,ioport_map)(unsigned long addr, unsigned int size); +void IO_CONCAT(__IO_PREFIX,ioport_unmap)(void __iomem *addr); + +#undef __IO_PREFIX diff --git a/include/asm-sh/machvec.h b/include/asm-sh/machvec.h index 3f18aa18051..550c50a7359 100644 --- a/include/asm-sh/machvec.h +++ b/include/asm-sh/machvec.h @@ -18,44 +18,37 @@ #include struct device; -struct timeval; -struct sh_machine_vector -{ +struct sh_machine_vector { int mv_nr_irqs; - unsigned char (*mv_inb)(unsigned long); - unsigned short (*mv_inw)(unsigned long); - unsigned int (*mv_inl)(unsigned long); - void (*mv_outb)(unsigned char, unsigned long); - void (*mv_outw)(unsigned short, unsigned long); - void (*mv_outl)(unsigned int, unsigned long); - - unsigned char (*mv_inb_p)(unsigned long); - unsigned short (*mv_inw_p)(unsigned long); - unsigned int (*mv_inl_p)(unsigned long); - void (*mv_outb_p)(unsigned char, unsigned long); - void (*mv_outw_p)(unsigned short, unsigned long); - void (*mv_outl_p)(unsigned int, unsigned long); - - void (*mv_insb)(unsigned long port, void *addr, unsigned long count); - void (*mv_insw)(unsigned long port, void *addr, unsigned long count); - void (*mv_insl)(unsigned long port, void *addr, unsigned long count); - void (*mv_outsb)(unsigned long port, const void *addr, unsigned long count); - void (*mv_outsw)(unsigned long port, const void *addr, unsigned long count); - void (*mv_outsl)(unsigned long port, const void *addr, unsigned long count); - - unsigned char (*mv_readb)(unsigned long); - unsigned short (*mv_readw)(unsigned long); - unsigned int (*mv_readl)(unsigned long); - void (*mv_writeb)(unsigned char, unsigned long); - void (*mv_writew)(unsigned short, unsigned long); - void (*mv_writel)(unsigned int, unsigned long); - - void* (*mv_ioremap)(unsigned long offset, unsigned long size); - void (*mv_iounmap)(void *addr); - - unsigned long (*mv_isa_port2addr)(unsigned long offset); + u8 (*mv_inb)(unsigned long); + u16 (*mv_inw)(unsigned long); + u32 (*mv_inl)(unsigned long); + void (*mv_outb)(u8, unsigned long); + void (*mv_outw)(u16, unsigned long); + void (*mv_outl)(u32, unsigned long); + + u8 (*mv_inb_p)(unsigned long); + u16 (*mv_inw_p)(unsigned long); + u32 (*mv_inl_p)(unsigned long); + void (*mv_outb_p)(u8, unsigned long); + void (*mv_outw_p)(u16, unsigned long); + void (*mv_outl_p)(u32, unsigned long); + + void (*mv_insb)(unsigned long, void *dst, unsigned long count); + void (*mv_insw)(unsigned long, void *dst, unsigned long count); + void (*mv_insl)(unsigned long, void *dst, unsigned long count); + void (*mv_outsb)(unsigned long, const void *src, unsigned long count); + void (*mv_outsw)(unsigned long, const void *src, unsigned long count); + void (*mv_outsl)(unsigned long, const void *src, unsigned long count); + + u8 (*mv_readb)(void __iomem *); + u16 (*mv_readw)(void __iomem *); + u32 (*mv_readl)(void __iomem *); + void (*mv_writeb)(u8, void __iomem *); + void (*mv_writew)(u16, void __iomem *); + void (*mv_writel)(u32, void __iomem *); int (*mv_irq_demux)(int irq); @@ -66,6 +59,9 @@ struct sh_machine_vector void *(*mv_consistent_alloc)(struct device *, size_t, dma_addr_t *, gfp_t); int (*mv_consistent_free)(struct device *, size_t, void *, dma_addr_t); + + void __iomem *(*mv_ioport_map)(unsigned long port, unsigned int size); + void (*mv_ioport_unmap)(void __iomem *); }; extern struct sh_machine_vector sh_mv; -- GitLab From 36ddf31b689a8c11d424e43565d2aa440b77bbf4 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 16 Jan 2006 22:14:17 -0800 Subject: [PATCH 379/465] [PATCH] sh: Simplistic clock framework This adds a relatively simplistic clock framework for sh. The initial goal behind this is to clean up the arch/sh/kernel/time.c mess and to get the CPU subtype-specific frequency setting and calculation code moved somewhere more sensible. This only deals with the core clocks at the moment, though it's trivial for other drivers to define their own clocks as desired. Signed-off-by: Paul Mundt Cc: john stultz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/sh/boards/overdrive/Makefile | 2 +- arch/sh/boards/overdrive/setup.c | 6 +- arch/sh/boards/overdrive/time.c | 119 ------ arch/sh/kernel/cpu/clock.c | 287 ++++++++++++++ arch/sh/kernel/cpu/sh3/Makefile | 7 + arch/sh/kernel/cpu/sh3/clock-sh3.c | 89 +++++ arch/sh/kernel/cpu/sh3/clock-sh7300.c | 78 ++++ arch/sh/kernel/cpu/sh3/clock-sh7705.c | 84 ++++ arch/sh/kernel/cpu/sh3/clock-sh7709.c | 96 +++++ arch/sh/kernel/cpu/sh4/Makefile | 11 +- arch/sh/kernel/cpu/sh4/clock-sh4-202.c | 179 +++++++++ arch/sh/kernel/cpu/sh4/clock-sh4.c | 80 ++++ arch/sh/kernel/cpu/sh4/clock-sh73180.c | 81 ++++ arch/sh/kernel/cpu/sh4/clock-sh7770.c | 73 ++++ arch/sh/kernel/cpu/sh4/clock-sh7780.c | 126 ++++++ arch/sh/kernel/time.c | 518 ++----------------------- include/asm-sh/clock.h | 61 +++ include/asm-sh/cpu-sh4/freq.h | 2 + include/asm-sh/freq.h | 11 - 19 files changed, 1287 insertions(+), 623 deletions(-) delete mode 100644 arch/sh/boards/overdrive/time.c create mode 100644 arch/sh/kernel/cpu/clock.c create mode 100644 arch/sh/kernel/cpu/sh3/clock-sh3.c create mode 100644 arch/sh/kernel/cpu/sh3/clock-sh7300.c create mode 100644 arch/sh/kernel/cpu/sh3/clock-sh7705.c create mode 100644 arch/sh/kernel/cpu/sh3/clock-sh7709.c create mode 100644 arch/sh/kernel/cpu/sh4/clock-sh4-202.c create mode 100644 arch/sh/kernel/cpu/sh4/clock-sh4.c create mode 100644 arch/sh/kernel/cpu/sh4/clock-sh73180.c create mode 100644 arch/sh/kernel/cpu/sh4/clock-sh7770.c create mode 100644 arch/sh/kernel/cpu/sh4/clock-sh7780.c create mode 100644 include/asm-sh/clock.h diff --git a/arch/sh/boards/overdrive/Makefile b/arch/sh/boards/overdrive/Makefile index 1762b59e927..245f03baf76 100644 --- a/arch/sh/boards/overdrive/Makefile +++ b/arch/sh/boards/overdrive/Makefile @@ -2,7 +2,7 @@ # Makefile for the STMicroelectronics Overdrive specific parts of the kernel # -obj-y := mach.o setup.o io.o irq.o led.o time.o +obj-y := mach.o setup.o io.o irq.o led.o obj-$(CONFIG_PCI) += fpga.o galileo.o pcidma.o diff --git a/arch/sh/boards/overdrive/setup.c b/arch/sh/boards/overdrive/setup.c index a36ce0284ed..94f6165d33b 100644 --- a/arch/sh/boards/overdrive/setup.c +++ b/arch/sh/boards/overdrive/setup.c @@ -17,8 +17,6 @@ #include #include -extern void od_time_init(void); - const char *get_system_type(void) { return "SH7750 Overdrive"; @@ -31,11 +29,9 @@ int __init platform_setup(void) { #ifdef CONFIG_PCI init_overdrive_fpga(); - galileo_init(); + galileo_init(); #endif - board_time_init = od_time_init; - /* Enable RS232 receive buffers */ writel(0x1e, OVERDRIVE_CTRL); } diff --git a/arch/sh/boards/overdrive/time.c b/arch/sh/boards/overdrive/time.c deleted file mode 100644 index 68533690e09..00000000000 --- a/arch/sh/boards/overdrive/time.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * arch/sh/boards/overdrive/time.c - * - * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) - * Copyright (C) 2002 Paul Mundt (lethal@chaoticdreams.org) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * STMicroelectronics Overdrive Support. - */ - -void od_time_init(void) -{ - struct frqcr_data { - unsigned short frqcr; - struct { - unsigned char multiplier; - unsigned char divisor; - } factor[3]; - }; - - static struct frqcr_data st40_frqcr_table[] = { - { 0x000, {{1,1}, {1,1}, {1,2}}}, - { 0x002, {{1,1}, {1,1}, {1,4}}}, - { 0x004, {{1,1}, {1,1}, {1,8}}}, - { 0x008, {{1,1}, {1,2}, {1,2}}}, - { 0x00A, {{1,1}, {1,2}, {1,4}}}, - { 0x00C, {{1,1}, {1,2}, {1,8}}}, - { 0x011, {{1,1}, {2,3}, {1,6}}}, - { 0x013, {{1,1}, {2,3}, {1,3}}}, - { 0x01A, {{1,1}, {1,2}, {1,4}}}, - { 0x01C, {{1,1}, {1,2}, {1,8}}}, - { 0x023, {{1,1}, {2,3}, {1,3}}}, - { 0x02C, {{1,1}, {1,2}, {1,8}}}, - { 0x048, {{1,2}, {1,2}, {1,4}}}, - { 0x04A, {{1,2}, {1,2}, {1,6}}}, - { 0x04C, {{1,2}, {1,2}, {1,8}}}, - { 0x05A, {{1,2}, {1,3}, {1,6}}}, - { 0x05C, {{1,2}, {1,3}, {1,6}}}, - { 0x063, {{1,2}, {1,4}, {1,4}}}, - { 0x06C, {{1,2}, {1,4}, {1,8}}}, - { 0x091, {{1,3}, {1,3}, {1,6}}}, - { 0x093, {{1,3}, {1,3}, {1,6}}}, - { 0x0A3, {{1,3}, {1,6}, {1,6}}}, - { 0x0DA, {{1,4}, {1,4}, {1,8}}}, - { 0x0DC, {{1,4}, {1,4}, {1,8}}}, - { 0x0EC, {{1,4}, {1,8}, {1,8}}}, - { 0x123, {{1,4}, {1,4}, {1,8}}}, - { 0x16C, {{1,4}, {1,8}, {1,8}}}, - }; - - struct memclk_data { - unsigned char multiplier; - unsigned char divisor; - }; - static struct memclk_data st40_memclk_table[8] = { - {1,1}, // 000 - {1,2}, // 001 - {1,3}, // 010 - {2,3}, // 011 - {1,4}, // 100 - {1,6}, // 101 - {1,8}, // 110 - {1,8} // 111 - }; - - unsigned long pvr; - - /* - * This should probably be moved into the SH3 probing code, and then - * use the processor structure to determine which CPU we are running - * on. - */ - pvr = ctrl_inl(CCN_PVR); - printk("PVR %08x\n", pvr); - - if (((pvr >> CCN_PVR_CHIP_SHIFT) & CCN_PVR_CHIP_MASK) == CCN_PVR_CHIP_ST40STB1) { - /* - * Unfortunatly the STB1 FRQCR values are different from the - * 7750 ones. - */ - struct frqcr_data *d; - int a; - unsigned long memclkcr; - struct memclk_data *e; - - for (a=0; afrqcr == (frqcr & 0x1ff)) - break; - } - if (a == ARRAY_SIZE(st40_frqcr_table)) { - d = st40_frqcr_table; - printk("ERROR: Unrecognised FRQCR value, using default multipliers\n"); - } - - memclkcr = ctrl_inl(CLOCKGEN_MEMCLKCR); - e = &st40_memclk_table[memclkcr & MEMCLKCR_RATIO_MASK]; - - printk("Clock multipliers: CPU: %d/%d Bus: %d/%d Mem: %d/%d Periph: %d/%d\n", - d->factor[0].multiplier, d->factor[0].divisor, - d->factor[1].multiplier, d->factor[1].divisor, - e->multiplier, e->divisor, - d->factor[2].multiplier, d->factor[2].divisor); - - current_cpu_data.master_clock = current_cpu_data.module_clock * - d->factor[2].divisor / - d->factor[2].multiplier; - current_cpu_data.bus_clock = current_cpu_data.master_clock * - d->factor[1].multiplier / - d->factor[1].divisor; - current_cpu_data.memory_clock = current_cpu_data.master_clock * - e->multiplier / e->divisor; - current_cpu_data.cpu_clock = current_cpu_data.master_clock * - d->factor[0].multiplier / - d->factor[0].divisor; -} - diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c new file mode 100644 index 00000000000..989e7fdd524 --- /dev/null +++ b/arch/sh/kernel/cpu/clock.c @@ -0,0 +1,287 @@ +/* + * arch/sh/kernel/cpu/clock.c - SuperH clock framework + * + * Copyright (C) 2005 Paul Mundt + * + * This clock framework is derived from the OMAP version by: + * + * Copyright (C) 2004 Nokia Corporation + * Written by Tuukka Tikkanen + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static LIST_HEAD(clock_list); +static DEFINE_SPINLOCK(clock_lock); +static DECLARE_MUTEX(clock_list_sem); + +/* + * Each subtype is expected to define the init routines for these clocks, + * as each subtype (or processor family) will have these clocks at the + * very least. These are all provided through the CPG, which even some of + * the more quirky parts (such as ST40, SH4-202, etc.) still have. + * + * The processor-specific code is expected to register any additional + * clock sources that are of interest. + */ +static struct clk master_clk = { + .name = "master_clk", + .flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES, +#ifdef CONFIG_SH_PCLK_FREQ_BOOL + .rate = CONFIG_SH_PCLK_FREQ, +#endif +}; + +static struct clk module_clk = { + .name = "module_clk", + .parent = &master_clk, + .flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES, +}; + +static struct clk bus_clk = { + .name = "bus_clk", + .parent = &master_clk, + .flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES, +}; + +static struct clk cpu_clk = { + .name = "cpu_clk", + .parent = &master_clk, + .flags = CLK_ALWAYS_ENABLED, +}; + +/* + * The ordering of these clocks matters, do not change it. + */ +static struct clk *onchip_clocks[] = { + &master_clk, + &module_clk, + &bus_clk, + &cpu_clk, +}; + +static void propagate_rate(struct clk *clk) +{ + struct clk *clkp; + + list_for_each_entry(clkp, &clock_list, node) { + if (likely(clkp->parent != clk)) + continue; + if (likely(clkp->ops && clkp->ops->recalc)) + clkp->ops->recalc(clkp); + } +} + +int __clk_enable(struct clk *clk) +{ + /* + * See if this is the first time we're enabling the clock, some + * clocks that are always enabled still require "special" + * initialization. This is especially true if the clock mode + * changes and the clock needs to hunt for the proper set of + * divisors to use before it can effectively recalc. + */ + if (unlikely(atomic_read(&clk->kref.refcount) == 1)) + if (clk->ops && clk->ops->init) + clk->ops->init(clk); + + if (clk->flags & CLK_ALWAYS_ENABLED) + return 0; + + if (likely(clk->ops && clk->ops->enable)) + clk->ops->enable(clk); + + kref_get(&clk->kref); + return 0; +} + +int clk_enable(struct clk *clk) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&clock_lock, flags); + ret = __clk_enable(clk); + spin_unlock_irqrestore(&clock_lock, flags); + + return ret; +} + +static void clk_kref_release(struct kref *kref) +{ + /* Nothing to do */ +} + +void __clk_disable(struct clk *clk) +{ + if (clk->flags & CLK_ALWAYS_ENABLED) + return; + + kref_put(&clk->kref, clk_kref_release); +} + +void clk_disable(struct clk *clk) +{ + unsigned long flags; + + spin_lock_irqsave(&clock_lock, flags); + __clk_disable(clk); + spin_unlock_irqrestore(&clock_lock, flags); +} + +int clk_register(struct clk *clk) +{ + down(&clock_list_sem); + + list_add(&clk->node, &clock_list); + kref_init(&clk->kref); + + up(&clock_list_sem); + + return 0; +} + +void clk_unregister(struct clk *clk) +{ + down(&clock_list_sem); + list_del(&clk->node); + up(&clock_list_sem); +} + +inline unsigned long clk_get_rate(struct clk *clk) +{ + return clk->rate; +} + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + int ret = -EOPNOTSUPP; + + if (likely(clk->ops && clk->ops->set_rate)) { + unsigned long flags; + + spin_lock_irqsave(&clock_lock, flags); + ret = clk->ops->set_rate(clk, rate); + spin_unlock_irqrestore(&clock_lock, flags); + } + + if (unlikely(clk->flags & CLK_RATE_PROPAGATES)) + propagate_rate(clk); + + return ret; +} + +void clk_recalc_rate(struct clk *clk) +{ + if (likely(clk->ops && clk->ops->recalc)) { + unsigned long flags; + + spin_lock_irqsave(&clock_lock, flags); + clk->ops->recalc(clk); + spin_unlock_irqrestore(&clock_lock, flags); + } + + if (unlikely(clk->flags & CLK_RATE_PROPAGATES)) + propagate_rate(clk); +} + +struct clk *clk_get(const char *id) +{ + struct clk *p, *clk = ERR_PTR(-ENOENT); + + down(&clock_list_sem); + list_for_each_entry(p, &clock_list, node) { + if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { + clk = p; + break; + } + } + up(&clock_list_sem); + + return clk; +} + +void clk_put(struct clk *clk) +{ + if (clk && !IS_ERR(clk)) + module_put(clk->owner); +} + +void __init __attribute__ ((weak)) +arch_init_clk_ops(struct clk_ops **ops, int type) +{ +} + +int __init clk_init(void) +{ + int i, ret = 0; + + if (unlikely(!master_clk.rate)) + /* + * NOTE: This will break if the default divisor has been + * changed. + * + * No one should be changing the default on us however, + * expect that a sane value for CONFIG_SH_PCLK_FREQ will + * be defined in the event of a different divisor. + */ + master_clk.rate = get_timer_frequency() * 4; + + for (i = 0; i < ARRAY_SIZE(onchip_clocks); i++) { + struct clk *clk = onchip_clocks[i]; + + arch_init_clk_ops(&clk->ops, i); + ret |= clk_register(clk); + clk_enable(clk); + } + + /* Kick the child clocks.. */ + propagate_rate(&master_clk); + propagate_rate(&bus_clk); + + return ret; +} + +int show_clocks(struct seq_file *m) +{ + struct clk *clk; + + list_for_each_entry_reverse(clk, &clock_list, node) { + unsigned long rate = clk_get_rate(clk); + + /* + * Don't bother listing dummy clocks with no ancestry + * that only support enable and disable ops. + */ + if (unlikely(!rate && !clk->parent)) + continue; + + seq_printf(m, "%-12s\t: %ld.%02ldMHz\n", clk->name, + rate / 1000000, (rate % 1000000) / 10000); + } + + return 0; +} + +EXPORT_SYMBOL_GPL(clk_register); +EXPORT_SYMBOL_GPL(clk_unregister); +EXPORT_SYMBOL_GPL(clk_get); +EXPORT_SYMBOL_GPL(clk_put); +EXPORT_SYMBOL_GPL(clk_enable); +EXPORT_SYMBOL_GPL(clk_disable); +EXPORT_SYMBOL_GPL(__clk_enable); +EXPORT_SYMBOL_GPL(__clk_disable); +EXPORT_SYMBOL_GPL(clk_get_rate); +EXPORT_SYMBOL_GPL(clk_set_rate); +EXPORT_SYMBOL_GPL(clk_recalc_rate); diff --git a/arch/sh/kernel/cpu/sh3/Makefile b/arch/sh/kernel/cpu/sh3/Makefile index a64532e4dc6..b54dbb9a0c8 100644 --- a/arch/sh/kernel/cpu/sh3/Makefile +++ b/arch/sh/kernel/cpu/sh3/Makefile @@ -4,3 +4,10 @@ obj-y := ex.o probe.o +clock-$(CONFIG_CPU_SH3) := clock-sh3.o +clock-$(CONFIG_CPU_SUBTYPE_SH7300) := clock-sh7300.o +clock-$(CONFIG_CPU_SUBTYPE_SH7705) := clock-sh7705.o +clock-$(CONFIG_CPU_SUBTYPE_SH7709) := clock-sh7709.o + +obj-y += $(clock-y) + diff --git a/arch/sh/kernel/cpu/sh3/clock-sh3.c b/arch/sh/kernel/cpu/sh3/clock-sh3.c new file mode 100644 index 00000000000..c3c945958ba --- /dev/null +++ b/arch/sh/kernel/cpu/sh3/clock-sh3.c @@ -0,0 +1,89 @@ +/* + * arch/sh/kernel/cpu/sh3/clock-sh3.c + * + * Generic SH-3 support for the clock framework + * + * Copyright (C) 2005 Paul Mundt + * + * FRQCR parsing hacked out of arch/sh/kernel/time.c + * + * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka + * Copyright (C) 2000 Philipp Rumpf + * Copyright (C) 2002, 2003, 2004 Paul Mundt + * Copyright (C) 2002 M. R. Brown + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include + +static int stc_multipliers[] = { 1, 2, 3, 4, 6, 1, 1, 1 }; +static int ifc_divisors[] = { 1, 2, 3, 4, 1, 1, 1, 1 }; +static int pfc_divisors[] = { 1, 2, 3, 4, 6, 1, 1, 1 }; + +static void master_clk_init(struct clk *clk) +{ + int frqcr = ctrl_inw(FRQCR); + int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003); + + clk->rate *= pfc_divisors[idx]; +} + +static struct clk_ops sh3_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int frqcr = ctrl_inw(FRQCR); + int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003); + + clk->rate = clk->parent->rate / pfc_divisors[idx]; +} + +static struct clk_ops sh3_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + int frqcr = ctrl_inw(FRQCR); + int idx = ((frqcr & 0x8000) >> 13) | ((frqcr & 0x0030) >> 4); + + clk->rate = clk->parent->rate / stc_multipliers[idx]; +} + +static struct clk_ops sh3_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + int frqcr = ctrl_inw(FRQCR); + int idx = ((frqcr & 0x4000) >> 12) | ((frqcr & 0x000c) >> 2); + + clk->rate = clk->parent->rate / ifc_divisors[idx]; +} + +static struct clk_ops sh3_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh3_clk_ops[] = { + &sh3_master_clk_ops, + &sh3_module_clk_ops, + &sh3_bus_clk_ops, + &sh3_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh3_clk_ops)) + *ops = sh3_clk_ops[idx]; +} + diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7300.c b/arch/sh/kernel/cpu/sh3/clock-sh7300.c new file mode 100644 index 00000000000..e804174b962 --- /dev/null +++ b/arch/sh/kernel/cpu/sh3/clock-sh7300.c @@ -0,0 +1,78 @@ +/* + * arch/sh/kernel/cpu/sh3/clock-sh7300.c + * + * SH7300 support for the clock framework + * + * Copyright (C) 2005 Paul Mundt + * + * FRQCR parsing hacked out of arch/sh/kernel/time.c + * + * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka + * Copyright (C) 2000 Philipp Rumpf + * Copyright (C) 2002, 2003, 2004 Paul Mundt + * Copyright (C) 2002 M. R. Brown + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include + +static int md_table[] = { 1, 2, 3, 4, 6, 8, 12 }; + +static void master_clk_init(struct clk *clk) +{ + clk->rate *= md_table[ctrl_inw(FRQCR) & 0x0007]; +} + +static struct clk_ops sh7300_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FRQCR) & 0x0007); + clk->rate = clk->parent->rate / md_table[idx]; +} + +static struct clk_ops sh7300_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FRQCR) & 0x0700) >> 8; + clk->rate = clk->parent->rate / md_table[idx]; +} + +static struct clk_ops sh7300_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FRQCR) & 0x0070) >> 4; + clk->rate = clk->parent->rate / md_table[idx]; +} + +static struct clk_ops sh7300_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh7300_clk_ops[] = { + &sh7300_master_clk_ops, + &sh7300_module_clk_ops, + &sh7300_bus_clk_ops, + &sh7300_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh7300_clk_ops)) + *ops = sh7300_clk_ops[idx]; +} + diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7705.c b/arch/sh/kernel/cpu/sh3/clock-sh7705.c new file mode 100644 index 00000000000..dfdbf3277fd --- /dev/null +++ b/arch/sh/kernel/cpu/sh3/clock-sh7705.c @@ -0,0 +1,84 @@ +/* + * arch/sh/kernel/cpu/sh3/clock-sh7705.c + * + * SH7705 support for the clock framework + * + * Copyright (C) 2005 Paul Mundt + * + * FRQCR parsing hacked out of arch/sh/kernel/time.c + * + * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka + * Copyright (C) 2000 Philipp Rumpf + * Copyright (C) 2002, 2003, 2004 Paul Mundt + * Copyright (C) 2002 M. R. Brown + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include + +/* + * SH7705 uses the same divisors as the generic SH-3 case, it's just the + * FRQCR layout that is a bit different.. + */ +static int stc_multipliers[] = { 1, 2, 3, 4, 6, 1, 1, 1 }; +static int ifc_divisors[] = { 1, 2, 3, 4, 1, 1, 1, 1 }; +static int pfc_divisors[] = { 1, 2, 3, 4, 6, 1, 1, 1 }; + +static void master_clk_init(struct clk *clk) +{ + clk->rate *= pfc_divisors[ctrl_inw(FRQCR) & 0x0003]; +} + +static struct clk_ops sh7705_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int idx = ctrl_inw(FRQCR) & 0x0003; + clk->rate = clk->parent->rate / pfc_divisors[idx]; +} + +static struct clk_ops sh7705_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FRQCR) & 0x0300) >> 8; + clk->rate = clk->parent->rate / stc_multipliers[idx]; +} + +static struct clk_ops sh7705_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FRQCR) & 0x0030) >> 4; + clk->rate = clk->parent->rate / ifc_divisors[idx]; +} + +static struct clk_ops sh7705_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh7705_clk_ops[] = { + &sh7705_master_clk_ops, + &sh7705_module_clk_ops, + &sh7705_bus_clk_ops, + &sh7705_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh7705_clk_ops)) + *ops = sh7705_clk_ops[idx]; +} + diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7709.c b/arch/sh/kernel/cpu/sh3/clock-sh7709.c new file mode 100644 index 00000000000..10461a745e5 --- /dev/null +++ b/arch/sh/kernel/cpu/sh3/clock-sh7709.c @@ -0,0 +1,96 @@ +/* + * arch/sh/kernel/cpu/sh3/clock-sh7709.c + * + * SH7709 support for the clock framework + * + * Copyright (C) 2005 Andriy Skulysh + * + * Based on arch/sh/kernel/cpu/sh3/clock-sh7705.c + * Copyright (C) 2005 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include + +static int stc_multipliers[] = { 1, 2, 4, 8, 3, 6, 1, 1 }; +static int ifc_divisors[] = { 1, 2, 4, 1, 3, 1, 1, 1 }; +static int pfc_divisors[] = { 1, 2, 4, 1, 3, 6, 1, 1 }; + +static void set_bus_parent(struct clk *clk) +{ + struct clk *bus_clk = clk_get("bus_clk"); + clk->parent = bus_clk; + clk_put(bus_clk); +} + +static void master_clk_init(struct clk *clk) +{ + int frqcr = ctrl_inw(FRQCR); + int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003); + + clk->rate *= pfc_divisors[idx]; +} + +static struct clk_ops sh7709_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int frqcr = ctrl_inw(FRQCR); + int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003); + + clk->rate = clk->parent->rate / pfc_divisors[idx]; +} + +static struct clk_ops sh7709_module_clk_ops = { +#ifdef CLOCK_MODE_0_1_2_7 + .init = set_bus_parent, +#endif + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + int frqcr = ctrl_inw(FRQCR); + int idx = (frqcr & 0x0080) ? + ((frqcr & 0x8000) >> 13) | ((frqcr & 0x0030) >> 4) : 1; + + clk->rate = clk->parent->rate * stc_multipliers[idx]; +} + +static struct clk_ops sh7709_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + int frqcr = ctrl_inw(FRQCR); + int idx = ((frqcr & 0x4000) >> 12) | ((frqcr & 0x000c) >> 2); + + clk->rate = clk->parent->rate / ifc_divisors[idx]; +} + +static struct clk_ops sh7709_cpu_clk_ops = { + .init = set_bus_parent, + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh7709_clk_ops[] = { + &sh7709_master_clk_ops, + &sh7709_module_clk_ops, + &sh7709_bus_clk_ops, + &sh7709_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh7709_clk_ops)) + *ops = sh7709_clk_ops[idx]; +} diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile index ead1071eac7..3d5cafc71ae 100644 --- a/arch/sh/kernel/cpu/sh4/Makefile +++ b/arch/sh/kernel/cpu/sh4/Makefile @@ -5,6 +5,15 @@ obj-y := ex.o probe.o obj-$(CONFIG_SH_FPU) += fpu.o -obj-$(CONFIG_CPU_SUBTYPE_ST40STB1) += irq_intc2.o obj-$(CONFIG_SH_STORE_QUEUES) += sq.o +# Primary on-chip clocks (common) +clock-$(CONFIG_CPU_SH4) := clock-sh4.o +clock-$(CONFIG_CPU_SUBTYPE_SH73180) := clock-sh73180.o +clock-$(CONFIG_CPU_SUBTYPE_SH7770) := clock-sh7770.o +clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o + +# Additional clocks by subtype +clock-$(CONFIG_CPU_SUBTYPE_SH4_202) += clock-sh4-202.o + +obj-y += $(clock-y) diff --git a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c new file mode 100644 index 00000000000..bfdf5fe8d94 --- /dev/null +++ b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c @@ -0,0 +1,179 @@ +/* + * arch/sh/kernel/cpu/sh4/clock-sh4-202.c + * + * Additional SH4-202 support for the clock framework + * + * Copyright (C) 2005 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include + +#define CPG2_FRQCR3 0xfe0a0018 + +static int frqcr3_divisors[] = { 1, 2, 3, 4, 6, 8, 16 }; +static int frqcr3_values[] = { 0, 1, 2, 3, 4, 5, 6 }; + +static void emi_clk_recalc(struct clk *clk) +{ + int idx = ctrl_inl(CPG2_FRQCR3) & 0x0007; + clk->rate = clk->parent->rate / frqcr3_divisors[idx]; +} + +static inline int frqcr3_lookup(struct clk *clk, unsigned long rate) +{ + int divisor = clk->parent->rate / rate; + int i; + + for (i = 0; i < ARRAY_SIZE(frqcr3_divisors); i++) + if (frqcr3_divisors[i] == divisor) + return frqcr3_values[i]; + + /* Safe fallback */ + return 5; +} + +static struct clk_ops sh4202_emi_clk_ops = { + .recalc = emi_clk_recalc, +}; + +static struct clk sh4202_emi_clk = { + .name = "emi_clk", + .flags = CLK_ALWAYS_ENABLED, + .ops = &sh4202_emi_clk_ops, +}; + +static void femi_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inl(CPG2_FRQCR3) >> 3) & 0x0007; + clk->rate = clk->parent->rate / frqcr3_divisors[idx]; +} + +static struct clk_ops sh4202_femi_clk_ops = { + .recalc = femi_clk_recalc, +}; + +static struct clk sh4202_femi_clk = { + .name = "femi_clk", + .flags = CLK_ALWAYS_ENABLED, + .ops = &sh4202_femi_clk_ops, +}; + +static void shoc_clk_init(struct clk *clk) +{ + int i; + + /* + * For some reason, the shoc_clk seems to be set to some really + * insane value at boot (values outside of the allowable frequency + * range for instance). We deal with this by scaling it back down + * to something sensible just in case. + * + * Start scaling from the high end down until we find something + * that passes rate verification.. + */ + for (i = 0; i < ARRAY_SIZE(frqcr3_divisors); i++) { + int divisor = frqcr3_divisors[i]; + + if (clk->ops->set_rate(clk, clk->parent->rate / divisor) == 0) + break; + } + + WARN_ON(i == ARRAY_SIZE(frqcr3_divisors)); /* Undefined clock */ +} + +static void shoc_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inl(CPG2_FRQCR3) >> 6) & 0x0007; + clk->rate = clk->parent->rate / frqcr3_divisors[idx]; +} + +static int shoc_clk_verify_rate(struct clk *clk, unsigned long rate) +{ + struct clk *bclk = clk_get("bus_clk"); + unsigned long bclk_rate = clk_get_rate(bclk); + + clk_put(bclk); + + if (rate > bclk_rate) + return 1; + if (rate > 66000000) + return 1; + + return 0; +} + +static int shoc_clk_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned long frqcr3; + unsigned int tmp; + + /* Make sure we have something sensible to switch to */ + if (shoc_clk_verify_rate(clk, rate) != 0) + return -EINVAL; + + tmp = frqcr3_lookup(clk, rate); + + frqcr3 = ctrl_inl(CPG2_FRQCR3); + frqcr3 &= ~(0x0007 << 6); + frqcr3 |= tmp << 6; + ctrl_outl(frqcr3, CPG2_FRQCR3); + + clk->rate = clk->parent->rate / frqcr3_divisors[tmp]; + + return 0; +} + +static struct clk_ops sh4202_shoc_clk_ops = { + .init = shoc_clk_init, + .recalc = shoc_clk_recalc, + .set_rate = shoc_clk_set_rate, +}; + +static struct clk sh4202_shoc_clk = { + .name = "shoc_clk", + .flags = CLK_ALWAYS_ENABLED, + .ops = &sh4202_shoc_clk_ops, +}; + +static struct clk *sh4202_onchip_clocks[] = { + &sh4202_emi_clk, + &sh4202_femi_clk, + &sh4202_shoc_clk, +}; + +static int __init sh4202_clk_init(void) +{ + struct clk *clk = clk_get("master_clk"); + int i; + + for (i = 0; i < ARRAY_SIZE(sh4202_onchip_clocks); i++) { + struct clk *clkp = sh4202_onchip_clocks[i]; + + clkp->parent = clk; + clk_register(clkp); + clk_enable(clkp); + } + + /* + * Now that we have the rest of the clocks registered, we need to + * force the parent clock to propagate so that these clocks will + * automatically figure out their rate. We cheat by handing the + * parent clock its current rate and forcing child propagation. + */ + clk_set_rate(clk, clk_get_rate(clk)); + + clk_put(clk); + + return 0; +} + +arch_initcall(sh4202_clk_init); + diff --git a/arch/sh/kernel/cpu/sh4/clock-sh4.c b/arch/sh/kernel/cpu/sh4/clock-sh4.c new file mode 100644 index 00000000000..dca9f87a12d --- /dev/null +++ b/arch/sh/kernel/cpu/sh4/clock-sh4.c @@ -0,0 +1,80 @@ +/* + * arch/sh/kernel/cpu/sh4/clock-sh4.c + * + * Generic SH-4 support for the clock framework + * + * Copyright (C) 2005 Paul Mundt + * + * FRQCR parsing hacked out of arch/sh/kernel/time.c + * + * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka + * Copyright (C) 2000 Philipp Rumpf + * Copyright (C) 2002, 2003, 2004 Paul Mundt + * Copyright (C) 2002 M. R. Brown + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include + +static int ifc_divisors[] = { 1, 2, 3, 4, 6, 8, 1, 1 }; +#define bfc_divisors ifc_divisors /* Same */ +static int pfc_divisors[] = { 2, 3, 4, 6, 8, 2, 2, 2 }; + +static void master_clk_init(struct clk *clk) +{ + clk->rate *= pfc_divisors[ctrl_inw(FRQCR) & 0x0007]; +} + +static struct clk_ops sh4_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FRQCR) & 0x0007); + clk->rate = clk->parent->rate / pfc_divisors[idx]; +} + +static struct clk_ops sh4_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FRQCR) >> 3) & 0x0007; + clk->rate = clk->parent->rate / bfc_divisors[idx]; +} + +static struct clk_ops sh4_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FRQCR) >> 6) & 0x0007; + clk->rate = clk->parent->rate / ifc_divisors[idx]; +} + +static struct clk_ops sh4_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh4_clk_ops[] = { + &sh4_master_clk_ops, + &sh4_module_clk_ops, + &sh4_bus_clk_ops, + &sh4_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh4_clk_ops)) + *ops = sh4_clk_ops[idx]; +} + diff --git a/arch/sh/kernel/cpu/sh4/clock-sh73180.c b/arch/sh/kernel/cpu/sh4/clock-sh73180.c new file mode 100644 index 00000000000..2fa5cb2ae68 --- /dev/null +++ b/arch/sh/kernel/cpu/sh4/clock-sh73180.c @@ -0,0 +1,81 @@ +/* + * arch/sh/kernel/cpu/sh4/clock-sh73180.c + * + * SH73180 support for the clock framework + * + * Copyright (C) 2005 Paul Mundt + * + * FRQCR parsing hacked out of arch/sh/kernel/time.c + * + * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka + * Copyright (C) 2000 Philipp Rumpf + * Copyright (C) 2002, 2003, 2004 Paul Mundt + * Copyright (C) 2002 M. R. Brown + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include + +/* + * SH73180 uses a common set of divisors, so this is quite simple.. + */ +static int divisors[] = { 1, 2, 3, 4, 6, 8, 12, 16 }; + +static void master_clk_init(struct clk *clk) +{ + clk->rate *= divisors[ctrl_inl(FRQCR) & 0x0007]; +} + +static struct clk_ops sh73180_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inl(FRQCR) & 0x0007); + clk->rate = clk->parent->rate / divisors[idx]; +} + +static struct clk_ops sh73180_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inl(FRQCR) >> 12) & 0x0007; + clk->rate = clk->parent->rate / divisors[idx]; +} + +static struct clk_ops sh73180_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inl(FRQCR) >> 20) & 0x0007; + clk->rate = clk->parent->rate / divisors[idx]; +} + +static struct clk_ops sh73180_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh73180_clk_ops[] = { + &sh73180_master_clk_ops, + &sh73180_module_clk_ops, + &sh73180_bus_clk_ops, + &sh73180_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh73180_clk_ops)) + *ops = sh73180_clk_ops[idx]; +} + diff --git a/arch/sh/kernel/cpu/sh4/clock-sh7770.c b/arch/sh/kernel/cpu/sh4/clock-sh7770.c new file mode 100644 index 00000000000..c8694bac647 --- /dev/null +++ b/arch/sh/kernel/cpu/sh4/clock-sh7770.c @@ -0,0 +1,73 @@ +/* + * arch/sh/kernel/cpu/sh4/clock-sh7770.c + * + * SH7770 support for the clock framework + * + * Copyright (C) 2005 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include + +static int ifc_divisors[] = { 1, 1, 1, 1, 1, 1, 1, 1 }; +static int bfc_divisors[] = { 1, 1, 1, 1, 1, 8,12, 1 }; +static int pfc_divisors[] = { 1, 8, 1,10,12,16, 1, 1 }; + +static void master_clk_init(struct clk *clk) +{ + clk->rate *= pfc_divisors[(ctrl_inl(FRQCR) >> 28) & 0x000f]; +} + +static struct clk_ops sh7770_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int idx = ((ctrl_inl(FRQCR) >> 28) & 0x000f); + clk->rate = clk->parent->rate / pfc_divisors[idx]; +} + +static struct clk_ops sh7770_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inl(FRQCR) & 0x000f); + clk->rate = clk->parent->rate / bfc_divisors[idx]; +} + +static struct clk_ops sh7770_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + int idx = ((ctrl_inl(FRQCR) >> 24) & 0x000f); + clk->rate = clk->parent->rate / ifc_divisors[idx]; +} + +static struct clk_ops sh7770_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh7770_clk_ops[] = { + &sh7770_master_clk_ops, + &sh7770_module_clk_ops, + &sh7770_bus_clk_ops, + &sh7770_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh7770_clk_ops)) + *ops = sh7770_clk_ops[idx]; +} + diff --git a/arch/sh/kernel/cpu/sh4/clock-sh7780.c b/arch/sh/kernel/cpu/sh4/clock-sh7780.c new file mode 100644 index 00000000000..93ad367342c --- /dev/null +++ b/arch/sh/kernel/cpu/sh4/clock-sh7780.c @@ -0,0 +1,126 @@ +/* + * arch/sh/kernel/cpu/sh4/clock-sh7780.c + * + * SH7780 support for the clock framework + * + * Copyright (C) 2005 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include + +static int ifc_divisors[] = { 2, 4 }; +static int bfc_divisors[] = { 1, 1, 1, 8, 12, 16, 24, 1 }; +static int pfc_divisors[] = { 1, 24, 24, 1 }; +static int cfc_divisors[] = { 1, 1, 4, 1, 6, 1, 1, 1 }; + +static void master_clk_init(struct clk *clk) +{ + clk->rate *= pfc_divisors[ctrl_inl(FRQCR) & 0x0003]; +} + +static struct clk_ops sh7780_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inl(FRQCR) & 0x0003); + clk->rate = clk->parent->rate / pfc_divisors[idx]; +} + +static struct clk_ops sh7780_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + int idx = ((ctrl_inl(FRQCR) >> 16) & 0x0007); + clk->rate = clk->parent->rate / bfc_divisors[idx]; +} + +static struct clk_ops sh7780_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + int idx = ((ctrl_inl(FRQCR) >> 24) & 0x0001); + clk->rate = clk->parent->rate / ifc_divisors[idx]; +} + +static struct clk_ops sh7780_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh7780_clk_ops[] = { + &sh7780_master_clk_ops, + &sh7780_module_clk_ops, + &sh7780_bus_clk_ops, + &sh7780_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh7780_clk_ops)) + *ops = sh7780_clk_ops[idx]; +} + +static void shyway_clk_recalc(struct clk *clk) +{ + int idx = ((ctrl_inl(FRQCR) >> 20) & 0x0007); + clk->rate = clk->parent->rate / cfc_divisors[idx]; +} + +static struct clk_ops sh7780_shyway_clk_ops = { + .recalc = shyway_clk_recalc, +}; + +static struct clk sh7780_shyway_clk = { + .name = "shyway_clk", + .flags = CLK_ALWAYS_ENABLED, + .ops = &sh7780_shyway_clk_ops, +}; + +/* + * Additional SH7780-specific on-chip clocks that aren't already part of the + * clock framework + */ +static struct clk *sh7780_onchip_clocks[] = { + &sh7780_shyway_clk, +}; + +static int __init sh7780_clk_init(void) +{ + struct clk *clk = clk_get("master_clk"); + int i; + + for (i = 0; i < ARRAY_SIZE(sh7780_onchip_clocks); i++) { + struct clk *clkp = sh7780_onchip_clocks[i]; + + clkp->parent = clk; + clk_register(clkp); + clk_enable(clkp); + } + + /* + * Now that we have the rest of the clocks registered, we need to + * force the parent clock to propagate so that these clocks will + * automatically figure out their rate. We cheat by handing the + * parent clock its current rate and forcing child propagation. + */ + clk_set_rate(clk, clk_get_rate(clk)); + + clk_put(clk); + + return 0; +} + +arch_initcall(sh7780_clk_init); + diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c index 671b876416b..314a275c04e 100644 --- a/arch/sh/kernel/time.c +++ b/arch/sh/kernel/time.c @@ -3,7 +3,7 @@ * * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka * Copyright (C) 2000 Philipp Rumpf - * Copyright (C) 2002, 2003, 2004 Paul Mundt + * Copyright (C) 2002, 2003, 2004, 2005 Paul Mundt * Copyright (C) 2002 M. R. Brown * * Some code taken from i386 version. @@ -11,50 +11,21 @@ */ #include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include +#include #include -#include #include - -#include -#include -#include -#include -#include -#include +#include #include -#include -#include -#ifdef CONFIG_SH_KGDB +#include #include -#endif - -#include -#include - -#define TMU_TOCR_INIT 0x00 -#define TMU0_TCR_INIT 0x0020 -#define TMU_TSTR_INIT 1 - -#define TMU0_TCR_CALIB 0x0000 - -#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 -#define CLOCKGEN_MEMCLKCR 0xbb040038 -#define MEMCLKCR_RATIO_MASK 0x7 -#endif /* CONFIG_CPU_SUBTYPE_ST40STB1 */ extern unsigned long wall_jiffies; -#define TICK_SIZE (tick_nsec / 1000) -DEFINE_SPINLOCK(tmu0_lock); +struct sys_timer *sys_timer; + +/* Move this somewhere more sensible.. */ +DEFINE_SPINLOCK(rtc_lock); +EXPORT_SYMBOL(rtc_lock); /* XXX: Can we initialize this in a routine somewhere? Dreamcast doesn't want * these routines anywhere... */ @@ -66,98 +37,14 @@ void (*rtc_get_time)(struct timespec *); int (*rtc_set_time)(const time_t); #endif -#if defined(CONFIG_CPU_SUBTYPE_SH7300) -static int md_table[] = { 1, 2, 3, 4, 6, 8, 12 }; -#endif -#if defined(CONFIG_CPU_SH3) -static int stc_multipliers[] = { 1, 2, 3, 4, 6, 1, 1, 1 }; -static int stc_values[] = { 0, 1, 4, 2, 5, 0, 0, 0 }; -#define bfc_divisors stc_multipliers -#define bfc_values stc_values -static int ifc_divisors[] = { 1, 2, 3, 4, 1, 1, 1, 1 }; -static int ifc_values[] = { 0, 1, 4, 2, 0, 0, 0, 0 }; -static int pfc_divisors[] = { 1, 2, 3, 4, 6, 1, 1, 1 }; -static int pfc_values[] = { 0, 1, 4, 2, 5, 0, 0, 0 }; -#elif defined(CONFIG_CPU_SH4) -#if defined(CONFIG_CPU_SUBTYPE_SH73180) -static int ifc_divisors[] = { 1, 2, 3, 4, 6, 8, 12, 16 }; -static int ifc_values[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; -#define bfc_divisors ifc_divisors /* Same */ -#define bfc_values ifc_values -#define pfc_divisors ifc_divisors /* Same */ -#define pfc_values ifc_values -#else -static int ifc_divisors[] = { 1, 2, 3, 4, 6, 8, 1, 1 }; -static int ifc_values[] = { 0, 1, 2, 3, 0, 4, 0, 5 }; -#define bfc_divisors ifc_divisors /* Same */ -#define bfc_values ifc_values -static int pfc_divisors[] = { 2, 3, 4, 6, 8, 2, 2, 2 }; -static int pfc_values[] = { 0, 0, 1, 2, 0, 3, 0, 4 }; -#endif -#else -#error "Unknown ifc/bfc/pfc/stc values for this processor" -#endif - /* * Scheduler clock - returns current time in nanosec units. */ -unsigned long long sched_clock(void) +unsigned long long __attribute__ ((weak)) sched_clock(void) { return (unsigned long long)jiffies * (1000000000 / HZ); } -static unsigned long do_gettimeoffset(void) -{ - int count; - unsigned long flags; - - static int count_p = 0x7fffffff; /* for the first call after boot */ - static unsigned long jiffies_p = 0; - - /* - * cache volatile jiffies temporarily; we have IRQs turned off. - */ - unsigned long jiffies_t; - - spin_lock_irqsave(&tmu0_lock, flags); - /* timer count may underflow right here */ - count = ctrl_inl(TMU0_TCNT); /* read the latched count */ - - jiffies_t = jiffies; - - /* - * avoiding timer inconsistencies (they are rare, but they happen)... - * there is one kind of problem that must be avoided here: - * 1. the timer counter underflows - */ - - if( jiffies_t == jiffies_p ) { - if( count > count_p ) { - /* the nutcase */ - - if(ctrl_inw(TMU0_TCR) & 0x100) { /* Check UNF bit */ - /* - * We cannot detect lost timer interrupts ... - * well, that's why we call them lost, don't we? :) - * [hmm, on the Pentium and Alpha we can ... sort of] - */ - count -= LATCH; - } else { - printk("do_slow_gettimeoffset(): hardware timer problem?\n"); - } - } - } else - jiffies_p = jiffies_t; - - count_p = count; - spin_unlock_irqrestore(&tmu0_lock, flags); - - count = ((LATCH-1) - count) * TICK_SIZE; - count = (count + LATCH/2) / LATCH; - - return count; -} - void do_gettimeofday(struct timeval *tv) { unsigned long seq; @@ -166,7 +53,7 @@ void do_gettimeofday(struct timeval *tv) do { seq = read_seqbegin(&xtime_lock); - usec = do_gettimeoffset(); + usec = get_timer_offset(); lost = jiffies - wall_jiffies; if (lost) @@ -202,7 +89,7 @@ int do_settimeofday(struct timespec *tv) * wall time. Discover what correction gettimeofday() would have * made, and then undo it! */ - nsec -= 1000 * (do_gettimeoffset() + + nsec -= 1000 * (get_timer_offset() + (jiffies - wall_jiffies) * (1000000 / HZ)); wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); @@ -224,10 +111,10 @@ EXPORT_SYMBOL(do_settimeofday); static long last_rtc_update; /* - * timer_interrupt() needs to keep up the real-time clock, + * handle_timer_tick() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick */ -static inline void do_timer_interrupt(int irq, struct pt_regs *regs) +void handle_timer_tick(struct pt_regs *regs) { do_timer(regs); #ifndef CONFIG_SMP @@ -252,337 +139,35 @@ static inline void do_timer_interrupt(int irq, struct pt_regs *regs) if (rtc_set_time(xtime.tv_sec) == 0) last_rtc_update = xtime.tv_sec; else - last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ + /* do it again in 60s */ + last_rtc_update = xtime.tv_sec - 600; } } -/* - * This is the same as the above, except we _also_ save the current - * Time Stamp Counter value at the time of the timer interrupt, so that - * we later on can estimate the time of day more exactly. - */ -static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - unsigned long timer_status; - - /* Clear UNF bit */ - timer_status = ctrl_inw(TMU0_TCR); - timer_status &= ~0x100; - ctrl_outw(timer_status, TMU0_TCR); - - /* - * Here we are in the timer irq handler. We just have irqs locally - * disabled but we don't know if the timer_bh is running on the other - * CPU. We need to avoid to SMP race with it. NOTE: we don' t need - * the irq version of write_lock because as just said we have irq - * locally disabled. -arca - */ - write_seqlock(&xtime_lock); - do_timer_interrupt(irq, regs); - write_sequnlock(&xtime_lock); - - return IRQ_HANDLED; -} - -/* - * Hah! We'll see if this works (switching from usecs to nsecs). - */ -static unsigned int __init get_timer_frequency(void) -{ - u32 freq; - struct timespec ts1, ts2; - unsigned long diff_nsec; - unsigned long factor; - - /* Setup the timer: We don't want to generate interrupts, just - * have it count down at its natural rate. - */ - ctrl_outb(0, TMU_TSTR); -#if !defined(CONFIG_CPU_SUBTYPE_SH7300) - ctrl_outb(TMU_TOCR_INIT, TMU_TOCR); -#endif - ctrl_outw(TMU0_TCR_CALIB, TMU0_TCR); - ctrl_outl(0xffffffff, TMU0_TCOR); - ctrl_outl(0xffffffff, TMU0_TCNT); - - rtc_get_time(&ts2); - - do { - rtc_get_time(&ts1); - } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec); - - /* actually start the timer */ - ctrl_outb(TMU_TSTR_INIT, TMU_TSTR); - - do { - rtc_get_time(&ts2); - } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec); - - freq = 0xffffffff - ctrl_inl(TMU0_TCNT); - if (ts2.tv_nsec < ts1.tv_nsec) { - ts2.tv_nsec += 1000000000; - ts2.tv_sec--; - } - - diff_nsec = (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec); - - /* this should work well if the RTC has a precision of n Hz, where - * n is an integer. I don't think we have to worry about the other - * cases. */ - factor = (1000000000 + diff_nsec/2) / diff_nsec; - - if (factor * diff_nsec > 1100000000 || - factor * diff_nsec < 900000000) - panic("weird RTC (diff_nsec %ld)", diff_nsec); - - return freq * factor; -} - -void (*board_time_init)(void); -void (*board_timer_setup)(struct irqaction *irq); - -static unsigned int sh_pclk_freq __initdata = CONFIG_SH_PCLK_FREQ; - -static int __init sh_pclk_setup(char *str) -{ - unsigned int freq; - - if (get_option(&str, &freq)) - sh_pclk_freq = freq; - - return 1; -} -__setup("sh_pclk=", sh_pclk_setup); - -static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer", NULL, NULL}; - -void get_current_frequency_divisors(unsigned int *ifc, unsigned int *bfc, unsigned int *pfc) -{ - unsigned int frqcr = ctrl_inw(FRQCR); - -#if defined(CONFIG_CPU_SH3) -#if defined(CONFIG_CPU_SUBTYPE_SH7300) - *ifc = md_table[((frqcr & 0x0070) >> 4)]; - *bfc = md_table[((frqcr & 0x0700) >> 8)]; - *pfc = md_table[frqcr & 0x0007]; -#elif defined(CONFIG_CPU_SUBTYPE_SH7705) - *bfc = stc_multipliers[(frqcr & 0x0300) >> 8]; - *ifc = ifc_divisors[(frqcr & 0x0030) >> 4]; - *pfc = pfc_divisors[frqcr & 0x0003]; -#else - unsigned int tmp; - - tmp = (frqcr & 0x8000) >> 13; - tmp |= (frqcr & 0x0030) >> 4; - *bfc = stc_multipliers[tmp]; - tmp = (frqcr & 0x4000) >> 12; - tmp |= (frqcr & 0x000c) >> 2; - *ifc = ifc_divisors[tmp]; - tmp = (frqcr & 0x2000) >> 11; - tmp |= frqcr & 0x0003; - *pfc = pfc_divisors[tmp]; -#endif -#elif defined(CONFIG_CPU_SH4) -#if defined(CONFIG_CPU_SUBTYPE_SH73180) - *ifc = ifc_divisors[(frqcr>> 20) & 0x0007]; - *bfc = bfc_divisors[(frqcr>> 12) & 0x0007]; - *pfc = pfc_divisors[frqcr & 0x0007]; -#else - *ifc = ifc_divisors[(frqcr >> 6) & 0x0007]; - *bfc = bfc_divisors[(frqcr >> 3) & 0x0007]; - *pfc = pfc_divisors[frqcr & 0x0007]; -#endif -#endif -} - -/* - * This bit of ugliness builds up accessor routines to get at both - * the divisors and the physical values. - */ -#define _FREQ_TABLE(x) \ - unsigned int get_##x##_divisor(unsigned int value) \ - { return x##_divisors[value]; } \ - \ - unsigned int get_##x##_value(unsigned int divisor) \ - { return x##_values[(divisor - 1)]; } - -_FREQ_TABLE(ifc); -_FREQ_TABLE(bfc); -_FREQ_TABLE(pfc); - -#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 - -/* - * The ST40 divisors are totally different so we set the cpu data - * clocks using a different algorithm - * - * I've just plugged this from the 2.4 code - * - Alex Bennee - */ -#define CCN_PVR_CHIP_SHIFT 24 -#define CCN_PVR_CHIP_MASK 0xff -#define CCN_PVR_CHIP_ST40STB1 0x4 - - -struct frqcr_data { - unsigned short frqcr; - - struct { - unsigned char multiplier; - unsigned char divisor; - } factor[3]; -}; - -static struct frqcr_data st40_frqcr_table[] = { - { 0x000, {{1,1}, {1,1}, {1,2}}}, - { 0x002, {{1,1}, {1,1}, {1,4}}}, - { 0x004, {{1,1}, {1,1}, {1,8}}}, - { 0x008, {{1,1}, {1,2}, {1,2}}}, - { 0x00A, {{1,1}, {1,2}, {1,4}}}, - { 0x00C, {{1,1}, {1,2}, {1,8}}}, - { 0x011, {{1,1}, {2,3}, {1,6}}}, - { 0x013, {{1,1}, {2,3}, {1,3}}}, - { 0x01A, {{1,1}, {1,2}, {1,4}}}, - { 0x01C, {{1,1}, {1,2}, {1,8}}}, - { 0x023, {{1,1}, {2,3}, {1,3}}}, - { 0x02C, {{1,1}, {1,2}, {1,8}}}, - { 0x048, {{1,2}, {1,2}, {1,4}}}, - { 0x04A, {{1,2}, {1,2}, {1,6}}}, - { 0x04C, {{1,2}, {1,2}, {1,8}}}, - { 0x05A, {{1,2}, {1,3}, {1,6}}}, - { 0x05C, {{1,2}, {1,3}, {1,6}}}, - { 0x063, {{1,2}, {1,4}, {1,4}}}, - { 0x06C, {{1,2}, {1,4}, {1,8}}}, - { 0x091, {{1,3}, {1,3}, {1,6}}}, - { 0x093, {{1,3}, {1,3}, {1,6}}}, - { 0x0A3, {{1,3}, {1,6}, {1,6}}}, - { 0x0DA, {{1,4}, {1,4}, {1,8}}}, - { 0x0DC, {{1,4}, {1,4}, {1,8}}}, - { 0x0EC, {{1,4}, {1,8}, {1,8}}}, - { 0x123, {{1,4}, {1,4}, {1,8}}}, - { 0x16C, {{1,4}, {1,8}, {1,8}}}, +static struct sysdev_class timer_sysclass = { + set_kset_name("timer"), }; -struct memclk_data { - unsigned char multiplier; - unsigned char divisor; -}; - -static struct memclk_data st40_memclk_table[8] = { - {1,1}, // 000 - {1,2}, // 001 - {1,3}, // 010 - {2,3}, // 011 - {1,4}, // 100 - {1,6}, // 101 - {1,8}, // 110 - {1,8} // 111 -}; - -static void st40_specific_time_init(unsigned int module_clock, unsigned short frqcr) +static int __init timer_init_sysfs(void) { - unsigned int cpu_clock, master_clock, bus_clock, memory_clock; - struct frqcr_data *d; - int a; - unsigned long memclkcr; - struct memclk_data *e; + int ret = sysdev_class_register(&timer_sysclass); + if (ret != 0) + return ret; - for (a = 0; a < ARRAY_SIZE(st40_frqcr_table); a++) { - d = &st40_frqcr_table[a]; - - if (d->frqcr == (frqcr & 0x1ff)) - break; - } + sys_timer->dev.cls = &timer_sysclass; + return sysdev_register(&sys_timer->dev); +} - if (a == ARRAY_SIZE(st40_frqcr_table)) { - d = st40_frqcr_table; +device_initcall(timer_init_sysfs); - printk("ERROR: Unrecognised FRQCR value (0x%x), " - "using default multipliers\n", frqcr); - } - - memclkcr = ctrl_inl(CLOCKGEN_MEMCLKCR); - e = &st40_memclk_table[memclkcr & MEMCLKCR_RATIO_MASK]; - - printk(KERN_INFO "Clock multipliers: CPU: %d/%d Bus: %d/%d " - "Mem: %d/%d Periph: %d/%d\n", - d->factor[0].multiplier, d->factor[0].divisor, - d->factor[1].multiplier, d->factor[1].divisor, - e->multiplier, e->divisor, - d->factor[2].multiplier, d->factor[2].divisor); - - master_clock = module_clock * d->factor[2].divisor - / d->factor[2].multiplier; - bus_clock = master_clock * d->factor[1].multiplier - / d->factor[1].divisor; - memory_clock = master_clock * e->multiplier - / e->divisor; - cpu_clock = master_clock * d->factor[0].multiplier - / d->factor[0].divisor; - - current_cpu_data.cpu_clock = cpu_clock; - current_cpu_data.master_clock = master_clock; - current_cpu_data.bus_clock = bus_clock; - current_cpu_data.memory_clock = memory_clock; - current_cpu_data.module_clock = module_clock; -} -#endif +void (*board_time_init)(void); void __init time_init(void) { - unsigned int timer_freq = 0; - unsigned int ifc, pfc, bfc; - unsigned long interval; -#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 - unsigned long pvr; - unsigned short frqcr; -#endif - if (board_time_init) board_time_init(); - /* - * If we don't have an RTC (such as with the SH7300), don't attempt to - * probe the timer frequency. Rely on an either hardcoded peripheral - * clock value, or on the sh_pclk command line option. Note that we - * still need to have CONFIG_SH_PCLK_FREQ set in order for things like - * CLOCK_TICK_RATE to be sane. - */ - current_cpu_data.module_clock = sh_pclk_freq; - -#ifdef CONFIG_SH_PCLK_CALC - /* XXX: Switch this over to a more generic test. */ - { - unsigned int freq; - - /* - * If we've specified a peripheral clock frequency, and we have - * an RTC, compare it against the autodetected value. Complain - * if there's a mismatch. - */ - timer_freq = get_timer_frequency(); - freq = timer_freq * 4; - - if (sh_pclk_freq && (sh_pclk_freq/100*99 > freq || sh_pclk_freq/100*101 < freq)) { - printk(KERN_NOTICE "Calculated peripheral clock value " - "%d differs from sh_pclk value %d, fixing..\n", - freq, sh_pclk_freq); - current_cpu_data.module_clock = freq; - } - } -#endif - -#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 - /* XXX: Update ST40 code to use board_time_init() */ - pvr = ctrl_inl(CCN_PVR); - frqcr = ctrl_inw(FRQCR); - printk("time.c ST40 Probe: PVR %08lx, FRQCR %04hx\n", pvr, frqcr); - - if (((pvr >> CCN_PVR_CHIP_SHIFT) & CCN_PVR_CHIP_MASK) == CCN_PVR_CHIP_ST40STB1) - st40_specific_time_init(current_cpu_data.module_clock, frqcr); - else -#endif - get_current_frequency_divisors(&ifc, &bfc, &pfc); + clk_init(); if (rtc_get_time) { rtc_get_time(&xtime); @@ -594,51 +179,12 @@ void __init time_init(void) set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); - if (board_timer_setup) { - board_timer_setup(&irq0); - } else { - setup_irq(TIMER_IRQ, &irq0); - } - /* - * for ST40 chips the current_cpu_data should already be set - * so not having valid pfc/bfc/ifc shouldn't be a problem + * Find the timer to use as the system timer, it will be + * initialized for us. */ - if (!current_cpu_data.master_clock) - current_cpu_data.master_clock = current_cpu_data.module_clock * pfc; - if (!current_cpu_data.bus_clock) - current_cpu_data.bus_clock = current_cpu_data.master_clock / bfc; - if (!current_cpu_data.cpu_clock) - current_cpu_data.cpu_clock = current_cpu_data.master_clock / ifc; - - printk("CPU clock: %d.%02dMHz\n", - (current_cpu_data.cpu_clock / 1000000), - (current_cpu_data.cpu_clock % 1000000)/10000); - printk("Bus clock: %d.%02dMHz\n", - (current_cpu_data.bus_clock / 1000000), - (current_cpu_data.bus_clock % 1000000)/10000); -#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 - printk("Memory clock: %d.%02dMHz\n", - (current_cpu_data.memory_clock / 1000000), - (current_cpu_data.memory_clock % 1000000)/10000); -#endif - printk("Module clock: %d.%02dMHz\n", - (current_cpu_data.module_clock / 1000000), - (current_cpu_data.module_clock % 1000000)/10000); - - interval = (current_cpu_data.module_clock/4 + HZ/2) / HZ; - - printk("Interval = %ld\n", interval); - - /* Start TMU0 */ - ctrl_outb(0, TMU_TSTR); -#if !defined(CONFIG_CPU_SUBTYPE_SH7300) - ctrl_outb(TMU_TOCR_INIT, TMU_TOCR); -#endif - ctrl_outw(TMU0_TCR_INIT, TMU0_TCR); - ctrl_outl(interval, TMU0_TCOR); - ctrl_outl(interval, TMU0_TCNT); - ctrl_outb(TMU_TSTR_INIT, TMU_TSTR); + sys_timer = get_sys_timer(); + printk(KERN_INFO "Using %s for system timer\n", sys_timer->name); #if defined(CONFIG_SH_KGDB) /* diff --git a/include/asm-sh/clock.h b/include/asm-sh/clock.h new file mode 100644 index 00000000000..fdfb75b30f0 --- /dev/null +++ b/include/asm-sh/clock.h @@ -0,0 +1,61 @@ +#ifndef __ASM_SH_CLOCK_H +#define __ASM_SH_CLOCK_H + +#include +#include +#include + +struct clk; + +struct clk_ops { + void (*init)(struct clk *clk); + void (*enable)(struct clk *clk); + void (*disable)(struct clk *clk); + void (*recalc)(struct clk *clk); + int (*set_rate)(struct clk *clk, unsigned long rate); +}; + +struct clk { + struct list_head node; + const char *name; + + struct module *owner; + + struct clk *parent; + struct clk_ops *ops; + + struct kref kref; + + unsigned long rate; + unsigned long flags; +}; + +#define CLK_ALWAYS_ENABLED (1 << 0) +#define CLK_RATE_PROPAGATES (1 << 1) + +/* Should be defined by processor-specific code */ +void arch_init_clk_ops(struct clk_ops **, int type); + +/* arch/sh/kernel/cpu/clock.c */ +int clk_init(void); + +int __clk_enable(struct clk *); +int clk_enable(struct clk *); + +void __clk_disable(struct clk *); +void clk_disable(struct clk *); + +int clk_set_rate(struct clk *, unsigned long rate); +unsigned long clk_get_rate(struct clk *); +void clk_recalc_rate(struct clk *); + +struct clk *clk_get(const char *id); +void clk_put(struct clk *); + +int clk_register(struct clk *); +void clk_unregister(struct clk *); + +int show_clocks(struct seq_file *m); + +#endif /* __ASM_SH_CLOCK_H */ + diff --git a/include/asm-sh/cpu-sh4/freq.h b/include/asm-sh/cpu-sh4/freq.h index 201d94fd214..ef2b9b1ae41 100644 --- a/include/asm-sh/cpu-sh4/freq.h +++ b/include/asm-sh/cpu-sh4/freq.h @@ -12,6 +12,8 @@ #if defined(CONFIG_CPU_SUBTYPE_SH73180) #define FRQCR 0xa4150000 +#elif defined(CONFIG_CPU_SUBTYPE_SH7780) +#define FRQCR 0xffc80000 #else #define FRQCR 0xffc00000 #endif diff --git a/include/asm-sh/freq.h b/include/asm-sh/freq.h index 2c0fde46a0e..39c0e091cf5 100644 --- a/include/asm-sh/freq.h +++ b/include/asm-sh/freq.h @@ -14,16 +14,5 @@ #include -/* arch/sh/kernel/time.c */ -extern void get_current_frequency_divisors(unsigned int *ifc, unsigned int *pfc, unsigned int *bfc); - -extern unsigned int get_ifc_divisor(unsigned int value); -extern unsigned int get_ifc_divisor(unsigned int value); -extern unsigned int get_ifc_divisor(unsigned int value); - -extern unsigned int get_ifc_value(unsigned int divisor); -extern unsigned int get_pfc_value(unsigned int divisor); -extern unsigned int get_bfc_value(unsigned int divisor); - #endif /* __KERNEL__ */ #endif /* __ASM_SH_FREQ_H */ -- GitLab From aa01666df35cd769c0957d4b3ae6ee99d680ab88 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 16 Jan 2006 22:14:18 -0800 Subject: [PATCH 380/465] [PATCH] sh: Simple timer framework This builds on some of the clock framework code to support a simple system timer interface. Signed-off-by: Paul Mundt Cc: john stultz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/sh/kernel/timers/Makefile | 8 ++ arch/sh/kernel/timers/timer-tmu.c | 229 ++++++++++++++++++++++++++++++ arch/sh/kernel/timers/timer.c | 50 +++++++ include/asm-sh/timer.h | 42 ++++++ 4 files changed, 329 insertions(+) create mode 100644 arch/sh/kernel/timers/Makefile create mode 100644 arch/sh/kernel/timers/timer-tmu.c create mode 100644 arch/sh/kernel/timers/timer.c create mode 100644 include/asm-sh/timer.h diff --git a/arch/sh/kernel/timers/Makefile b/arch/sh/kernel/timers/Makefile new file mode 100644 index 00000000000..151a6a304ce --- /dev/null +++ b/arch/sh/kernel/timers/Makefile @@ -0,0 +1,8 @@ +# +# Makefile for the various Linux/SuperH timers +# + +obj-y := timer.o + +obj-$(CONFIG_SH_TMU) += timer-tmu.o + diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c new file mode 100644 index 00000000000..96a64cb1310 --- /dev/null +++ b/arch/sh/kernel/timers/timer-tmu.c @@ -0,0 +1,229 @@ +/* + * arch/sh/kernel/timers/timer-tmu.c - TMU Timer Support + * + * Copyright (C) 2005 Paul Mundt + * + * TMU handling code hacked out of arch/sh/kernel/time.c + * + * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka + * Copyright (C) 2000 Philipp Rumpf + * Copyright (C) 2002, 2003, 2004 Paul Mundt + * Copyright (C) 2002 M. R. Brown + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TMU_TOCR_INIT 0x00 +#define TMU0_TCR_INIT 0x0020 +#define TMU_TSTR_INIT 1 + +#define TMU0_TCR_CALIB 0x0000 + +static DEFINE_SPINLOCK(tmu0_lock); + +static unsigned long tmu_timer_get_offset(void) +{ + int count; + unsigned long flags; + + static int count_p = 0x7fffffff; /* for the first call after boot */ + static unsigned long jiffies_p = 0; + + /* + * cache volatile jiffies temporarily; we have IRQs turned off. + */ + unsigned long jiffies_t; + + spin_lock_irqsave(&tmu0_lock, flags); + /* timer count may underflow right here */ + count = ctrl_inl(TMU0_TCNT); /* read the latched count */ + + jiffies_t = jiffies; + + /* + * avoiding timer inconsistencies (they are rare, but they happen)... + * there is one kind of problem that must be avoided here: + * 1. the timer counter underflows + */ + + if (jiffies_t == jiffies_p) { + if (count > count_p) { + /* the nutcase */ + if (ctrl_inw(TMU0_TCR) & 0x100) { /* Check UNF bit */ + count -= LATCH; + } else { + printk("%s (): hardware timer problem?\n", + __FUNCTION__); + } + } + } else + jiffies_p = jiffies_t; + + count_p = count; + spin_unlock_irqrestore(&tmu0_lock, flags); + + count = ((LATCH-1) - count) * TICK_SIZE; + count = (count + LATCH/2) / LATCH; + + return count; +} + +static irqreturn_t tmu_timer_interrupt(int irq, void *dev_id, + struct pt_regs *regs) +{ + unsigned long timer_status; + + /* Clear UNF bit */ + timer_status = ctrl_inw(TMU0_TCR); + timer_status &= ~0x100; + ctrl_outw(timer_status, TMU0_TCR); + + /* + * Here we are in the timer irq handler. We just have irqs locally + * disabled but we don't know if the timer_bh is running on the other + * CPU. We need to avoid to SMP race with it. NOTE: we don' t need + * the irq version of write_lock because as just said we have irq + * locally disabled. -arca + */ + write_seqlock(&xtime_lock); + handle_timer_tick(regs); + write_sequnlock(&xtime_lock); + + return IRQ_HANDLED; +} + +static struct irqaction tmu_irq = { + .name = "timer", + .handler = tmu_timer_interrupt, + .flags = SA_INTERRUPT, + .mask = CPU_MASK_NONE, +}; + +/* + * Hah! We'll see if this works (switching from usecs to nsecs). + */ +static unsigned long tmu_timer_get_frequency(void) +{ + u32 freq; + struct timespec ts1, ts2; + unsigned long diff_nsec; + unsigned long factor; + + /* Setup the timer: We don't want to generate interrupts, just + * have it count down at its natural rate. + */ + ctrl_outb(0, TMU_TSTR); +#if !defined(CONFIG_CPU_SUBTYPE_SH7300) && !defined(CONFIG_CPU_SUBTYPE_SH7760) + ctrl_outb(TMU_TOCR_INIT, TMU_TOCR); +#endif + ctrl_outw(TMU0_TCR_CALIB, TMU0_TCR); + ctrl_outl(0xffffffff, TMU0_TCOR); + ctrl_outl(0xffffffff, TMU0_TCNT); + + rtc_get_time(&ts2); + + do { + rtc_get_time(&ts1); + } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec); + + /* actually start the timer */ + ctrl_outb(TMU_TSTR_INIT, TMU_TSTR); + + do { + rtc_get_time(&ts2); + } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec); + + freq = 0xffffffff - ctrl_inl(TMU0_TCNT); + if (ts2.tv_nsec < ts1.tv_nsec) { + ts2.tv_nsec += 1000000000; + ts2.tv_sec--; + } + + diff_nsec = (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec); + + /* this should work well if the RTC has a precision of n Hz, where + * n is an integer. I don't think we have to worry about the other + * cases. */ + factor = (1000000000 + diff_nsec/2) / diff_nsec; + + if (factor * diff_nsec > 1100000000 || + factor * diff_nsec < 900000000) + panic("weird RTC (diff_nsec %ld)", diff_nsec); + + return freq * factor; +} + +static void tmu_clk_init(struct clk *clk) +{ + u8 divisor = TMU0_TCR_INIT & 0x7; + ctrl_outw(TMU0_TCR_INIT, TMU0_TCR); + clk->rate = clk->parent->rate / (4 << (divisor << 1)); +} + +static void tmu_clk_recalc(struct clk *clk) +{ + u8 divisor = ctrl_inw(TMU0_TCR) & 0x7; + clk->rate = clk->parent->rate / (4 << (divisor << 1)); +} + +static struct clk_ops tmu_clk_ops = { + .init = tmu_clk_init, + .recalc = tmu_clk_recalc, +}; + +static struct clk tmu0_clk = { + .name = "tmu0_clk", + .ops = &tmu_clk_ops, +}; + +static int tmu_timer_init(void) +{ + unsigned long interval; + + setup_irq(TIMER_IRQ, &tmu_irq); + + tmu0_clk.parent = clk_get("module_clk"); + + /* Start TMU0 */ + ctrl_outb(0, TMU_TSTR); +#if !defined(CONFIG_CPU_SUBTYPE_SH7300) && !defined(CONFIG_CPU_SUBTYPE_SH7760) + ctrl_outb(TMU_TOCR_INIT, TMU_TOCR); +#endif + + clk_register(&tmu0_clk); + clk_enable(&tmu0_clk); + + interval = (clk_get_rate(&tmu0_clk) + HZ / 2) / HZ; + printk(KERN_INFO "Interval = %ld\n", interval); + + ctrl_outl(interval, TMU0_TCOR); + ctrl_outl(interval, TMU0_TCNT); + + ctrl_outb(TMU_TSTR_INIT, TMU_TSTR); + + return 0; +} + +struct sys_timer_ops tmu_timer_ops = { + .init = tmu_timer_init, + .get_frequency = tmu_timer_get_frequency, + .get_offset = tmu_timer_get_offset, +}; + +struct sys_timer tmu_timer = { + .name = "tmu", + .ops = &tmu_timer_ops, +}; + diff --git a/arch/sh/kernel/timers/timer.c b/arch/sh/kernel/timers/timer.c new file mode 100644 index 00000000000..dc1f631053a --- /dev/null +++ b/arch/sh/kernel/timers/timer.c @@ -0,0 +1,50 @@ +/* + * arch/sh/kernel/timers/timer.c - Common timer code + * + * Copyright (C) 2005 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include + +static struct sys_timer *sys_timers[] __initdata = { +#ifdef CONFIG_SH_TMU + &tmu_timer, +#endif + NULL, +}; + +static char timer_override[10] __initdata; +static int __init timer_setup(char *str) +{ + if (str) + strlcpy(timer_override, str, sizeof(timer_override)); + return 1; +} +__setup("timer=", timer_setup); + +struct sys_timer *get_sys_timer(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(sys_timers); i++) { + struct sys_timer *t = sys_timers[i]; + + if (unlikely(!t)) + break; + if (unlikely(timer_override[0])) + if ((strcmp(timer_override, t->name) != 0)) + continue; + if (likely(t->ops->init() == 0)) + return t; + } + + return NULL; +} + diff --git a/include/asm-sh/timer.h b/include/asm-sh/timer.h new file mode 100644 index 00000000000..dd6579c0b04 --- /dev/null +++ b/include/asm-sh/timer.h @@ -0,0 +1,42 @@ +#ifndef __ASM_SH_TIMER_H +#define __ASM_SH_TIMER_H + +#include +#include + +struct sys_timer_ops { + int (*init)(void); + unsigned long (*get_offset)(void); + unsigned long (*get_frequency)(void); +}; + +struct sys_timer { + const char *name; + + struct sys_device dev; + struct sys_timer_ops *ops; +}; + +#define TICK_SIZE (tick_nsec / 1000) + +extern struct sys_timer tmu_timer; +extern struct sys_timer *sys_timer; + +static inline unsigned long get_timer_offset(void) +{ + return sys_timer->ops->get_offset(); +} + +static inline unsigned long get_timer_frequency(void) +{ + return sys_timer->ops->get_frequency(); +} + +/* arch/sh/kernel/timers/timer.c */ +struct sys_timer *get_sys_timer(void); + +/* arch/sh/kernel/time.c */ +void handle_timer_tick(struct pt_regs *); + +#endif /* __ASM_SH_TIMER_H */ + -- GitLab From cad8244840d1a148f638925758afd1cdf81fc839 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 16 Jan 2006 22:14:19 -0800 Subject: [PATCH 381/465] [PATCH] sh: Move CPU subtype configuration to its own Kconfig Currently the CPU subtype options are cluttering up arch/sh/Kconfig somewhat. Given that, this moves all of that in to its own arch/sh/mm/Kconfig. Things like cache configuration are also moved to this new location. This also adds support for strict CPU tuning on newer cores, which requires the addition of as-option. Signed-off-by: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Makefile | 7 + arch/sh/Kconfig | 537 ++++++++++++++++-------------------------- arch/sh/Kconfig.debug | 2 +- arch/sh/Makefile | 60 +++-- arch/sh/mm/Kconfig | 233 ++++++++++++++++++ 5 files changed, 489 insertions(+), 350 deletions(-) create mode 100644 arch/sh/mm/Kconfig diff --git a/Makefile b/Makefile index 34d6176dfcb..c3a727126d2 100644 --- a/Makefile +++ b/Makefile @@ -263,6 +263,13 @@ export quiet Q KBUILD_VERBOSE # cc support functions to be used (only) in arch/$(ARCH)/Makefile # See documentation in Documentation/kbuild/makefiles.txt +# as-option +# Usage: cflags-y += $(call as-option, -Wa$(comma)-isa=foo,) + +as-option = $(shell if $(CC) $(CFLAGS) $(1) -Wa,-Z -c -o /dev/null \ + -xassembler /dev/null > /dev/null 2>&1; then echo "$(1)"; \ + else echo "$(2)"; fi ;) + # cc-option # Usage: cflags-y += $(call cc-option, -march=winchip-c6, -march=i586) diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 8cf6d437a63..01bc7d589af 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -33,9 +33,11 @@ config GENERIC_CALIBRATE_DELAY bool default y +config GENERIC_IOMAP + bool + config ARCH_MAY_HAVE_PC_FDC bool - default y source "init/Kconfig" @@ -53,24 +55,28 @@ config SH_SOLUTION_ENGINE config SH_7751_SOLUTION_ENGINE bool "SolutionEngine7751" + select CPU_SUBTYPE_SH7751 help Select 7751 SolutionEngine if configuring for a Hitachi SH7751 evaluation board. config SH_7300_SOLUTION_ENGINE bool "SolutionEngine7300" + select CPU_SUBTYPE_SH7300 help Select 7300 SolutionEngine if configuring for a Hitachi SH7300(SH-Mobile V) evaluation board. config SH_73180_SOLUTION_ENGINE bool "SolutionEngine73180" + select CPU_SUBTYPE_SH73180 help Select 73180 SolutionEngine if configuring for a Hitachi SH73180(SH-Mobile 3) evaluation board. config SH_7751_SYSTEMH bool "SystemH7751R" + select CPU_SUBTYPE_SH7751R help Select SystemH if you are configuring for a Renesas SystemH 7751R evaluation board. @@ -81,27 +87,13 @@ config SH_STB1_HARP config SH_STB1_OVERDRIVE bool "STB1_Overdrive" -config SH_HP620 - bool "HP620" +config SH_HP6XX + bool "HP6XX" help - Select HP620 if configuring for a HP jornada HP620. + Select HP6XX if configuring for a HP jornada HP6xx. More information (hardware only) at . -config SH_HP680 - bool "HP680" - help - Select HP680 if configuring for a HP Jornada HP680. - More information (hardware only) at - . - -config SH_HP690 - bool "HP690" - help - Select HP690 if configuring for a HP Jornada HP690. - More information (hardware only) - at . - config SH_CQREEK bool "CqREEK" help @@ -123,11 +115,13 @@ config SH_EC3104 config SH_SATURN bool "Saturn" + select CPU_SUBTYPE_SH7604 help Select Saturn if configuring for a SEGA Saturn. config SH_DREAMCAST bool "Dreamcast" + select CPU_SUBTYPE_SH7091 help Select Dreamcast if configuring for a SEGA Dreamcast. More information at @@ -142,6 +136,7 @@ config SH_BIGSUR config SH_SH2000 bool "SH2000" + select CPU_SUBTYPE_SH7709 help SH-2000 is a single-board computer based around SH7709A chip intended for embedded applications. @@ -153,20 +148,22 @@ config SH_ADX bool "ADX" config SH_MPC1211 - bool "MPC1211" + bool "Interface MPC1211" + help + CTP/PCI-SH02 is a CPU module computer that is produced + by Interface Corporation. + More information at config SH_SH03 - bool "SH03" + bool "Interface CTP/PCI-SH03" help - CTP/PCI-SH03 is a CPU module computer that produced + CTP/PCI-SH03 is a CPU module computer that is produced by Interface Corporation. - It is compact and excellent in durability. - It will play an active part in your factory or laboratory - as a FA computer. More information at config SH_SECUREEDGE5410 bool "SecureEdge5410" + select CPU_SUBTYPE_SH7751R help Select SecureEdge5410 if configuring for a SnapGear SH board. This includes both the OEM SecureEdge products as well as the @@ -174,25 +171,49 @@ config SH_SECUREEDGE5410 config SH_HS7751RVOIP bool "HS7751RVOIP" + select CPU_SUBTYPE_SH7751R help Select HS7751RVOIP if configuring for a Renesas Technology Sales VoIP board. config SH_RTS7751R2D bool "RTS7751R2D" + select CPU_SUBTYPE_SH7751R help Select RTS7751R2D if configuring for a Renesas Technology Sales SH-Graphics board. +config SH_R7780RP + bool "R7780RP-1" + select CPU_SUBTYPE_SH7780 + help + Select R7780RP-1 if configuring for a Renesas Solutions + HIGHLANDER board. + config SH_EDOSK7705 bool "EDOSK7705" + select CPU_SUBTYPE_SH7705 config SH_SH4202_MICRODEV bool "SH4-202 MicroDev" + select CPU_SUBTYPE_SH4_202 help Select SH4-202 MicroDev if configuring for a SuperH MicroDev board with an SH4-202 CPU. +config SH_LANDISK + bool "LANDISK" + select CPU_SUBTYPE_SH7751R + help + I-O DATA DEVICE, INC. "LANDISK Series" support. + +config SH_TITAN + bool "TITAN" + select CPU_SUBTYPE_SH7751R + help + Select Titan if you are configuring for a Nimble Microsystems + NetEngine NP51R. + config SH_UNKNOWN bool "BareCPU" help @@ -207,168 +228,27 @@ config SH_UNKNOWN endchoice -choice - prompt "Processor family" - default CPU_SH4 - help - This option determines the CPU family to compile for. Supported - targets are SH-2, SH-3, and SH-4. These options are independent of - CPU functionality. As such, SH-DSP users will still want to select - their respective processor family in addition to the DSP support - option. - -config CPU_SH2 - bool "SH-2" - select SH_WRITETHROUGH - -config CPU_SH3 - bool "SH-3" - -config CPU_SH4 - bool "SH-4" - -endchoice - -choice - prompt "Processor subtype" - -config CPU_SUBTYPE_SH7604 - bool "SH7604" - depends on CPU_SH2 - help - Select SH7604 if you have SH7604 - -config CPU_SUBTYPE_SH7300 - bool "SH7300" - depends on CPU_SH3 - -config CPU_SUBTYPE_SH7705 - bool "SH7705" - depends on CPU_SH3 - -config CPU_SUBTYPE_SH7707 - bool "SH7707" - depends on CPU_SH3 - help - Select SH7707 if you have a 60 Mhz SH-3 HD6417707 CPU. - -config CPU_SUBTYPE_SH7708 - bool "SH7708" - depends on CPU_SH3 - help - Select SH7708 if you have a 60 Mhz SH-3 HD6417708S or - if you have a 100 Mhz SH-3 HD6417708R CPU. - -config CPU_SUBTYPE_SH7709 - bool "SH7709" - depends on CPU_SH3 - help - Select SH7709 if you have a 80 Mhz SH-3 HD6417709 CPU. - -config CPU_SUBTYPE_SH7750 - bool "SH7750" - depends on CPU_SH4 - help - Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU. - -config CPU_SUBTYPE_SH7751 - bool "SH7751/SH7751R" - depends on CPU_SH4 - help - Select SH7751 if you have a 166 Mhz SH-4 HD6417751 CPU, - or if you have a HD6417751R CPU. - -config CPU_SUBTYPE_SH7760 - bool "SH7760" - depends on CPU_SH4 - -config CPU_SUBTYPE_SH73180 - bool "SH73180" - depends on CPU_SH4 - -config CPU_SUBTYPE_ST40STB1 - bool "ST40STB1 / ST40RA" - depends on CPU_SH4 - help - Select ST40STB1 if you have a ST40RA CPU. - This was previously called the ST40STB1, hence the option name. - -config CPU_SUBTYPE_ST40GX1 - bool "ST40GX1" - depends on CPU_SH4 - help - Select ST40GX1 if you have a ST40GX1 CPU. - -config CPU_SUBTYPE_SH4_202 - bool "SH4-202" - depends on CPU_SH4 - -endchoice - -config SH7705_CACHE_32KB - bool "Enable 32KB cache size for SH7705" - depends on CPU_SUBTYPE_SH7705 - default y - -config MMU - bool "Support for memory management hardware" - depends on !CPU_SH2 - default y - help - Early SH processors (such as the SH7604) lack an MMU. In order to - boot on these systems, this option must not be set. - - On other systems (such as the SH-3 and 4) where an MMU exists, - turning this off will boot the kernel on these machines with the - MMU implicitly switched off. - -choice - prompt "HugeTLB page size" - depends on HUGETLB_PAGE && CPU_SH4 && MMU - default HUGETLB_PAGE_SIZE_64K - -config HUGETLB_PAGE_SIZE_64K - bool "64K" - -config HUGETLB_PAGE_SIZE_1MB - bool "1MB" - -endchoice - -config CMDLINE_BOOL - bool "Default bootloader kernel arguments" - -config CMDLINE - string "Initial kernel command string" - depends on CMDLINE_BOOL - default "console=ttySC1,115200" +source "arch/sh/mm/Kconfig" -# Platform-specific memory start and size definitions config MEMORY_START - hex "Physical memory start address" if !MEMORY_SET || MEMORY_OVERRIDE - default "0x08000000" if !MEMORY_SET || MEMORY_OVERRIDE || !MEMORY_OVERRIDE && SH_ADX || SH_MPC1211 || SH_SH03 || SH_SECUREEDGE5410 || SH_SH4202_MICRODEV - default "0x0c000000" if !MEMORY_OVERRIDE && (SH_DREAMCAST || SH_HP600 || SH_BIGSUR || SH_SH2000 || SH_73180_SOLUTION_ENGINE || SH_7300_SOLUTION_ENGINE || SH_7751_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || SH_HS7751RVOIP || SH_RTS7751R2D || SH_EDOSK7705) + hex "Physical memory start address" + default "0x08000000" ---help--- Computers built with Hitachi SuperH processors always map the ROM starting at address zero. But the processor does not specify the range that RAM takes. The physical memory (RAM) start address will be automatically - set to 08000000, unless you selected one of the following - processor types: SolutionEngine, Overdrive, HP620, HP680, HP690, - in which case the start address will be set to 0c000000. + set to 08000000. Other platforms, such as the Solution Engine + boards typically map RAM at 0C000000. - Tweak this only when porting to a new machine which is not already - known by the config system. Changing it from the known correct + Tweak this only when porting to a new machine which does not + already have a defconfig. Changing it from the known correct value on any of the known systems will only lead to disaster. config MEMORY_SIZE - hex "Physical memory size" if !MEMORY_SET || MEMORY_OVERRIDE - default "0x00400000" if !MEMORY_SET || MEMORY_OVERRIDE || !MEMORY_OVERRIDE && SH_ADX || !MEMORY_OVERRIDE && (SH_HP600 || SH_BIGSUR || SH_SH2000) - default "0x01000000" if !MEMORY_OVERRIDE && SH_DREAMCAST || SH_SECUREEDGE5410 || SH_EDOSK7705 - default "0x02000000" if !MEMORY_OVERRIDE && (SH_73180_SOLUTION_ENGINE || SH_SOLUTION_ENGINE) - default "0x04000000" if !MEMORY_OVERRIDE && (SH_7300_SOLUTION_ENGINE || SH_7751_SOLUTION_ENGINE || SH_HS7751RVOIP || SH_RTS7751R2D || SH_SH4202_MICRODEV) - default "0x08000000" if SH_MPC1211 || SH_SH03 + hex "Physical memory size" + default "0x00400000" help This sets the default memory size assumed by your SH kernel. It can be overridden as normal by the 'mem=' argument on the kernel command @@ -376,21 +256,6 @@ config MEMORY_SIZE as 0x00400000 which was the default value before this became configurable. -config MEMORY_SET - bool - depends on !MEMORY_OVERRIDE && (SH_MPC1211 || SH_SH03 || SH_ADX || SH_DREAMCAST || SH_HP600 || SH_BIGSUR || SH_SH2000 || SH_7751_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || SH_SECUREEDGE5410 || SH_HS7751RVOIP || SH_RTS7751R2D || SH_SH4202_MICRODEV || SH_EDOSK7705) - default y - help - This is an option about which you will never be asked a question. - Therefore, I conclude that you do not exist - go away. - - There is a grue here. - -# If none of the above have set memory start/size, ask the user. -config MEMORY_OVERRIDE - bool "Override default load address and memory size" - -# XXX: break these out into the board-specific configs below config CF_ENABLER bool "Compact Flash Enabler support" depends on SH_ADX || SH_SOLUTION_ENGINE || SH_UNKNOWN || SH_CAT68701 || SH_SH03 @@ -434,10 +299,21 @@ config CF_BASE_ADDR default "0xb8000000" if CF_AREA6 default "0xb4000000" if CF_AREA5 +menu "Processor features" + +config CPU_LITTLE_ENDIAN + bool "Little Endian" + help + Some SuperH machines can be configured for either little or big + endian byte order. These modes require different kernels. Say Y if + your machine is little endian, N if it's a big endian machine. + # The SH7750 RTC module is disabled in the Dreamcast config SH_RTC bool - depends on !SH_DREAMCAST && !SH_SATURN && !SH_7300_SOLUTION_ENGINE && !SH_73180_SOLUTION_ENGINE + depends on !SH_DREAMCAST && !SH_SATURN && !SH_7300_SOLUTION_ENGINE && \ + !SH_73180_SOLUTION_ENGINE && !SH_LANDISK && \ + !SH_R7780RP default y help Selecting this option will allow the Linux kernel to emulate @@ -476,104 +352,131 @@ config SH_ADC If unsure, say N. -config SH_HP600 +config SH_STORE_QUEUES + bool "Support for Store Queues" + depends on CPU_SH4 + help + Selecting this option will enable an in-kernel API for manipulating + the store queues integrated in the SH-4 processors. + +config CPU_HAS_INTEVT bool - depends on SH_HP620 || SH_HP680 || SH_HP690 - default y -config CPU_SUBTYPE_ST40 - bool - depends on CPU_SUBTYPE_ST40STB1 || CPU_SUBTYPE_ST40GX1 - default y +config CPU_HAS_PINT_IRQ + bool -source "mm/Kconfig" +config CPU_HAS_INTC2_IRQ + bool -config ZERO_PAGE_OFFSET - hex "Zero page offset" - default "0x00001000" if !(SH_MPC1211 || SH_SH03) - default "0x00004000" if SH_MPC1211 || SH_SH03 +config CPU_HAS_SR_RB + bool "CPU has SR.RB" + depends on CPU_SH3 || CPU_SH4 + default y help - This sets the default offset of zero page. + This will enable the use of SR.RB register bank usage. Processors + that are lacking this bit must have another method in place for + accomplishing what is taken care of by the banked registers. -# XXX: needs to lose subtype for system type -config ST40_LMI_MEMORY - bool "Memory on LMI" - depends on CPU_SUBTYPE_ST40STB1 + See for further + information on SR.RB and register banking in the kernel in general. -config MEMORY_START - hex - depends on CPU_SUBTYPE_ST40STB1 && ST40_LMI_MEMORY - default "0x08000000" +endmenu -config MEMORY_SIZE - hex - depends on CPU_SUBTYPE_ST40STB1 && ST40_LMI_MEMORY - default "0x00400000" +menu "Timer support" -config MEMORY_SET - bool - depends on CPU_SUBTYPE_ST40STB1 && ST40_LMI_MEMORY +config SH_TMU + bool "TMU timer support" default y - -config BOOT_LINK_OFFSET - hex "Link address offset for booting" - default "0x00800000" help - This option allows you to set the link address offset of the zImage. - This can be useful if you are on a board which has a small amount of - memory. + This enables the use of the TMU as the system timer. -config CPU_LITTLE_ENDIAN - bool "Little Endian" - help - Some SuperH machines can be configured for either little or big - endian byte order. These modes require different kernels. Say Y if - your machine is little endian, N if it's a big endian machine. +endmenu -config PREEMPT - bool "Preemptible Kernel (EXPERIMENTAL)" - depends on EXPERIMENTAL +source "arch/sh/boards/renesas/hs7751rvoip/Kconfig" -config UBC_WAKEUP - bool "Wakeup UBC on startup" +source "arch/sh/boards/renesas/rts7751r2d/Kconfig" + +config SH_PCLK_FREQ_BOOL + bool "Set default pclk frequency" + default y if !SH_RTC + default n + +config SH_PCLK_FREQ + int "Peripheral clock frequency (in Hz)" + depends on SH_PCLK_FREQ_BOOL + default "50000000" if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7780 + default "60000000" if CPU_SUBTYPE_SH7751 + default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || CPU_SUBTYPE_SH7760 + default "27000000" if CPU_SUBTYPE_SH73180 + default "66000000" if CPU_SUBTYPE_SH4_202 help - Selecting this option will wakeup the User Break Controller (UBC) on - startup. Although the UBC is left in an awake state when the processor - comes up, some boot loaders misbehave by putting the UBC to sleep in a - power saving state, which causes issues with things like ptrace(). + This option is used to specify the peripheral clock frequency. + This is necessary for determining the reference clock value on + platforms lacking an RTC. - If unsure, say N. +menu "CPU Frequency scaling" + +source "drivers/cpufreq/Kconfig" -config SH_WRITETHROUGH - bool "Use write-through caching" - default y if CPU_SH2 +config SH_CPU_FREQ + tristate "SuperH CPU Frequency driver" + depends on CPU_FREQ + select CPU_FREQ_TABLE help - Selecting this option will configure the caches in write-through - mode, as opposed to the default write-back configuration. + This adds the cpufreq driver for SuperH. At present, only + the SH-4 is supported. - Since there's sill some aliasing issues on SH-4, this option will - unfortunately still require the majority of flushing functions to - be implemented to deal with aliasing. + For details, take a look at . If unsure, say N. -config SH_OCRAM - bool "Operand Cache RAM (OCRAM) support" +endmenu + +source "arch/sh/drivers/dma/Kconfig" + +source "arch/sh/cchips/Kconfig" + +config HEARTBEAT + bool "Heartbeat LED" + depends on SH_MPC1211 || SH_SH03 || SH_CAT68701 || \ + SH_STB1_HARP || SH_STB1_OVERDRIVE || SH_BIGSUR || \ + SH_7751_SOLUTION_ENGINE || SH_7300_SOLUTION_ENGINE || \ + SH_73180_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || \ + SH_RTS7751R2D || SH_SH4202_MICRODEV || SH_LANDISK help - Selecting this option will automatically tear down the number of - sets in the dcache by half, which in turn exposes a memory range. + Use the power-on LED on your machine as a load meter. The exact + behavior is platform-dependent, but normally the flash frequency is + a hyperbolic function of the 5-minute load average. - The addresses for the OC RAM base will vary according to the - processor version. Consult vendor documentation for specifics. +endmenu - If unsure, say N. +config ISA_DMA_API + bool + depends on MPC1211 + default y -config SH_STORE_QUEUES - bool "Support for Store Queues" - depends on CPU_SH4 +menu "Kernel features" + +config KEXEC + bool "kexec system call (EXPERIMENTAL)" + depends on EXPERIMENTAL help - Selecting this option will enable an in-kernel API for manipulating - the store queues integrated in the SH-4 processors. + kexec is a system call that implements the ability to shutdown your + current kernel, and to start another kernel. It is like a reboot + but it is indepedent of the system firmware. And like a reboot + you can start any kernel with it, not just Linux. + + The name comes from the similiarity to the exec system call. + + It is an ongoing process to be certain the hardware in a machine + is properly shutdown, so do not be surprised if this code does not + initially work for you. It may help to enable device hotplugging + support. As of this writing the exact hardware interface is + strongly in flux, so no good recommendation can be made. + +config PREEMPT + bool "Preemptible Kernel (EXPERIMENTAL)" + depends on EXPERIMENTAL config SMP bool "Symmetric multi-processing support" @@ -610,87 +513,58 @@ config NR_CPUS This is purely to save memory - each supported CPU adds approximately eight kilobytes to the kernel image. -config HS7751RVOIP_CODEC - bool "Support VoIP Codec section" - depends on SH_HS7751RVOIP - help - Selecting this option will support CODEC section. - -config RTS7751R2D_REV11 - bool "RTS7751R2D Rev. 1.1 board support" - depends on SH_RTS7751R2D - help - Selecting this option will support version rev. 1.1. - -config SH_PCLK_CALC - bool - default n if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH73180 +config CPU_HAS_SR_RB + bool "CPU has SR.RB" + depends on CPU_SH3 || CPU_SH4 default y help - This option will cause the PCLK value to be probed at run-time. It - will display a notification if the probed value has greater than a - 1% variance of the hardcoded CONFIG_SH_PCLK_FREQ. + This will enable the use of SR.RB register bank usage. Processors + that are lacking this bit must have another method in place for + accomplishing what is taken care of by the banked registers. -config SH_PCLK_FREQ - int "Peripheral clock frequency (in Hz)" - default "50000000" if CPU_SUBTYPE_SH7750 - default "60000000" if CPU_SUBTYPE_SH7751 - default "33333333" if CPU_SUBTYPE_SH7300 - default "27000000" if CPU_SUBTYPE_SH73180 - default "66000000" if CPU_SUBTYPE_SH4_202 - default "1193182" - help - This option is used to specify the peripheral clock frequency. This - option must be set for each processor in order for the kernel to - function reliably. If no sane default exists, we use a default from - the legacy i8254. Any discrepancies will be reported on boot time - with an auto-probed frequency which should be considered the proper - value for your hardware. + See for further + information on SR.RB and register banking in the kernel in general. -menu "CPU Frequency scaling" +endmenu -source "drivers/cpufreq/Kconfig" +menu "Boot options" -config SH_CPU_FREQ - tristate "SuperH CPU Frequency driver" - depends on CPU_FREQ - select CPU_FREQ_TABLE +config ZERO_PAGE_OFFSET + hex "Zero page offset" + default "0x00004000" if SH_MPC1211 || SH_SH03 + default "0x00001000" help - This adds the cpufreq driver for SuperH. At present, only - the SH-4 is supported. - - For details, take a look at . - - If unsure, say N. + This sets the default offset of zero page. -endmenu +config BOOT_LINK_OFFSET + hex "Link address offset for booting" + default "0x00800000" + help + This option allows you to set the link address offset of the zImage. + This can be useful if you are on a board which has a small amount of + memory. -source "arch/sh/drivers/dma/Kconfig" +config UBC_WAKEUP + bool "Wakeup UBC on startup" + help + Selecting this option will wakeup the User Break Controller (UBC) on + startup. Although the UBC is left in an awake state when the processor + comes up, some boot loaders misbehave by putting the UBC to sleep in a + power saving state, which causes issues with things like ptrace(). -source "arch/sh/cchips/Kconfig" + If unsure, say N. -config HEARTBEAT - bool "Heartbeat LED" - depends on SH_MPC1211 || SH_SH03 || SH_CAT68701 || SH_STB1_HARP || SH_STB1_OVERDRIVE || SH_BIGSUR || SH_7751_SOLUTION_ENGINE || SH_7300_SOLUTION_ENGINE || SH_73180_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || SH_RTS7751R2D || SH_SH4202_MICRODEV - help - Use the power-on LED on your machine as a load meter. The exact - behavior is platform-dependent, but normally the flash frequency is - a hyperbolic function of the 5-minute load average. +config CMDLINE_BOOL + bool "Default bootloader kernel arguments" -config RTC_9701JE - tristate "EPSON RTC-9701JE support" - depends on SH_RTS7751R2D - help - Selecting this option will support EPSON RTC-9701JE. +config CMDLINE + string "Initial kernel command string" + depends on CMDLINE_BOOL + default "console=ttySC1,115200" endmenu -config ISA_DMA_API - bool - depends on MPC1211 - default y - -menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)" +menu "Bus options" # Even on SuperH devices which don't have an ISA bus, # this variable helps the PCMCIA modules handle @@ -701,7 +575,7 @@ menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)" # PCMCIA outright. -- PFM. config ISA bool - default y if PCMCIA || SMC91X + default y if PCMCIA help Find out whether you have ISA slots on your motherboard. ISA is the name of a bus system, i.e. the way the CPU talks to the other stuff @@ -735,10 +609,9 @@ config MCA config SBUS bool -config MAPLE - tristate "Maple Bus support" - depends on SH_DREAMCAST - default y +config SUPERHYWAY + tristate "SuperHyway Bus support" + depends on CPU_SUBTYPE_SH4_202 source "arch/sh/drivers/pci/Kconfig" diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug index 3fab181da36..8fb31ab2c02 100644 --- a/arch/sh/Kconfig.debug +++ b/arch/sh/Kconfig.debug @@ -17,7 +17,7 @@ config SH_STANDARD_BIOS config EARLY_SCIF_CONSOLE bool "Use early SCIF console" - depends on CPU_SH4 + depends on CPU_SH4 || CPU_SH2A && !SH_STANDARD_BIOS config EARLY_PRINTK bool "Early printk support" diff --git a/arch/sh/Makefile b/arch/sh/Makefile index 67192d6b00d..08c9515c480 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -17,10 +17,30 @@ cflags-y := -mb cflags-$(CONFIG_CPU_LITTLE_ENDIAN) := -ml +isa-y := any +isa-$(CONFIG_CPU_SH2) := sh2 +isa-$(CONFIG_CPU_SH3) := sh3 +isa-$(CONFIG_CPU_SH4) := sh4 +isa-$(CONFIG_CPU_SH4A) := sh4a +isa-$(CONFIG_CPU_SH2A) := sh2a + +isa-$(CONFIG_SH_DSP) := $(isa-y)-dsp + +ifndef CONFIG_MMU +isa-y := $(isa-y)-nommu +endif + +ifndef CONFIG_SH_FPU +isa-y := $(isa-y)-nofpu +endif + +cflags-y += $(call as-option,-Wa$(comma)-isa=$(isa-y),) + cflags-$(CONFIG_CPU_SH2) += -m2 cflags-$(CONFIG_CPU_SH3) += -m3 cflags-$(CONFIG_CPU_SH4) += -m4 \ $(call cc-option,-mno-implicit-fp,-m4-nofpu) +cflags-$(CONFIG_CPU_SH4A) += $(call cc-option,-m4a-nofpu,) cflags-$(CONFIG_SH_DSP) += -Wa,-dsp cflags-$(CONFIG_SH_KGDB) += -g @@ -67,9 +87,7 @@ machdir-$(CONFIG_SH_7300_SOLUTION_ENGINE) := se/7300 machdir-$(CONFIG_SH_73180_SOLUTION_ENGINE) := se/73180 machdir-$(CONFIG_SH_STB1_HARP) := harp machdir-$(CONFIG_SH_STB1_OVERDRIVE) := overdrive -machdir-$(CONFIG_SH_HP620) := hp6xx/hp620 -machdir-$(CONFIG_SH_HP680) := hp6xx/hp680 -machdir-$(CONFIG_SH_HP690) := hp6xx/hp690 +machdir-$(CONFIG_SH_HP6XX) := hp6xx machdir-$(CONFIG_SH_CQREEK) := cqreek machdir-$(CONFIG_SH_DMIDA) := dmida machdir-$(CONFIG_SH_EC3104) := ec3104 @@ -119,31 +137,39 @@ boot := arch/sh/boot CPPFLAGS_vmlinux.lds := -traditional +ifneq ($(KBUILD_SRC),) +incdir-prefix := $(srctree)/include/asm-sh/ +else +incdir-prefix := +endif + # Update machine arch and proc symlinks if something which affects # them changed. We use .arch and .mach to indicate when they were # updated last, otherwise make uses the target directory mtime. include/asm-sh/.cpu: $(wildcard include/config/cpu/*.h) include/config/MARKER @echo ' SYMLINK include/asm-sh/cpu -> include/asm-sh/$(cpuincdir-y)' -ifneq ($(KBUILD_SRC),) - $(Q)mkdir -p include/asm-sh - $(Q)ln -fsn $(srctree)/include/asm-sh/$(cpuincdir-y) include/asm-sh/cpu -else - $(Q)ln -fsn $(cpuincdir-y) include/asm-sh/cpu -endif + $(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi + $(Q)ln -fsn $(incdir-prefix)$(cpuincdir-y) include/asm-sh/cpu @touch $@ +# Most boards have their own mach directories. For the ones that +# don't, just reference the parent directory so the semantics are +# kept roughly the same. + include/asm-sh/.mach: $(wildcard include/config/sh/*.h) include/config/MARKER - @echo ' SYMLINK include/asm-sh/mach -> include/asm-sh/$(incdir-y)' -ifneq ($(KBUILD_SRC),) - $(Q)mkdir -p include/asm-sh - $(Q)ln -fsn $(srctree)/include/asm-sh/$(incdir-y) include/asm-sh/mach -else - $(Q)ln -fsn $(incdir-y) include/asm-sh/mach -endif + @echo -n ' SYMLINK include/asm-sh/mach -> ' + $(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi + $(Q)if [ -d $(incdir-prefix)$(incdir-y) ]; then \ + echo -e 'include/asm-sh/$(incdir-y)'; \ + ln -fsn $(incdir-prefix)$(incdir-y) \ + include/asm-sh/mach; \ + else \ + echo -e 'include/asm-sh'; \ + ln -fsn $(incdir-prefix) include/asm-sh/mach; \ + fi @touch $@ - archprepare: maketools include/asm-sh/.cpu include/asm-sh/.mach .PHONY: maketools FORCE diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig new file mode 100644 index 00000000000..fb586b1cf8b --- /dev/null +++ b/arch/sh/mm/Kconfig @@ -0,0 +1,233 @@ +menu "Processor selection" + +# +# Processor families +# +config CPU_SH2 + bool + select SH_WRITETHROUGH + +config CPU_SH3 + bool + select CPU_HAS_INTEVT + select CPU_HAS_SR_RB + +config CPU_SH4 + bool + select CPU_HAS_INTEVT + select CPU_HAS_SR_RB + +config CPU_SH4A + bool + select CPU_SH4 + select CPU_HAS_INTC2_IRQ + +config CPU_SUBTYPE_ST40 + bool + select CPU_SH4 + select CPU_HAS_INTC2_IRQ + +# +# Processor subtypes +# + +comment "SH-2 Processor Support" + +config CPU_SUBTYPE_SH7604 + bool "Support SH7604 processor" + select CPU_SH2 + +comment "SH-3 Processor Support" + +config CPU_SUBTYPE_SH7300 + bool "Support SH7300 processor" + select CPU_SH3 + +config CPU_SUBTYPE_SH7705 + bool "Support SH7705 processor" + select CPU_SH3 + select CPU_HAS_PINT_IRQ + +config CPU_SUBTYPE_SH7707 + bool "Support SH7707 processor" + select CPU_SH3 + select CPU_HAS_PINT_IRQ + help + Select SH7707 if you have a 60 Mhz SH-3 HD6417707 CPU. + +config CPU_SUBTYPE_SH7708 + bool "Support SH7708 processor" + select CPU_SH3 + help + Select SH7708 if you have a 60 Mhz SH-3 HD6417708S or + if you have a 100 Mhz SH-3 HD6417708R CPU. + +config CPU_SUBTYPE_SH7709 + bool "Support SH7709 processor" + select CPU_SH3 + select CPU_HAS_PINT_IRQ + help + Select SH7709 if you have a 80 Mhz SH-3 HD6417709 CPU. + +comment "SH-4 Processor Support" + +config CPU_SUBTYPE_SH7750 + bool "Support SH7750 processor" + select CPU_SH4 + help + Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU. + +config CPU_SUBTYPE_SH7091 + bool "Support SH7091 processor" + select CPU_SH4 + select CPU_SUBTYPE_SH7750 + help + Select SH7091 if you have an SH-4 based Sega device (such as + the Dreamcast, Naomi, and Naomi 2). + +config CPU_SUBTYPE_SH7750R + bool "Support SH7750R processor" + select CPU_SH4 + select CPU_SUBTYPE_SH7750 + +config CPU_SUBTYPE_SH7750S + bool "Support SH7750S processor" + select CPU_SH4 + select CPU_SUBTYPE_SH7750 + +config CPU_SUBTYPE_SH7751 + bool "Support SH7751 processor" + select CPU_SH4 + help + Select SH7751 if you have a 166 Mhz SH-4 HD6417751 CPU, + or if you have a HD6417751R CPU. + +config CPU_SUBTYPE_SH7751R + bool "Support SH7751R processor" + select CPU_SH4 + select CPU_SUBTYPE_SH7751 + +config CPU_SUBTYPE_SH7760 + bool "Support SH7760 processor" + select CPU_SH4 + select CPU_HAS_INTC2_IRQ + +config CPU_SUBTYPE_SH4_202 + bool "Support SH4-202 processor" + select CPU_SH4 + +comment "ST40 Processor Support" + +config CPU_SUBTYPE_ST40STB1 + bool "Support ST40STB1/ST40RA processors" + select CPU_SUBTYPE_ST40 + help + Select ST40STB1 if you have a ST40RA CPU. + This was previously called the ST40STB1, hence the option name. + +config CPU_SUBTYPE_ST40GX1 + bool "Support ST40GX1 processor" + select CPU_SUBTYPE_ST40 + help + Select ST40GX1 if you have a ST40GX1 CPU. + +comment "SH-4A Processor Support" + +config CPU_SUBTYPE_SH73180 + bool "Support SH73180 processor" + select CPU_SH4A + +config CPU_SUBTYPE_SH7770 + bool "Support SH7770 processor" + select CPU_SH4A + +config CPU_SUBTYPE_SH7780 + bool "Support SH7780 processor" + select CPU_SH4A + +endmenu + +menu "Memory management options" + +config MMU + bool "Support for memory management hardware" + depends on !CPU_SH2 + default y + help + Some SH processors (such as SH-2/SH-2A) lack an MMU. In order to + boot on these systems, this option must not be set. + + On other systems (such as the SH-3 and 4) where an MMU exists, + turning this off will boot the kernel on these machines with the + MMU implicitly switched off. + +config 32BIT + bool "Support 32-bit physical addressing through PMB" + depends on CPU_SH4A + default y + help + If you say Y here, physical addressing will be extended to + 32-bits through the SH-4A PMB. If this is not set, legacy + 29-bit physical addressing will be used. + +choice + prompt "HugeTLB page size" + depends on HUGETLB_PAGE && CPU_SH4 && MMU + default HUGETLB_PAGE_SIZE_64K + +config HUGETLB_PAGE_SIZE_64K + bool "64K" + +config HUGETLB_PAGE_SIZE_1MB + bool "1MB" + +endchoice + +source "mm/Kconfig" + +endmenu + +menu "Cache configuration" + +config SH7705_CACHE_32KB + bool "Enable 32KB cache size for SH7705" + depends on CPU_SUBTYPE_SH7705 + default y + +config SH_DIRECT_MAPPED + bool "Use direct-mapped caching" + default n + help + Selecting this option will configure the caches to be direct-mapped, + even if the cache supports a 2 or 4-way mode. This is useful primarily + for debugging on platforms with 2 and 4-way caches (SH7750R/SH7751R, + SH4-202, SH4-501, etc.) + + Turn this option off for platforms that do not have a direct-mapped + cache, and you have no need to run the caches in such a configuration. + +config SH_WRITETHROUGH + bool "Use write-through caching" + default y if CPU_SH2 + help + Selecting this option will configure the caches in write-through + mode, as opposed to the default write-back configuration. + + Since there's sill some aliasing issues on SH-4, this option will + unfortunately still require the majority of flushing functions to + be implemented to deal with aliasing. + + If unsure, say N. + +config SH_OCRAM + bool "Operand Cache RAM (OCRAM) support" + help + Selecting this option will automatically tear down the number of + sets in the dcache by half, which in turn exposes a memory range. + + The addresses for the OC RAM base will vary according to the + processor version. Consult vendor documentation for specifics. + + If unsure, say N. + +endmenu -- GitLab From 0e6e1db4ac7acfe3e38bbef9eba59233ba7f6b9a Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Mon, 16 Jan 2006 22:14:20 -0800 Subject: [PATCH 382/465] [PATCH] partitions: Read Rio Karma partition table The Rio Karma portable MP3 player has its own proprietary partition table. The partition layout is similar to a DOS boot sector but it begins at a different offset and uses a different magic number (0xAB56 instead of 0xAA55). Add support for it to enable mounting the device. Signed-off-by: Bob Copeland Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/partitions/Kconfig | 7 ++++++ fs/partitions/Makefile | 1 + fs/partitions/check.c | 4 +++ fs/partitions/karma.c | 57 ++++++++++++++++++++++++++++++++++++++++++ fs/partitions/karma.h | 8 ++++++ 5 files changed, 77 insertions(+) create mode 100644 fs/partitions/karma.c create mode 100644 fs/partitions/karma.h diff --git a/fs/partitions/Kconfig b/fs/partitions/Kconfig index 7490cc9208b..c9a47809928 100644 --- a/fs/partitions/Kconfig +++ b/fs/partitions/Kconfig @@ -222,6 +222,13 @@ config SUN_PARTITION given by the tar program ("man tar" or preferably "info tar"). If you don't know what all this is about, say N. +config KARMA_PARTITION + bool "Karma Partition support" + depends on PARTITION_ADVANCED + help + Say Y here if you would like to mount the Rio Karma MP3 player, as it + uses a proprietary partition table. + config EFI_PARTITION bool "EFI GUID Partition support" depends on PARTITION_ADVANCED diff --git a/fs/partitions/Makefile b/fs/partitions/Makefile index 66d5cc26faf..42c7d3878ed 100644 --- a/fs/partitions/Makefile +++ b/fs/partitions/Makefile @@ -17,3 +17,4 @@ obj-$(CONFIG_SUN_PARTITION) += sun.o obj-$(CONFIG_ULTRIX_PARTITION) += ultrix.o obj-$(CONFIG_IBM_PARTITION) += ibm.o obj-$(CONFIG_EFI_PARTITION) += efi.o +obj-$(CONFIG_KARMA_PARTITION) += karma.o diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 7881ce05dae..f924f459bdb 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -35,6 +35,7 @@ #include "ibm.h" #include "ultrix.h" #include "efi.h" +#include "karma.h" #ifdef CONFIG_BLK_DEV_MD extern void md_autodetect_dev(dev_t dev); @@ -102,6 +103,9 @@ static int (*check_part[])(struct parsed_partitions *, struct block_device *) = #endif #ifdef CONFIG_IBM_PARTITION ibm_partition, +#endif +#ifdef CONFIG_KARMA_PARTITION + karma_partition, #endif NULL }; diff --git a/fs/partitions/karma.c b/fs/partitions/karma.c new file mode 100644 index 00000000000..176d89bcf12 --- /dev/null +++ b/fs/partitions/karma.c @@ -0,0 +1,57 @@ +/* + * fs/partitions/karma.c + * Rio Karma partition info. + * + * Copyright (C) 2006 Bob Copeland (me@bobcopeland.com) + * based on osf.c + */ + +#include "check.h" +#include "karma.h" + +int karma_partition(struct parsed_partitions *state, struct block_device *bdev) +{ + int i; + int slot = 1; + Sector sect; + unsigned char *data; + struct disklabel { + u8 d_reserved[270]; + struct d_partition { + __le32 p_res; + u8 p_fstype; + u8 p_res2[3]; + __le32 p_offset; + __le32 p_size; + } d_partitions[2]; + u8 d_blank[208]; + __le16 d_magic; + } __attribute__((packed)) *label; + struct d_partition *p; + + data = read_dev_sector(bdev, 0, §); + if (!data) + return -1; + + label = (struct disklabel *)data; + if (le16_to_cpu(label->d_magic) != KARMA_LABEL_MAGIC) { + put_dev_sector(sect); + return 0; + } + + p = label->d_partitions; + for (i = 0 ; i < 2; i++, p++) { + if (slot == state->limit) + break; + + if (p->p_fstype == 0x4d && le32_to_cpu(p->p_size)) { + put_partition(state, slot, le32_to_cpu(p->p_offset), + le32_to_cpu(p->p_size)); + } + slot++; + } + printk("\n"); + put_dev_sector(sect); + return 1; +} + diff --git a/fs/partitions/karma.h b/fs/partitions/karma.h new file mode 100644 index 00000000000..ecf7d3f2a3d --- /dev/null +++ b/fs/partitions/karma.h @@ -0,0 +1,8 @@ +/* + * fs/partitions/karma.h + */ + +#define KARMA_LABEL_MAGIC 0xAB56 + +int karma_partition(struct parsed_partitions *state, struct block_device *bdev); + -- GitLab From f87fd4c2a0c4f3baad28057360b36a59591ef751 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 16 Jan 2006 22:14:23 -0800 Subject: [PATCH 383/465] [PATCH] add /sys/fs This patch adds an empty /sys/fs, which filesystems can use. Signed-off-by: Miklos Szeredi Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/namespace.c | 5 +++++ include/linux/fs.h | 3 +++ 2 files changed, 8 insertions(+) diff --git a/fs/namespace.c b/fs/namespace.c index 8bc15b362d2..ce97becff46 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -48,6 +48,10 @@ static int hash_mask __read_mostly, hash_bits __read_mostly; static kmem_cache_t *mnt_cache; static struct rw_semaphore namespace_sem; +/* /sys/fs */ +decl_subsys(fs, NULL, NULL); +EXPORT_SYMBOL_GPL(fs_subsys); + static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry) { unsigned long tmp = ((unsigned long)mnt / L1_CACHE_BYTES); @@ -1725,6 +1729,7 @@ void __init mnt_init(unsigned long mempages) i--; } while (i); sysfs_init(); + subsystem_register(&fs_subsys); init_rootfs(); init_mount_tree(); } diff --git a/include/linux/fs.h b/include/linux/fs.h index 552cedfa606..b77f2608eef 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1290,6 +1290,9 @@ extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *, extern int vfs_statfs(struct super_block *, struct kstatfs *); +/* /sys/fs */ +extern struct subsystem fs_subsys; + #define FLOCK_VERIFY_READ 1 #define FLOCK_VERIFY_WRITE 2 -- GitLab From 222f1d69183f10d70a37de5785698fe0aa363c12 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 16 Jan 2006 22:14:25 -0800 Subject: [PATCH 384/465] [PATCH] fuse: fuse_copy_finish() order fix fuse_copy_finish() must be called before request_end(), since the later might sleep, and no sleeping is allowed between fuse_copy_one() and fuse_copy_finish() because of kmap_atomic()/kunmap_atomic() used in them. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/dev.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index e08ab4702d9..9af88953db6 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -773,8 +773,10 @@ static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov, list_del_init(&req->list); if (req->interrupted) { - request_end(fc, req); + spin_unlock(&fuse_lock); fuse_copy_finish(&cs); + spin_lock(&fuse_lock); + request_end(fc, req); return -ENOENT; } req->out.h = oh; -- GitLab From f43b155a5a8a95b06bc0b4474fbb7311c7e9709a Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 16 Jan 2006 22:14:26 -0800 Subject: [PATCH 385/465] [PATCH] fuse: fix request_end() This function used the request object after decrementing its reference count and releasing the lock. This could in theory lead to all sorts of problems. Fix and simplify at the same time. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/dev.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 9af88953db6..de402e4d8bc 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -171,19 +171,17 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) /* * This function is called when a request is finished. Either a reply * has arrived or it was interrupted (and not yet sent) or some error - * occurred during communication with userspace, or the device file was - * closed. It decreases the reference count for the request. In case - * of a background request the reference to the stored objects are - * released. The requester thread is woken up (if still waiting), and - * finally the request is either freed or put on the unused_list + * occurred during communication with userspace, or the device file + * was closed. In case of a background request the reference to the + * stored objects are released. The requester thread is woken up (if + * still waiting), and finally the reference to the request is + * released * * Called with fuse_lock, unlocks it */ static void request_end(struct fuse_conn *fc, struct fuse_req *req) { - int putback; req->finished = 1; - putback = atomic_dec_and_test(&req->count); spin_unlock(&fuse_lock); if (req->background) { down_read(&fc->sbput_sem); @@ -197,13 +195,11 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) else if (req->in.h.opcode == FUSE_RELEASE && req->inode == NULL) { /* Special case for failed iget in CREATE */ u64 nodeid = req->in.h.nodeid; - __fuse_get_request(req); fuse_reset_request(req); fuse_send_forget(fc, req, nodeid, 1); - putback = 0; + return; } - if (putback) - fuse_putback_request(fc, req); + fuse_put_request(fc, req); } /* -- GitLab From b3bebd94bbe4e59dfa23d85b0296a4ce8ebcc6c7 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 16 Jan 2006 22:14:27 -0800 Subject: [PATCH 386/465] [PATCH] fuse: handle error INIT reply Handle the case when the INIT request is answered with an error. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index de402e4d8bc..8244e89a8dd 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -153,7 +153,7 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) int i; struct fuse_init_out *arg = &req->misc.init_out; - if (arg->major != FUSE_KERNEL_VERSION) + if (req->out.h.error || arg->major != FUSE_KERNEL_VERSION) fc->conn_error = 1; else { fc->minor = arg->minor; -- GitLab From 8bfc016d2e2fff71c6843257f0fd0b60876331ed Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 16 Jan 2006 22:14:28 -0800 Subject: [PATCH 387/465] [PATCH] fuse: uninline some functions Inline keyword is unnecessary in most cases. Clean them up. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/dev.c | 21 ++++++++++----------- fs/fuse/dir.c | 12 +++++------- fs/fuse/file.c | 5 ++--- 3 files changed, 17 insertions(+), 21 deletions(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 8244e89a8dd..d76432b757c 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -21,7 +21,7 @@ MODULE_ALIAS_MISCDEV(FUSE_MINOR); static kmem_cache_t *fuse_req_cachep; -static inline struct fuse_conn *fuse_get_conn(struct file *file) +static struct fuse_conn *fuse_get_conn(struct file *file) { struct fuse_conn *fc; spin_lock(&fuse_lock); @@ -32,7 +32,7 @@ static inline struct fuse_conn *fuse_get_conn(struct file *file) return fc; } -static inline void fuse_request_init(struct fuse_req *req) +static void fuse_request_init(struct fuse_req *req) { memset(req, 0, sizeof(*req)); INIT_LIST_HEAD(&req->list); @@ -53,7 +53,7 @@ void fuse_request_free(struct fuse_req *req) kmem_cache_free(fuse_req_cachep, req); } -static inline void block_sigs(sigset_t *oldset) +static void block_sigs(sigset_t *oldset) { sigset_t mask; @@ -61,7 +61,7 @@ static inline void block_sigs(sigset_t *oldset) sigprocmask(SIG_BLOCK, &mask, oldset); } -static inline void restore_sigs(sigset_t *oldset) +static void restore_sigs(sigset_t *oldset) { sigprocmask(SIG_SETMASK, oldset, NULL); } @@ -385,7 +385,7 @@ void fuse_send_init(struct fuse_conn *fc) * anything that could cause a page-fault. If the request was already * interrupted bail out. */ -static inline int lock_request(struct fuse_req *req) +static int lock_request(struct fuse_req *req) { int err = 0; if (req) { @@ -404,7 +404,7 @@ static inline int lock_request(struct fuse_req *req) * requester thread is currently waiting for it to be unlocked, so * wake it up. */ -static inline void unlock_request(struct fuse_req *req) +static void unlock_request(struct fuse_req *req) { if (req) { spin_lock(&fuse_lock); @@ -440,7 +440,7 @@ static void fuse_copy_init(struct fuse_copy_state *cs, int write, } /* Unmap and put previous page of userspace buffer */ -static inline void fuse_copy_finish(struct fuse_copy_state *cs) +static void fuse_copy_finish(struct fuse_copy_state *cs) { if (cs->mapaddr) { kunmap_atomic(cs->mapaddr, KM_USER0); @@ -489,8 +489,7 @@ static int fuse_copy_fill(struct fuse_copy_state *cs) } /* Do as much copy to/from userspace buffer as we can */ -static inline int fuse_copy_do(struct fuse_copy_state *cs, void **val, - unsigned *size) +static int fuse_copy_do(struct fuse_copy_state *cs, void **val, unsigned *size) { unsigned ncpy = min(*size, cs->len); if (val) { @@ -510,8 +509,8 @@ static inline int fuse_copy_do(struct fuse_copy_state *cs, void **val, * Copy a page in the request to/from the userspace buffer. Must be * done atomically */ -static inline int fuse_copy_page(struct fuse_copy_state *cs, struct page *page, - unsigned offset, unsigned count, int zeroing) +static int fuse_copy_page(struct fuse_copy_state *cs, struct page *page, + unsigned offset, unsigned count, int zeroing) { if (page && zeroing && count < PAGE_SIZE) { void *mapaddr = kmap_atomic(page, KM_USER1); diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 417bcee466f..e47fa3a2b4a 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -23,8 +23,7 @@ /* * Calculate the time in jiffies until a dentry/attributes are valid */ -static inline unsigned long time_to_jiffies(unsigned long sec, - unsigned long nsec) +static unsigned long time_to_jiffies(unsigned long sec, unsigned long nsec) { struct timespec ts = {sec, nsec}; return jiffies + timespec_to_jiffies(&ts); @@ -157,7 +156,7 @@ static int dir_alias(struct inode *inode) return 0; } -static inline int invalid_nodeid(u64 nodeid) +static int invalid_nodeid(u64 nodeid) { return !nodeid || nodeid == FUSE_ROOT_ID; } @@ -166,7 +165,7 @@ static struct dentry_operations fuse_dentry_operations = { .d_revalidate = fuse_dentry_revalidate, }; -static inline int valid_mode(int m) +static int valid_mode(int m) { return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) || S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m); @@ -763,9 +762,8 @@ static int parse_dirfile(char *buf, size_t nbytes, struct file *file, return 0; } -static inline size_t fuse_send_readdir(struct fuse_req *req, struct file *file, - struct inode *inode, loff_t pos, - size_t count) +static size_t fuse_send_readdir(struct fuse_req *req, struct file *file, + struct inode *inode, loff_t pos, size_t count) { return fuse_send_read_common(req, file, inode, pos, count, 1); } diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 63d2980df5c..52557664a89 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -267,9 +267,8 @@ size_t fuse_send_read_common(struct fuse_req *req, struct file *file, return req->out.args[0].size; } -static inline size_t fuse_send_read(struct fuse_req *req, struct file *file, - struct inode *inode, loff_t pos, - size_t count) +static size_t fuse_send_read(struct fuse_req *req, struct file *file, + struct inode *inode, loff_t pos, size_t count) { return fuse_send_read_common(req, file, inode, pos, count, 0); } -- GitLab From 6383bdaa2ed2d461d9f4d369dfaa9d610fc972e3 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 16 Jan 2006 22:14:29 -0800 Subject: [PATCH 388/465] [PATCH] fuse: miscellaneous cleanup - remove some unneeded assignments - use kzalloc instead of kmalloc + memset - simplify setting sb->s_fs_info - in fuse_send_init() use fuse_get_request() instead of do_get_request() helper Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/dev.c | 4 ++-- fs/fuse/fuse_i.h | 7 +------ fs/fuse/inode.c | 10 +++------- 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index d76432b757c..4f1ca7b119e 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -361,8 +361,8 @@ void request_send_background(struct fuse_conn *fc, struct fuse_req *req) void fuse_send_init(struct fuse_conn *fc) { /* This is called from fuse_read_super() so there's guaranteed - to be a request available */ - struct fuse_req *req = do_get_request(fc); + to be exactly one request available */ + struct fuse_req *req = fuse_get_request(fc); struct fuse_init_in *arg = &req->misc.init_in; arg->major = FUSE_KERNEL_VERSION; arg->minor = FUSE_KERNEL_MINOR_VERSION; diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 74c8d098a14..27937e8018e 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -280,14 +280,9 @@ struct fuse_conn { struct backing_dev_info bdi; }; -static inline struct fuse_conn **get_fuse_conn_super_p(struct super_block *sb) -{ - return (struct fuse_conn **) &sb->s_fs_info; -} - static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb) { - return *get_fuse_conn_super_p(sb); + return sb->s_fs_info; } static inline struct fuse_conn *get_fuse_conn(struct inode *inode) diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 04c80cc957a..ceee75df7b3 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -200,9 +200,6 @@ static void fuse_put_super(struct super_block *sb) spin_lock(&fuse_lock); fc->mounted = 0; - fc->user_id = 0; - fc->group_id = 0; - fc->flags = 0; /* Flush all readers on this fs */ wake_up_all(&fc->waitq); up_write(&fc->sbput_sem); @@ -379,16 +376,15 @@ static struct fuse_conn *new_conn(void) { struct fuse_conn *fc; - fc = kmalloc(sizeof(*fc), GFP_KERNEL); + fc = kzalloc(sizeof(*fc), GFP_KERNEL); if (fc != NULL) { int i; - memset(fc, 0, sizeof(*fc)); init_waitqueue_head(&fc->waitq); INIT_LIST_HEAD(&fc->pending); INIT_LIST_HEAD(&fc->processing); INIT_LIST_HEAD(&fc->unused_list); INIT_LIST_HEAD(&fc->background); - sema_init(&fc->outstanding_sem, 0); + sema_init(&fc->outstanding_sem, 1); /* One for INIT */ init_rwsem(&fc->sbput_sem); for (i = 0; i < FUSE_MAX_OUTSTANDING; i++) { struct fuse_req *req = fuse_request_alloc(); @@ -420,7 +416,7 @@ static struct fuse_conn *get_conn(struct file *file, struct super_block *sb) fc = ERR_PTR(-EINVAL); } else { file->private_data = fc; - *get_fuse_conn_super_p(sb) = fc; + sb->s_fs_info = fc; fc->mounted = 1; fc->connected = 1; fc->count = 2; -- GitLab From 83cfd4935124b165e942c317dc3e9ebb0a3e6a63 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 16 Jan 2006 22:14:31 -0800 Subject: [PATCH 389/465] [PATCH] fuse: introduce unified request state The state of request was made up of 2 bitfields (->sent and ->finished) and of the fact that the request was on a list or not. Unify this into a single state field. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/dev.c | 14 ++++++++------ fs/fuse/fuse_i.h | 16 +++++++++++----- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 4f1ca7b119e..bc8a3846a4b 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -181,7 +181,7 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) */ static void request_end(struct fuse_conn *fc, struct fuse_req *req) { - req->finished = 1; + req->state = FUSE_REQ_FINISHED; spin_unlock(&fuse_lock); if (req->background) { down_read(&fc->sbput_sem); @@ -250,10 +250,10 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req) spin_unlock(&fuse_lock); block_sigs(&oldset); - wait_event_interruptible(req->waitq, req->finished); + wait_event_interruptible(req->waitq, req->state == FUSE_REQ_FINISHED); restore_sigs(&oldset); spin_lock(&fuse_lock); - if (req->finished) + if (req->state == FUSE_REQ_FINISHED) return; req->out.h.error = -EINTR; @@ -268,10 +268,10 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req) wait_event(req->waitq, !req->locked); spin_lock(&fuse_lock); } - if (!req->sent && !list_empty(&req->list)) { + if (req->state == FUSE_REQ_PENDING) { list_del(&req->list); __fuse_put_request(req); - } else if (!req->finished && req->sent) + } else if (req->state == FUSE_REQ_SENT) background_request(fc, req); } @@ -306,6 +306,7 @@ static void queue_request(struct fuse_conn *fc, struct fuse_req *req) fc->outstanding_debt++; } list_add_tail(&req->list, &fc->pending); + req->state = FUSE_REQ_PENDING; wake_up(&fc->waitq); } @@ -639,6 +640,7 @@ static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov, goto err_unlock; req = list_entry(fc->pending.next, struct fuse_req, list); + req->state = FUSE_REQ_READING; list_del_init(&req->list); in = &req->in; @@ -672,7 +674,7 @@ static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov, if (!req->isreply) request_end(fc, req); else { - req->sent = 1; + req->state = FUSE_REQ_SENT; list_add_tail(&req->list, &fc->processing); spin_unlock(&fuse_lock); } diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 27937e8018e..8cc87ebeed2 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -111,6 +111,15 @@ struct fuse_out { struct fuse_arg args[3]; }; +/** The request state */ +enum fuse_req_state { + FUSE_REQ_INIT = 0, + FUSE_REQ_PENDING, + FUSE_REQ_READING, + FUSE_REQ_SENT, + FUSE_REQ_FINISHED +}; + /** * A request to the client */ @@ -140,11 +149,8 @@ struct fuse_req { /** Data is being copied to/from the request */ unsigned locked:1; - /** Request has been sent to userspace */ - unsigned sent:1; - - /** The request is finished */ - unsigned finished:1; + /** State of the request */ + enum fuse_req_state state; /** The request input */ struct fuse_in in; -- GitLab From d77a1d5b611742c538364f041ff4610d27b14fe7 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 16 Jan 2006 22:14:31 -0800 Subject: [PATCH 390/465] [PATCH] fuse: introduce list for requests under I/O Create a new list for requests in the process of being transfered to/from userspace. This will be needed to be able to abort all requests even those currently under I/O Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/dev.c | 8 ++++---- fs/fuse/fuse_i.h | 7 +++++-- fs/fuse/inode.c | 1 + 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index bc8a3846a4b..609875dbd21 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -181,6 +181,7 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) */ static void request_end(struct fuse_conn *fc, struct fuse_req *req) { + list_del(&req->list); req->state = FUSE_REQ_FINISHED; spin_unlock(&fuse_lock); if (req->background) { @@ -641,7 +642,7 @@ static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov, req = list_entry(fc->pending.next, struct fuse_req, list); req->state = FUSE_REQ_READING; - list_del_init(&req->list); + list_move(&req->list, &fc->io); in = &req->in; reqsize = in->h.len; @@ -675,7 +676,7 @@ static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov, request_end(fc, req); else { req->state = FUSE_REQ_SENT; - list_add_tail(&req->list, &fc->processing); + list_move_tail(&req->list, &fc->processing); spin_unlock(&fuse_lock); } return reqsize; @@ -768,7 +769,6 @@ static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov, if (!req) goto err_unlock; - list_del_init(&req->list); if (req->interrupted) { spin_unlock(&fuse_lock); fuse_copy_finish(&cs); @@ -776,6 +776,7 @@ static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov, request_end(fc, req); return -ENOENT; } + list_move(&req->list, &fc->io); req->out.h = oh; req->locked = 1; cs.req = req; @@ -835,7 +836,6 @@ static void end_requests(struct fuse_conn *fc, struct list_head *head) while (!list_empty(head)) { struct fuse_req *req; req = list_entry(head->next, struct fuse_req, list); - list_del_init(&req->list); req->out.h.error = -ECONNABORTED; request_end(fc, req); spin_lock(&fuse_lock); diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 8cc87ebeed2..5742253164d 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -124,8 +124,8 @@ enum fuse_req_state { * A request to the client */ struct fuse_req { - /** This can be on either unused_list, pending or processing - lists in fuse_conn */ + /** This can be on either unused_list, pending processing or + io lists in fuse_conn */ struct list_head list; /** Entry on the background list */ @@ -223,6 +223,9 @@ struct fuse_conn { /** The list of requests being processed */ struct list_head processing; + /** The list of requests under I/O */ + struct list_head io; + /** Requests put in the background (RELEASE or any other interrupted request) */ struct list_head background; diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index ceee75df7b3..d7aaffe979d 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -382,6 +382,7 @@ static struct fuse_conn *new_conn(void) init_waitqueue_head(&fc->waitq); INIT_LIST_HEAD(&fc->pending); INIT_LIST_HEAD(&fc->processing); + INIT_LIST_HEAD(&fc->io); INIT_LIST_HEAD(&fc->unused_list); INIT_LIST_HEAD(&fc->background); sema_init(&fc->outstanding_sem, 1); /* One for INIT */ -- GitLab From 9ba7cbba100bdaca7316d71d6c6298e61191f8b2 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 16 Jan 2006 22:14:34 -0800 Subject: [PATCH 391/465] [PATCH] fuse: extend semantics of connected flag The ->connected flag for a fuse_conn object previously only indicated whether the device file for this connection is currently open or not. Change it's meaning so that it indicates whether the connection is active or not: now either umount or device release will clear the flag. The separate ->mounted flag is still needed for handling background requests. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/dev.c | 6 +++--- fs/fuse/fuse_i.h | 3 ++- fs/fuse/inode.c | 1 + 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 609875dbd21..5cd43bf917a 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -26,7 +26,7 @@ static struct fuse_conn *fuse_get_conn(struct file *file) struct fuse_conn *fc; spin_lock(&fuse_lock); fc = file->private_data; - if (fc && !fc->mounted) + if (fc && !fc->connected) fc = NULL; spin_unlock(&fuse_lock); return fc; @@ -594,7 +594,7 @@ static void request_wait(struct fuse_conn *fc) DECLARE_WAITQUEUE(wait, current); add_wait_queue_exclusive(&fc->waitq, &wait); - while (fc->mounted && list_empty(&fc->pending)) { + while (fc->connected && list_empty(&fc->pending)) { set_current_state(TASK_INTERRUPTIBLE); if (signal_pending(current)) break; @@ -634,7 +634,7 @@ static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov, goto err_unlock; request_wait(fc); err = -ENODEV; - if (!fc->mounted) + if (!fc->connected) goto err_unlock; err = -ERESTARTSYS; if (list_empty(&fc->pending)) diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 5742253164d..e824a09d315 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -249,7 +249,8 @@ struct fuse_conn { /** Mount is active */ unsigned mounted : 1; - /** Connection established */ + /** Connection established, cleared on umount and device + release */ unsigned connected : 1; /** Connection failed (version mismatch) */ diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index d7aaffe979d..d6a09fdaa94 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -200,6 +200,7 @@ static void fuse_put_super(struct super_block *sb) spin_lock(&fuse_lock); fc->mounted = 0; + fc->connected = 0; /* Flush all readers on this fs */ wake_up_all(&fc->waitq); up_write(&fc->sbput_sem); -- GitLab From f543f253f3aa721a24557d7df8259145bb01b734 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 16 Jan 2006 22:14:35 -0800 Subject: [PATCH 392/465] [PATCH] fuse: make fuse connection a kobject Kobjectify fuse_conn, and make it visible under /sys/fs/fuse/connections. Lacking any natural naming, connections are numbered. This patch doesn't add any attributes, just the infrastructure. Signed-off-by: Miklos Szeredi Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/dev.c | 4 +- fs/fuse/fuse_i.h | 17 ++--- fs/fuse/inode.c | 186 ++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 164 insertions(+), 43 deletions(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 5cd43bf917a..de4a0a0bda8 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -852,9 +852,11 @@ static int fuse_dev_release(struct inode *inode, struct file *file) fc->connected = 0; end_requests(fc, &fc->pending); end_requests(fc, &fc->processing); - fuse_release_conn(fc); } spin_unlock(&fuse_lock); + if (fc) + kobject_put(&fc->kobj); + return 0; } diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index e824a09d315..6ef1e5f5873 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -196,9 +196,6 @@ struct fuse_req { * unmounted. */ struct fuse_conn { - /** Reference count */ - int count; - /** The user id for this mount */ uid_t user_id; @@ -288,6 +285,9 @@ struct fuse_conn { /** Backing dev info */ struct backing_dev_info bdi; + + /** kobject */ + struct kobject kobj; }; static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb) @@ -300,6 +300,11 @@ static inline struct fuse_conn *get_fuse_conn(struct inode *inode) return get_fuse_conn_super(inode->i_sb); } +static inline struct fuse_conn *get_fuse_conn_kobj(struct kobject *obj) +{ + return container_of(obj, struct fuse_conn, kobj); +} + static inline struct fuse_inode *get_fuse_inode(struct inode *inode) { return container_of(inode, struct fuse_inode, inode); @@ -399,12 +404,6 @@ void fuse_init_symlink(struct inode *inode); */ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr); -/** - * Check if the connection can be released, and if yes, then free the - * connection structure - */ -void fuse_release_conn(struct fuse_conn *fc); - /** * Initialize the client device */ diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index d6a09fdaa94..514b700c863 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -24,6 +24,13 @@ MODULE_LICENSE("GPL"); spinlock_t fuse_lock; static kmem_cache_t *fuse_inode_cachep; +static struct subsystem connections_subsys; + +struct fuse_conn_attr { + struct attribute attr; + ssize_t (*show)(struct fuse_conn *, char *); + ssize_t (*store)(struct fuse_conn *, const char *, size_t); +}; #define FUSE_SUPER_MAGIC 0x65735546 @@ -201,11 +208,12 @@ static void fuse_put_super(struct super_block *sb) spin_lock(&fuse_lock); fc->mounted = 0; fc->connected = 0; + spin_unlock(&fuse_lock); + up_write(&fc->sbput_sem); /* Flush all readers on this fs */ wake_up_all(&fc->waitq); - up_write(&fc->sbput_sem); - fuse_release_conn(fc); - spin_unlock(&fuse_lock); + kobject_del(&fc->kobj); + kobject_put(&fc->kobj); } static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr) @@ -354,8 +362,10 @@ static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt) return 0; } -static void free_conn(struct fuse_conn *fc) +static void fuse_conn_release(struct kobject *kobj) { + struct fuse_conn *fc = get_fuse_conn_kobj(kobj); + while (!list_empty(&fc->unused_list)) { struct fuse_req *req; req = list_entry(fc->unused_list.next, struct fuse_req, list); @@ -365,20 +375,12 @@ static void free_conn(struct fuse_conn *fc) kfree(fc); } -/* Must be called with the fuse lock held */ -void fuse_release_conn(struct fuse_conn *fc) -{ - fc->count--; - if (!fc->count) - free_conn(fc); -} - static struct fuse_conn *new_conn(void) { struct fuse_conn *fc; fc = kzalloc(sizeof(*fc), GFP_KERNEL); - if (fc != NULL) { + if (fc) { int i; init_waitqueue_head(&fc->waitq); INIT_LIST_HEAD(&fc->pending); @@ -388,10 +390,12 @@ static struct fuse_conn *new_conn(void) INIT_LIST_HEAD(&fc->background); sema_init(&fc->outstanding_sem, 1); /* One for INIT */ init_rwsem(&fc->sbput_sem); + kobj_set_kset_s(fc, connections_subsys); + kobject_init(&fc->kobj); for (i = 0; i < FUSE_MAX_OUTSTANDING; i++) { struct fuse_req *req = fuse_request_alloc(); if (!req) { - free_conn(fc); + kobject_put(&fc->kobj); return NULL; } list_add(&req->list, &fc->unused_list); @@ -406,25 +410,32 @@ static struct fuse_conn *new_conn(void) static struct fuse_conn *get_conn(struct file *file, struct super_block *sb) { struct fuse_conn *fc; + int err; + err = -EINVAL; if (file->f_op != &fuse_dev_operations) - return ERR_PTR(-EINVAL); + goto out_err; + + err = -ENOMEM; fc = new_conn(); - if (fc == NULL) - return ERR_PTR(-ENOMEM); + if (!fc) + goto out_err; + spin_lock(&fuse_lock); - if (file->private_data) { - free_conn(fc); - fc = ERR_PTR(-EINVAL); - } else { - file->private_data = fc; - sb->s_fs_info = fc; - fc->mounted = 1; - fc->connected = 1; - fc->count = 2; - } + err = -EINVAL; + if (file->private_data) + goto out_unlock; + + kobject_get(&fc->kobj); + file->private_data = fc; spin_unlock(&fuse_lock); return fc; + + out_unlock: + spin_unlock(&fuse_lock); + kobject_put(&fc->kobj); + out_err: + return ERR_PTR(err); } static struct inode *get_root_inode(struct super_block *sb, unsigned mode) @@ -447,12 +458,23 @@ static struct super_operations fuse_super_operations = { .show_options = fuse_show_options, }; +static unsigned long long conn_id(void) +{ + static unsigned long long ctr = 1; + unsigned long long val; + spin_lock(&fuse_lock); + val = ctr++; + spin_unlock(&fuse_lock); + return val; +} + static int fuse_fill_super(struct super_block *sb, void *data, int silent) { struct fuse_conn *fc; struct inode *root; struct fuse_mount_data d; struct file *file; + struct dentry *root_dentry; int err; if (!parse_fuse_opt((char *) data, &d)) @@ -480,23 +502,42 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) if (fc->max_read / PAGE_CACHE_SIZE < fc->bdi.ra_pages) fc->bdi.ra_pages = fc->max_read / PAGE_CACHE_SIZE; + /* Used by get_root_inode() */ + sb->s_fs_info = fc; + err = -ENOMEM; root = get_root_inode(sb, d.rootmode); - if (root == NULL) + if (!root) goto err; - sb->s_root = d_alloc_root(root); - if (!sb->s_root) { + root_dentry = d_alloc_root(root); + if (!root_dentry) { iput(root); goto err; } + + err = kobject_set_name(&fc->kobj, "%llu", conn_id()); + if (err) + goto err_put_root; + + err = kobject_add(&fc->kobj); + if (err) + goto err_put_root; + + sb->s_root = root_dentry; + spin_lock(&fuse_lock); + fc->mounted = 1; + fc->connected = 1; + spin_unlock(&fuse_lock); + fuse_send_init(fc); + return 0; + err_put_root: + dput(root_dentry); err: - spin_lock(&fuse_lock); - fuse_release_conn(fc); - spin_unlock(&fuse_lock); + kobject_put(&fc->kobj); return err; } @@ -514,6 +555,50 @@ static struct file_system_type fuse_fs_type = { .kill_sb = kill_anon_super, }; +static struct attribute *fuse_conn_attrs[] = { + NULL, +}; + +static ssize_t fuse_conn_attr_show(struct kobject *kobj, + struct attribute *attr, + char *page) +{ + struct fuse_conn_attr *fca = + container_of(attr, struct fuse_conn_attr, attr); + + if (fca->show) + return fca->show(get_fuse_conn_kobj(kobj), page); + else + return -EACCES; +} + +static ssize_t fuse_conn_attr_store(struct kobject *kobj, + struct attribute *attr, + const char *page, size_t count) +{ + struct fuse_conn_attr *fca = + container_of(attr, struct fuse_conn_attr, attr); + + if (fca->store) + return fca->store(get_fuse_conn_kobj(kobj), page, count); + else + return -EACCES; +} + +static struct sysfs_ops fuse_conn_sysfs_ops = { + .show = &fuse_conn_attr_show, + .store = &fuse_conn_attr_store, +}; + +static struct kobj_type ktype_fuse_conn = { + .release = fuse_conn_release, + .sysfs_ops = &fuse_conn_sysfs_ops, + .default_attrs = fuse_conn_attrs, +}; + +static decl_subsys(fuse, NULL, NULL); +static decl_subsys(connections, &ktype_fuse_conn, NULL); + static void fuse_inode_init_once(void *foo, kmem_cache_t *cachep, unsigned long flags) { @@ -551,6 +636,34 @@ static void fuse_fs_cleanup(void) kmem_cache_destroy(fuse_inode_cachep); } +static int fuse_sysfs_init(void) +{ + int err; + + kset_set_kset_s(&fuse_subsys, fs_subsys); + err = subsystem_register(&fuse_subsys); + if (err) + goto out_err; + + kset_set_kset_s(&connections_subsys, fuse_subsys); + err = subsystem_register(&connections_subsys); + if (err) + goto out_fuse_unregister; + + return 0; + + out_fuse_unregister: + subsystem_unregister(&fuse_subsys); + out_err: + return err; +} + +static void fuse_sysfs_cleanup(void) +{ + subsystem_unregister(&connections_subsys); + subsystem_unregister(&fuse_subsys); +} + static int __init fuse_init(void) { int res; @@ -567,8 +680,14 @@ static int __init fuse_init(void) if (res) goto err_fs_cleanup; + res = fuse_sysfs_init(); + if (res) + goto err_dev_cleanup; + return 0; + err_dev_cleanup: + fuse_dev_cleanup(); err_fs_cleanup: fuse_fs_cleanup(); err: @@ -579,6 +698,7 @@ static void __exit fuse_exit(void) { printk(KERN_DEBUG "fuse exit\n"); + fuse_sysfs_cleanup(); fuse_fs_cleanup(); fuse_dev_cleanup(); } -- GitLab From 0cd5b88553acf0611474dbaf8e43770eed268060 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 16 Jan 2006 22:14:38 -0800 Subject: [PATCH 393/465] [PATCH] fuse: add number of waiting requests attribute This patch adds the 'waiting' attribute which indicates how many filesystem requests are currently waiting to be completed. A non-zero value without any filesystem activity indicates a hung or deadlocked filesystem. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/dev.c | 12 +++++++++--- fs/fuse/fuse_i.h | 3 +++ fs/fuse/inode.c | 9 +++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index de4a0a0bda8..c72e44b58d0 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -109,18 +109,24 @@ struct fuse_req *fuse_get_request(struct fuse_conn *fc) int intr; sigset_t oldset; + atomic_inc(&fc->num_waiting); block_sigs(&oldset); intr = down_interruptible(&fc->outstanding_sem); restore_sigs(&oldset); - return intr ? NULL : do_get_request(fc); + if (intr) { + atomic_dec(&fc->num_waiting); + return NULL; + } + return do_get_request(fc); } static void fuse_putback_request(struct fuse_conn *fc, struct fuse_req *req) { spin_lock(&fuse_lock); - if (req->preallocated) + if (req->preallocated) { + atomic_dec(&fc->num_waiting); list_add(&req->list, &fc->unused_list); - else + } else fuse_request_free(req); /* If we are in debt decrease that first */ diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 6ef1e5f5873..bcb453f6811 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -280,6 +280,9 @@ struct fuse_conn { /** Is create not implemented by fs? */ unsigned no_create : 1; + /** The number of requests waiting for completion */ + atomic_t num_waiting; + /** Negotiated minor version */ unsigned minor; diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 514b700c863..182235923cd 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -555,7 +555,16 @@ static struct file_system_type fuse_fs_type = { .kill_sb = kill_anon_super, }; +static ssize_t fuse_conn_waiting_show(struct fuse_conn *fc, char *page) +{ + return sprintf(page, "%i\n", atomic_read(&fc->num_waiting)); +} + +static struct fuse_conn_attr fuse_conn_waiting = + __ATTR(waiting, 0400, fuse_conn_waiting_show, NULL); + static struct attribute *fuse_conn_attrs[] = { + &fuse_conn_waiting.attr, NULL, }; -- GitLab From 69a53bf267fa58b89aa659d121dfe38436562a30 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 16 Jan 2006 22:14:41 -0800 Subject: [PATCH 394/465] [PATCH] fuse: add connection aborting Add ability to abort a filesystem connection. With the introduction of asynchronous reads, the ability to interrupt any request is not enough to dissolve deadlocks, since now waiting for the request completion (page unlocked) is independent of the actual request, so in a deadlock all threads will be uninterruptible. The solution is to make it possible to abort all requests, even those currently undergoing I/O to/from userspace. The natural interface for this is 'mount -f mountpoint', but that only works as long as the filesystem is attached. So also add an 'abort' attribute to the sysfs view of the connection. Signed-off-by: Miklos Szeredi Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/dev.c | 71 +++++++++++++++++++++++++++++++++++++++++++++--- fs/fuse/fuse_i.h | 7 +++-- fs/fuse/inode.c | 16 +++++++++++ 3 files changed, 88 insertions(+), 6 deletions(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index c72e44b58d0..60c222517cc 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -260,11 +260,13 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req) wait_event_interruptible(req->waitq, req->state == FUSE_REQ_FINISHED); restore_sigs(&oldset); spin_lock(&fuse_lock); - if (req->state == FUSE_REQ_FINISHED) + if (req->state == FUSE_REQ_FINISHED && !req->interrupted) return; - req->out.h.error = -EINTR; - req->interrupted = 1; + if (!req->interrupted) { + req->out.h.error = -EINTR; + req->interrupted = 1; + } if (req->locked) { /* This is uninterruptible sleep, because data is being copied to/from the buffers of req. During @@ -770,6 +772,10 @@ static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov, goto err_finish; spin_lock(&fuse_lock); + err = -ENOENT; + if (!fc->connected) + goto err_unlock; + req = request_find(fc, oh.unique); err = -EINVAL; if (!req) @@ -836,7 +842,11 @@ static unsigned fuse_dev_poll(struct file *file, poll_table *wait) return mask; } -/* Abort all requests on the given list (pending or processing) */ +/* + * Abort all requests on the given list (pending or processing) + * + * This function releases and reacquires fuse_lock + */ static void end_requests(struct fuse_conn *fc, struct list_head *head) { while (!list_empty(head)) { @@ -848,6 +858,59 @@ static void end_requests(struct fuse_conn *fc, struct list_head *head) } } +/* + * Abort requests under I/O + * + * The requests are set to interrupted and finished, and the request + * waiter is woken up. This will make request_wait_answer() wait + * until the request is unlocked and then return. + */ +static void end_io_requests(struct fuse_conn *fc) +{ + while (!list_empty(&fc->io)) { + struct fuse_req *req; + req = list_entry(fc->io.next, struct fuse_req, list); + req->interrupted = 1; + req->out.h.error = -ECONNABORTED; + req->state = FUSE_REQ_FINISHED; + list_del_init(&req->list); + wake_up(&req->waitq); + } +} + +/* + * Abort all requests. + * + * Emergency exit in case of a malicious or accidental deadlock, or + * just a hung filesystem. + * + * The same effect is usually achievable through killing the + * filesystem daemon and all users of the filesystem. The exception + * is the combination of an asynchronous request and the tricky + * deadlock (see Documentation/filesystems/fuse.txt). + * + * During the aborting, progression of requests from the pending and + * processing lists onto the io list, and progression of new requests + * onto the pending list is prevented by req->connected being false. + * + * Progression of requests under I/O to the processing list is + * prevented by the req->interrupted flag being true for these + * requests. For this reason requests on the io list must be aborted + * first. + */ +void fuse_abort_conn(struct fuse_conn *fc) +{ + spin_lock(&fuse_lock); + if (fc->connected) { + fc->connected = 0; + end_io_requests(fc); + end_requests(fc, &fc->pending); + end_requests(fc, &fc->processing); + wake_up_all(&fc->waitq); + } + spin_unlock(&fuse_lock); +} + static int fuse_dev_release(struct inode *inode, struct file *file) { struct fuse_conn *fc; diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index bcb453f6811..e6381db41df 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -246,8 +246,8 @@ struct fuse_conn { /** Mount is active */ unsigned mounted : 1; - /** Connection established, cleared on umount and device - release */ + /** Connection established, cleared on umount, connection + abort and device release */ unsigned connected : 1; /** Connection failed (version mismatch) */ @@ -463,6 +463,9 @@ void request_send_background(struct fuse_conn *fc, struct fuse_req *req); */ void fuse_release_background(struct fuse_req *req); +/* Abort all requests */ +void fuse_abort_conn(struct fuse_conn *fc); + /** * Get the attributes of a file */ diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 182235923cd..d359d8de22a 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -196,6 +196,11 @@ struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid, return inode; } +static void fuse_umount_begin(struct super_block *sb) +{ + fuse_abort_conn(get_fuse_conn_super(sb)); +} + static void fuse_put_super(struct super_block *sb) { struct fuse_conn *fc = get_fuse_conn_super(sb); @@ -454,6 +459,7 @@ static struct super_operations fuse_super_operations = { .read_inode = fuse_read_inode, .clear_inode = fuse_clear_inode, .put_super = fuse_put_super, + .umount_begin = fuse_umount_begin, .statfs = fuse_statfs, .show_options = fuse_show_options, }; @@ -560,11 +566,21 @@ static ssize_t fuse_conn_waiting_show(struct fuse_conn *fc, char *page) return sprintf(page, "%i\n", atomic_read(&fc->num_waiting)); } +static ssize_t fuse_conn_abort_store(struct fuse_conn *fc, const char *page, + size_t count) +{ + fuse_abort_conn(fc); + return count; +} + static struct fuse_conn_attr fuse_conn_waiting = __ATTR(waiting, 0400, fuse_conn_waiting_show, NULL); +static struct fuse_conn_attr fuse_conn_abort = + __ATTR(abort, 0600, NULL, fuse_conn_abort_store); static struct attribute *fuse_conn_attrs[] = { &fuse_conn_waiting.attr, + &fuse_conn_abort.attr, NULL, }; -- GitLab From 64c6d8ed4c55f0a99b1b81558851da80c8d58244 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 16 Jan 2006 22:14:42 -0800 Subject: [PATCH 395/465] [PATCH] fuse: add asynchronous request support Add possibility for requests to run asynchronously and call an 'end' callback when finished. With this, the special handling of the INIT and RELEASE requests can be cleaned up too. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/dev.c | 42 ++++++++++++++++++++++++++++-------------- fs/fuse/file.c | 10 ++++++++++ fs/fuse/fuse_i.h | 5 +++++ 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 60c222517cc..99325547604 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -172,6 +172,8 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) fuse_putback_request() */ for (i = 1; i < FUSE_MAX_OUTSTANDING; i++) up(&fc->outstanding_sem); + + fuse_put_request(fc, req); } /* @@ -180,13 +182,15 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) * occurred during communication with userspace, or the device file * was closed. In case of a background request the reference to the * stored objects are released. The requester thread is woken up (if - * still waiting), and finally the reference to the request is - * released + * still waiting), the 'end' callback is called if given, else the + * reference to the request is released * * Called with fuse_lock, unlocks it */ static void request_end(struct fuse_conn *fc, struct fuse_req *req) { + void (*end) (struct fuse_conn *, struct fuse_req *) = req->end; + req->end = NULL; list_del(&req->list); req->state = FUSE_REQ_FINISHED; spin_unlock(&fuse_lock); @@ -197,16 +201,10 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) up_read(&fc->sbput_sem); } wake_up(&req->waitq); - if (req->in.h.opcode == FUSE_INIT) - process_init_reply(fc, req); - else if (req->in.h.opcode == FUSE_RELEASE && req->inode == NULL) { - /* Special case for failed iget in CREATE */ - u64 nodeid = req->in.h.nodeid; - fuse_reset_request(req); - fuse_send_forget(fc, req, nodeid, 1); - return; - } - fuse_put_request(fc, req); + if (end) + end(fc, req); + else + fuse_put_request(fc, req); } /* @@ -387,6 +385,7 @@ void fuse_send_init(struct fuse_conn *fc) req->out.argvar = 1; req->out.args[0].size = sizeof(struct fuse_init_out); req->out.args[0].value = &req->misc.init_out; + req->end = process_init_reply; request_send_background(fc, req); } @@ -864,17 +863,32 @@ static void end_requests(struct fuse_conn *fc, struct list_head *head) * The requests are set to interrupted and finished, and the request * waiter is woken up. This will make request_wait_answer() wait * until the request is unlocked and then return. + * + * If the request is asynchronous, then the end function needs to be + * called after waiting for the request to be unlocked (if it was + * locked). */ static void end_io_requests(struct fuse_conn *fc) { while (!list_empty(&fc->io)) { - struct fuse_req *req; - req = list_entry(fc->io.next, struct fuse_req, list); + struct fuse_req *req = + list_entry(fc->io.next, struct fuse_req, list); + void (*end) (struct fuse_conn *, struct fuse_req *) = req->end; + req->interrupted = 1; req->out.h.error = -ECONNABORTED; req->state = FUSE_REQ_FINISHED; list_del_init(&req->list); wake_up(&req->waitq); + if (end) { + req->end = NULL; + /* The end function will consume this reference */ + __fuse_get_request(req); + spin_unlock(&fuse_lock); + wait_event(req->waitq, !req->locked); + end(fc, req); + spin_lock(&fuse_lock); + } } } diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 52557664a89..043d5b36846 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -113,6 +113,14 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir) return err; } +/* Special case for failed iget in CREATE */ +static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req) +{ + u64 nodeid = req->in.h.nodeid; + fuse_reset_request(req); + fuse_send_forget(fc, req, nodeid, 1); +} + void fuse_send_release(struct fuse_conn *fc, struct fuse_file *ff, u64 nodeid, struct inode *inode, int flags, int isdir) { @@ -128,6 +136,8 @@ void fuse_send_release(struct fuse_conn *fc, struct fuse_file *ff, req->in.args[0].size = sizeof(struct fuse_release_in); req->in.args[0].value = inarg; request_send_background(fc, req); + if (!inode) + req->end = fuse_release_end; kfree(ff); } diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index e6381db41df..145098056ca 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -120,6 +120,8 @@ enum fuse_req_state { FUSE_REQ_FINISHED }; +struct fuse_conn; + /** * A request to the client */ @@ -186,6 +188,9 @@ struct fuse_req { /** File used in the request (or NULL) */ struct file *file; + + /** Request completion callback */ + void (*end)(struct fuse_conn *, struct fuse_req *); }; /** -- GitLab From 9b9a04693fa2d9e60933154e4c4aca83c219ef0a Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 16 Jan 2006 22:14:44 -0800 Subject: [PATCH 396/465] [PATCH] fuse: move INIT handling to inode.c Now the INIT requests can be completely handled in inode.c and the fuse_send_init() function need not be global any more. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/dev.c | 45 --------------------------------------------- fs/fuse/fuse_i.h | 5 ----- fs/fuse/inode.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 50 deletions(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 99325547604..4526da8907c 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -154,28 +154,6 @@ void fuse_release_background(struct fuse_req *req) spin_unlock(&fuse_lock); } -static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) -{ - int i; - struct fuse_init_out *arg = &req->misc.init_out; - - if (req->out.h.error || arg->major != FUSE_KERNEL_VERSION) - fc->conn_error = 1; - else { - fc->minor = arg->minor; - fc->max_write = arg->minor < 5 ? 4096 : arg->max_write; - } - - /* After INIT reply is received other requests can go - out. So do (FUSE_MAX_OUTSTANDING - 1) number of - up()s on outstanding_sem. The last up() is done in - fuse_putback_request() */ - for (i = 1; i < FUSE_MAX_OUTSTANDING; i++) - up(&fc->outstanding_sem); - - fuse_put_request(fc, req); -} - /* * This function is called when a request is finished. Either a reply * has arrived or it was interrupted (and not yet sent) or some error @@ -366,29 +344,6 @@ void request_send_background(struct fuse_conn *fc, struct fuse_req *req) request_send_nowait(fc, req); } -void fuse_send_init(struct fuse_conn *fc) -{ - /* This is called from fuse_read_super() so there's guaranteed - to be exactly one request available */ - struct fuse_req *req = fuse_get_request(fc); - struct fuse_init_in *arg = &req->misc.init_in; - arg->major = FUSE_KERNEL_VERSION; - arg->minor = FUSE_KERNEL_MINOR_VERSION; - req->in.h.opcode = FUSE_INIT; - req->in.numargs = 1; - req->in.args[0].size = sizeof(*arg); - req->in.args[0].value = arg; - req->out.numargs = 1; - /* Variable length arguement used for backward compatibility - with interface version < 7.5. Rest of init_out is zeroed - by do_get_request(), so a short reply is not a problem */ - req->out.argvar = 1; - req->out.args[0].size = sizeof(struct fuse_init_out); - req->out.args[0].value = &req->misc.init_out; - req->end = process_init_reply; - request_send_background(fc, req); -} - /* * Lock the request. Up to the next unlock_request() there mustn't be * anything that could cause a page-fault. If the request was already diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 145098056ca..926b41c959d 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -480,8 +480,3 @@ int fuse_do_getattr(struct inode *inode); * Invalidate inode attributes */ void fuse_invalidate_attr(struct inode *inode); - -/** - * Send the INIT message - */ -void fuse_send_init(struct fuse_conn *fc); diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index d359d8de22a..8683e7254d5 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -464,6 +464,51 @@ static struct super_operations fuse_super_operations = { .show_options = fuse_show_options, }; +static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) +{ + int i; + struct fuse_init_out *arg = &req->misc.init_out; + + if (req->out.h.error || arg->major != FUSE_KERNEL_VERSION) + fc->conn_error = 1; + else { + fc->minor = arg->minor; + fc->max_write = arg->minor < 5 ? 4096 : arg->max_write; + } + + /* After INIT reply is received other requests can go + out. So do (FUSE_MAX_OUTSTANDING - 1) number of + up()s on outstanding_sem. The last up() is done in + fuse_putback_request() */ + for (i = 1; i < FUSE_MAX_OUTSTANDING; i++) + up(&fc->outstanding_sem); + + fuse_put_request(fc, req); +} + +static void fuse_send_init(struct fuse_conn *fc) +{ + /* This is called from fuse_read_super() so there's guaranteed + to be exactly one request available */ + struct fuse_req *req = fuse_get_request(fc); + struct fuse_init_in *arg = &req->misc.init_in; + arg->major = FUSE_KERNEL_VERSION; + arg->minor = FUSE_KERNEL_MINOR_VERSION; + req->in.h.opcode = FUSE_INIT; + req->in.numargs = 1; + req->in.args[0].size = sizeof(*arg); + req->in.args[0].value = arg; + req->out.numargs = 1; + /* Variable length arguement used for backward compatibility + with interface version < 7.5. Rest of init_out is zeroed + by do_get_request(), so a short reply is not a problem */ + req->out.argvar = 1; + req->out.args[0].size = sizeof(struct fuse_init_out); + req->out.args[0].value = &req->misc.init_out; + req->end = process_init_reply; + request_send_background(fc, req); +} + static unsigned long long conn_id(void) { static unsigned long long ctr = 1; -- GitLab From 361b1eb55ea84181505c7f0674ca1205da1127ab Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 16 Jan 2006 22:14:45 -0800 Subject: [PATCH 397/465] [PATCH] fuse: READ request initialization Add a separate function for filling in the READ request. This will make it possible to send asynchronous READ requests as well as synchronous ones. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/dir.c | 10 +++------- fs/fuse/file.c | 24 +++++++++++------------- fs/fuse/fuse_i.h | 8 ++++---- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index e47fa3a2b4a..21fd59c7bc2 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -762,12 +762,6 @@ static int parse_dirfile(char *buf, size_t nbytes, struct file *file, return 0; } -static size_t fuse_send_readdir(struct fuse_req *req, struct file *file, - struct inode *inode, loff_t pos, size_t count) -{ - return fuse_send_read_common(req, file, inode, pos, count, 1); -} - static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) { int err; @@ -791,7 +785,9 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) } req->num_pages = 1; req->pages[0] = page; - nbytes = fuse_send_readdir(req, file, inode, file->f_pos, PAGE_SIZE); + fuse_read_fill(req, file, inode, file->f_pos, PAGE_SIZE, FUSE_READDIR); + request_send(fc, req); + nbytes = req->out.args[0].size; err = req->out.h.error; fuse_put_request(fc, req); if (!err) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 043d5b36846..4a0b0f9a217 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -250,19 +250,16 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync) return fuse_fsync_common(file, de, datasync, 0); } -size_t fuse_send_read_common(struct fuse_req *req, struct file *file, - struct inode *inode, loff_t pos, size_t count, - int isdir) +void fuse_read_fill(struct fuse_req *req, struct file *file, + struct inode *inode, loff_t pos, size_t count, int opcode) { - struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_file *ff = file->private_data; - struct fuse_read_in inarg; + struct fuse_read_in *inarg = &req->misc.read_in; - memset(&inarg, 0, sizeof(struct fuse_read_in)); - inarg.fh = ff->fh; - inarg.offset = pos; - inarg.size = count; - req->in.h.opcode = isdir ? FUSE_READDIR : FUSE_READ; + inarg->fh = ff->fh; + inarg->offset = pos; + inarg->size = count; + req->in.h.opcode = opcode; req->in.h.nodeid = get_node_id(inode); req->inode = inode; req->file = file; @@ -273,14 +270,15 @@ size_t fuse_send_read_common(struct fuse_req *req, struct file *file, req->out.argvar = 1; req->out.numargs = 1; req->out.args[0].size = count; - request_send(fc, req); - return req->out.args[0].size; } static size_t fuse_send_read(struct fuse_req *req, struct file *file, struct inode *inode, loff_t pos, size_t count) { - return fuse_send_read_common(req, file, inode, pos, count, 0); + struct fuse_conn *fc = get_fuse_conn(inode); + fuse_read_fill(req, file, inode, pos, count, FUSE_READ); + request_send(fc, req); + return req->out.args[0].size; } static int fuse_readpage(struct file *file, struct page *page) diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 926b41c959d..7ed1d3c53b8 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -169,6 +169,7 @@ struct fuse_req { struct fuse_release_in release_in; struct fuse_init_in init_in; struct fuse_init_out init_out; + struct fuse_read_in read_in; } misc; /** page vector */ @@ -354,11 +355,10 @@ void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req, unsigned long nodeid, u64 nlookup); /** - * Send READ or READDIR request + * Initialize READ or READDIR request */ -size_t fuse_send_read_common(struct fuse_req *req, struct file *file, - struct inode *inode, loff_t pos, size_t count, - int isdir); +void fuse_read_fill(struct fuse_req *req, struct file *file, + struct inode *inode, loff_t pos, size_t count, int opcode); /** * Send OPEN or OPENDIR request -- GitLab From c1aa96a52e9594fb16296c0d76c2066773d62933 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 16 Jan 2006 22:14:46 -0800 Subject: [PATCH 398/465] [PATCH] fuse: use asynchronous READ requests for readpages This patch changes fuse_readpages() to send READ requests asynchronously. This makes it possible for userspace filesystems to utilize the kernel readahead logic instead of having to implement their own (resulting in double caching). Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/file.c | 44 +++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 4a0b0f9a217..a7ef5e716f3 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -265,7 +265,7 @@ void fuse_read_fill(struct fuse_req *req, struct file *file, req->file = file; req->in.numargs = 1; req->in.args[0].size = sizeof(struct fuse_read_in); - req->in.args[0].value = &inarg; + req->in.args[0].value = inarg; req->out.argpages = 1; req->out.argvar = 1; req->out.numargs = 1; @@ -311,21 +311,33 @@ static int fuse_readpage(struct file *file, struct page *page) return err; } -static int fuse_send_readpages(struct fuse_req *req, struct file *file, - struct inode *inode) +static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req) { - loff_t pos = page_offset(req->pages[0]); - size_t count = req->num_pages << PAGE_CACHE_SHIFT; - unsigned i; - req->out.page_zeroing = 1; - fuse_send_read(req, file, inode, pos, count); + int i; + + fuse_invalidate_attr(req->pages[0]->mapping->host); /* atime changed */ + for (i = 0; i < req->num_pages; i++) { struct page *page = req->pages[i]; if (!req->out.h.error) SetPageUptodate(page); + else + SetPageError(page); unlock_page(page); } - return req->out.h.error; + fuse_put_request(fc, req); +} + +static void fuse_send_readpages(struct fuse_req *req, struct file *file, + struct inode *inode) +{ + struct fuse_conn *fc = get_fuse_conn(inode); + loff_t pos = page_offset(req->pages[0]); + size_t count = req->num_pages << PAGE_CACHE_SHIFT; + req->out.page_zeroing = 1; + req->end = fuse_readpages_end; + fuse_read_fill(req, file, inode, pos, count, FUSE_READ); + request_send_background(fc, req); } struct fuse_readpages_data { @@ -345,12 +357,12 @@ static int fuse_readpages_fill(void *_data, struct page *page) (req->num_pages == FUSE_MAX_PAGES_PER_REQ || (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read || req->pages[req->num_pages - 1]->index + 1 != page->index)) { - int err = fuse_send_readpages(req, data->file, inode); - if (err) { + fuse_send_readpages(req, data->file, inode); + data->req = req = fuse_get_request(fc); + if (!req) { unlock_page(page); - return err; + return -EINTR; } - fuse_reset_request(req); } req->pages[req->num_pages] = page; req->num_pages ++; @@ -375,10 +387,8 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, return -EINTR; err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); - if (!err && data.req->num_pages) - err = fuse_send_readpages(data.req, file, inode); - fuse_put_request(fc, data.req); - fuse_invalidate_attr(inode); /* atime changed */ + if (!err) + fuse_send_readpages(data.req, file, inode); return err; } -- GitLab From bacac382fbf53f717ca7f83558e45cce44e67df9 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 16 Jan 2006 22:14:47 -0800 Subject: [PATCH 399/465] [PATCH] fuse: update documentation for sysfs Add documentation for new attributes in sysfs. Also describe the filesystem. Signed-off-by: Miklos Szeredi Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/filesystems/fuse.txt | 63 ++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/Documentation/filesystems/fuse.txt b/Documentation/filesystems/fuse.txt index 6b5741e651a..33f74310d16 100644 --- a/Documentation/filesystems/fuse.txt +++ b/Documentation/filesystems/fuse.txt @@ -86,6 +86,62 @@ Mount options The default is infinite. Note that the size of read requests is limited anyway to 32 pages (which is 128kbyte on i386). +Sysfs +~~~~~ + +FUSE sets up the following hierarchy in sysfs: + + /sys/fs/fuse/connections/N/ + +where N is an increasing number allocated to each new connection. + +For each connection the following attributes are defined: + + 'waiting' + + The number of requests which are waiting to be transfered to + userspace or being processed by the filesystem daemon. If there is + no filesystem activity and 'waiting' is non-zero, then the + filesystem is hung or deadlocked. + + 'abort' + + Writing anything into this file will abort the filesystem + connection. This means that all waiting requests will be aborted an + error returned for all aborted and new requests. + +Only a privileged user may read or write these attributes. + +Aborting a filesystem connection +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +It is possible to get into certain situations where the filesystem is +not responding. Reasons for this may be: + + a) Broken userspace filesystem implementation + + b) Network connection down + + c) Accidental deadlock + + d) Malicious deadlock + +(For more on c) and d) see later sections) + +In either of these cases it may be useful to abort the connection to +the filesystem. There are several ways to do this: + + - Kill the filesystem daemon. Works in case of a) and b) + + - Kill the filesystem daemon and all users of the filesystem. Works + in all cases except some malicious deadlocks + + - Use forced umount (umount -f). Works in all cases but only if + filesystem is still attached (it hasn't been lazy unmounted) + + - Abort filesystem through the sysfs interface. Most powerful + method, always works. + How do non-privileged mounts work? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -313,3 +369,10 @@ faulted with get_user_pages(). The 'req->locked' flag indicates when the copy is taking place, and interruption is delayed until this flag is unset. +Scenario 3 - Tricky deadlock with asynchronous read +--------------------------------------------------- + +The same situation as above, except thread-1 will wait on page lock +and hence it will be uninterruptible as well. The solution is to +abort the connection with forced umount (if mount is attached) or +through the abort attribute in sysfs. -- GitLab From 095da6cbb6a1c54c19b11190218eb0fbac666b6d Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 16 Jan 2006 22:14:52 -0800 Subject: [PATCH 400/465] [PATCH] fuse: fix bitfield race Fix race in setting bitfields of fuse_conn. Spotted by Andrew Morton. The two fields ->connected and ->mounted were always changed with the fuse_lock held. But other bitfields in the same structure were changed without the lock. In theory this could lead to losing the assignment of even the ones under lock. The chosen solution is to change these two fields to be a full unsigned type. The other bitfields aren't "important" enough to warrant the extra complexity of full locking or changing them to bitops. For all bitfields document why they are safe wrt. concurrent assignments. Also make the initialization of the 'num_waiting' atomic counter explicit. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/fuse_i.h | 24 +++++++++++++++++++++--- fs/fuse/inode.c | 2 ++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 7ed1d3c53b8..46cf933aa3b 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -94,6 +94,11 @@ struct fuse_out { /** Header returned from userspace */ struct fuse_out_header h; + /* + * The following bitfields are not changed during the request + * processing + */ + /** Last argument is variable length (can be shorter than arg->size) */ unsigned argvar:1; @@ -136,6 +141,12 @@ struct fuse_req { /** refcount */ atomic_t count; + /* + * The following bitfields are either set once before the + * request is queued or setting/clearing them is protected by + * fuse_lock + */ + /** True if the request has reply */ unsigned isreply:1; @@ -250,15 +261,22 @@ struct fuse_conn { u64 reqctr; /** Mount is active */ - unsigned mounted : 1; + unsigned mounted; /** Connection established, cleared on umount, connection abort and device release */ - unsigned connected : 1; + unsigned connected; - /** Connection failed (version mismatch) */ + /** Connection failed (version mismatch). Cannot race with + setting other bitfields since it is only set once in INIT + reply, before any other request, and never cleared */ unsigned conn_error : 1; + /* + * The following bitfields are only for optimization purposes + * and hence races in setting them will not cause malfunction + */ + /** Is fsync not implemented by fs? */ unsigned no_fsync : 1; diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 8683e7254d5..c755a0440a6 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -397,6 +397,7 @@ static struct fuse_conn *new_conn(void) init_rwsem(&fc->sbput_sem); kobj_set_kset_s(fc, connections_subsys); kobject_init(&fc->kobj); + atomic_set(&fc->num_waiting, 0); for (i = 0; i < FUSE_MAX_OUTSTANDING; i++) { struct fuse_req *req = fuse_request_alloc(); if (!req) { @@ -492,6 +493,7 @@ static void fuse_send_init(struct fuse_conn *fc) to be exactly one request available */ struct fuse_req *req = fuse_get_request(fc); struct fuse_init_in *arg = &req->misc.init_in; + arg->major = FUSE_KERNEL_VERSION; arg->minor = FUSE_KERNEL_MINOR_VERSION; req->in.h.opcode = FUSE_INIT; -- GitLab From 5aeebe01cb2ba1bca4cd9b8a6e77386bd7499dc2 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 16 Jan 2006 22:14:53 -0800 Subject: [PATCH 401/465] [PATCH] cs89x0: credit Dmitry Pervushin Credit Dmitry Pervushin for the PNX010X platform support. Signed-off-by: Lennert Buytenhek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/cs89x0.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index fab6586d87e..ef54ebeb29b 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c @@ -93,6 +93,9 @@ Deepak Saxena : dsaxena@plexity.net : Intel IXDP2351 platform support + Dmitry Pervushin : dpervushin@ru.mvista.com + : PNX010X platform support + */ /* Always include 'config.h' first in case the user wants to turn on -- GitLab From 4c2645830e29c082217662e7486572e9637e9f1d Mon Sep 17 00:00:00 2001 From: Chuck Ebbert <76306.1226@compuserve.com> Date: Mon, 16 Jan 2006 22:14:55 -0800 Subject: [PATCH 402/465] [PATCH] elevator=as back-compatibility As of 2.6.15 you need to use "anticipatory" instead of "as". Fix that up so that `elevator=as' still works. Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Cc: Nick Piggin Cc: Jens Axboe Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- block/elevator.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/block/elevator.c b/block/elevator.c index 1d0759178e4..e8025b2ec54 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -149,6 +149,13 @@ static void elevator_setup_default(void) if (!chosen_elevator[0]) strcpy(chosen_elevator, CONFIG_DEFAULT_IOSCHED); + /* + * Be backwards-compatible with previous kernels, so users + * won't get the wrong elevator. + */ + if (!strcmp(chosen_elevator, "as")) + strcpy(chosen_elevator, "anticipatory"); + /* * If the given scheduler is not available, fall back to no-op. */ -- GitLab From 17115e0388ece8d7141c0282c88e7dfc61953f92 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 16 Jan 2006 22:14:57 -0800 Subject: [PATCH 403/465] [PATCH] md: Clear clevel whenever level is set. The 'level' of an md array can be set as either a number of a string. When one is set, the other must be marked 'undefined'. This wasn't being done in one place: where new arrays are created. Result: if md1 is a raid1, it is stopped and a raid5 is created there, it might still appear to be a raid1. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/md/md.c b/drivers/md/md.c index 1778104e106..7145cd150f7 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3395,6 +3395,7 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info) mddev->ctime = get_seconds(); mddev->level = info->level; + mddev->clevel[0] = 0; mddev->size = info->size; mddev->raid_disks = info->raid_disks; /* don't set md_minor, it is determined by which /dev/md* was -- GitLab From 0addb142afa12a9bdf6cc53d3e86670c59c82d8f Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 17 Jan 2006 07:03:29 +0100 Subject: [PATCH 404/465] [PATCH] x86_64: Update defconfig Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds --- arch/x86_64/defconfig | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig index 054dcd8a5e9..5231fe83ea4 100644 --- a/arch/x86_64/defconfig +++ b/arch/x86_64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.15-git7 -# Wed Jan 11 11:57:36 2006 +# Linux kernel version: 2.6.15-git12 +# Mon Jan 16 13:09:08 2006 # CONFIG_X86_64=y CONFIG_64BIT=y @@ -319,6 +319,11 @@ CONFIG_IPV6=y # CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -537,8 +542,7 @@ CONFIG_SCSI_SATA_INTEL_COMBINED=y # CONFIG_SCSI_IPR is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set -CONFIG_SCSI_QLA2XXX=y -# CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE is not set +# CONFIG_SCSI_QLA_FC is not set # CONFIG_SCSI_LPFC is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set @@ -805,6 +809,7 @@ CONFIG_SOFT_WATCHDOG=y # CONFIG_W83877F_WDT is not set # CONFIG_W83977F_WDT is not set # CONFIG_MACHZ_WDT is not set +# CONFIG_SBC_EPX_C3_WATCHDOG is not set # # PCI-based Watchdog Cards @@ -849,6 +854,12 @@ CONFIG_HPET_MMAP=y # # CONFIG_I2C is not set +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + # # Dallas's 1-wire bus # @@ -992,6 +1003,7 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_HID=y CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set # CONFIG_HID_FF is not set # CONFIG_USB_HIDDEV is not set # CONFIG_USB_AIPTEK is not set @@ -1276,6 +1288,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_DEBUG_FS=y # CONFIG_DEBUG_VM is not set # CONFIG_FRAME_POINTER is not set +# CONFIG_FORCED_INLINING is not set # CONFIG_RCU_TORTURE_TEST is not set CONFIG_INIT_DEBUG=y # CONFIG_DEBUG_RODATA is not set -- GitLab From f0cf5d1a34725f3eab39120204da4afa43874269 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Tue, 17 Jan 2006 07:03:32 +0100 Subject: [PATCH 405/465] [PATCH] x86_64: eliminate empty_bad_{page,{pte,pmd}_table} ... as they are no longer needed. Since there were hard-coded numbers in the file, the patch also adds a mechanism to avoid these (otherwise potential future changes would again and again require adjusting these numbers). Signed-Off-By: Jan Beulich Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds --- arch/x86_64/kernel/head.S | 108 +++++++++++++------------------------- 1 file changed, 37 insertions(+), 71 deletions(-) diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S index 38fc3d5112e..692c737fedd 100644 --- a/arch/x86_64/kernel/head.S +++ b/arch/x86_64/kernel/head.S @@ -241,104 +241,70 @@ ljumpvector: ENTRY(stext) ENTRY(_stext) -.org 0x1000 -ENTRY(init_level4_pgt) + $page = 0 +#define NEXT_PAGE(name) \ + $page = $page + 1; \ + .org $page * 0x1000; \ + phys_/**/name = $page * 0x1000 + __PHYSICAL_START; \ +ENTRY(name) + +NEXT_PAGE(init_level4_pgt) /* This gets initialized in x86_64_start_kernel */ .fill 512,8,0 -.org 0x2000 -ENTRY(level3_ident_pgt) - .quad 0x0000000000004007 + __PHYSICAL_START +NEXT_PAGE(level3_ident_pgt) + .quad phys_level2_ident_pgt | 0x007 .fill 511,8,0 -.org 0x3000 -ENTRY(level3_kernel_pgt) +NEXT_PAGE(level3_kernel_pgt) .fill 510,8,0 /* (2^48-(2*1024*1024*1024)-((2^39)*511))/(2^30) = 510 */ - .quad 0x0000000000005007 + __PHYSICAL_START /* -> level2_kernel_pgt */ + .quad phys_level2_kernel_pgt | 0x007 .fill 1,8,0 -.org 0x4000 -ENTRY(level2_ident_pgt) +NEXT_PAGE(level2_ident_pgt) /* 40MB for bootup. */ - .quad 0x0000000000000083 - .quad 0x0000000000200083 - .quad 0x0000000000400083 - .quad 0x0000000000600083 - .quad 0x0000000000800083 - .quad 0x0000000000A00083 - .quad 0x0000000000C00083 - .quad 0x0000000000E00083 - .quad 0x0000000001000083 - .quad 0x0000000001200083 - .quad 0x0000000001400083 - .quad 0x0000000001600083 - .quad 0x0000000001800083 - .quad 0x0000000001A00083 - .quad 0x0000000001C00083 - .quad 0x0000000001E00083 - .quad 0x0000000002000083 - .quad 0x0000000002200083 - .quad 0x0000000002400083 - .quad 0x0000000002600083 + i = 0 + .rept 20 + .quad i << 21 | 0x083 + i = i + 1 + .endr /* Temporary mappings for the super early allocator in arch/x86_64/mm/init.c */ .globl temp_boot_pmds temp_boot_pmds: .fill 492,8,0 -.org 0x5000 -ENTRY(level2_kernel_pgt) +NEXT_PAGE(level2_kernel_pgt) /* 40MB kernel mapping. The kernel code cannot be bigger than that. When you change this change KERNEL_TEXT_SIZE in page.h too. */ /* (2^48-(2*1024*1024*1024)-((2^39)*511)-((2^30)*510)) = 0 */ - .quad 0x0000000000000183 - .quad 0x0000000000200183 - .quad 0x0000000000400183 - .quad 0x0000000000600183 - .quad 0x0000000000800183 - .quad 0x0000000000A00183 - .quad 0x0000000000C00183 - .quad 0x0000000000E00183 - .quad 0x0000000001000183 - .quad 0x0000000001200183 - .quad 0x0000000001400183 - .quad 0x0000000001600183 - .quad 0x0000000001800183 - .quad 0x0000000001A00183 - .quad 0x0000000001C00183 - .quad 0x0000000001E00183 - .quad 0x0000000002000183 - .quad 0x0000000002200183 - .quad 0x0000000002400183 - .quad 0x0000000002600183 + i = 0 + .rept 20 + .quad i << 21 | 0x183 + i = i + 1 + .endr /* Module mapping starts here */ .fill 492,8,0 -.org 0x6000 -ENTRY(empty_zero_page) - -.org 0x7000 -ENTRY(empty_bad_page) +NEXT_PAGE(empty_zero_page) -.org 0x8000 -ENTRY(empty_bad_pte_table) +NEXT_PAGE(level3_physmem_pgt) + .quad phys_level2_kernel_pgt | 0x007 /* so that __va works even before pagetable_init */ + .fill 511,8,0 -.org 0x9000 -ENTRY(empty_bad_pmd_table) +#undef NEXT_PAGE -.org 0xa000 -ENTRY(level3_physmem_pgt) - .quad 0x0000000000005007 + __PHYSICAL_START /* -> level2_kernel_pgt (so that __va works even before pagetable_init) */ + .data - .org 0xb000 #ifdef CONFIG_ACPI_SLEEP + .align PAGE_SIZE ENTRY(wakeup_level4_pgt) - .quad 0x0000000000002007 + __PHYSICAL_START /* -> level3_ident_pgt */ + .quad phys_level3_ident_pgt | 0x007 .fill 255,8,0 - .quad 0x000000000000a007 + __PHYSICAL_START + .quad phys_level3_physmem_pgt | 0x007 .fill 254,8,0 /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */ - .quad 0x0000000000003007 + __PHYSICAL_START /* -> level3_kernel_pgt */ + .quad phys_level3_kernel_pgt | 0x007 #endif #ifndef CONFIG_HOTPLUG_CPU @@ -352,12 +318,12 @@ ENTRY(wakeup_level4_pgt) */ .align PAGE_SIZE ENTRY(boot_level4_pgt) - .quad 0x0000000000002007 + __PHYSICAL_START /* -> level3_ident_pgt */ + .quad phys_level3_ident_pgt | 0x007 .fill 255,8,0 - .quad 0x000000000000a007 + __PHYSICAL_START + .quad phys_level3_physmem_pgt | 0x007 .fill 254,8,0 /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */ - .quad 0x0000000000003007 + __PHYSICAL_START /* -> level3_kernel_pgt */ + .quad phys_level3_kernel_pgt | 0x007 .data -- GitLab From 562795fe5770d0c7ee7fe269890e37d9fd475fdf Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 17 Jan 2006 07:03:35 +0100 Subject: [PATCH 406/465] [PATCH] x86_64: Remove elf32_map in 32bit ELF loader It's identical to the standard elf_map. Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds --- arch/x86_64/ia32/ia32_binfmt.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c index 029bddab045..572b3b28772 100644 --- a/arch/x86_64/ia32/ia32_binfmt.c +++ b/arch/x86_64/ia32/ia32_binfmt.c @@ -293,8 +293,6 @@ int ia32_setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top, int } while(0) -#define elf_map elf32_map - #include MODULE_DESCRIPTION("Binary format loader for compatibility with IA32 ELF binaries."); @@ -390,21 +388,6 @@ int ia32_setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top, } EXPORT_SYMBOL(ia32_setup_arg_pages); -static unsigned long -elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type) -{ - unsigned long map_addr; - struct task_struct *me = current; - - down_write(&me->mm->mmap_sem); - map_addr = do_mmap(filep, ELF_PAGESTART(addr), - eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr), prot, - type, - eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr)); - up_write(&me->mm->mmap_sem); - return(map_addr); -} - #ifdef CONFIG_SYSCTL /* Register vsyscall32 into the ABI table */ #include -- GitLab From 8817210d4d968e58f7d93db2eecd17b20dd03d40 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 17 Jan 2006 07:03:38 +0100 Subject: [PATCH 407/465] [PATCH] x86_64: Flexmap for 32bit and randomized mappings for 64bit Another try at this. For 32bit follow the 32bit implementation from Ingo - mappings are growing down from the end of stack now and vary randomly by 1GB. Randomized mappings for 64bit just vary the normal mmap break by 1TB. I didn't bother implementing full flex mmap for 64bit because it shouldn't be needed there. Cc: mingo@elte.hu Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds --- arch/x86_64/ia32/Makefile | 3 +- arch/x86_64/ia32/mmap32.c | 78 ++++++++++++++++++++++++++++++++++ arch/x86_64/mm/Makefile | 2 +- arch/x86_64/mm/mmap.c | 30 +++++++++++++ include/asm-x86_64/ia32.h | 2 + include/asm-x86_64/processor.h | 2 + 6 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 arch/x86_64/ia32/mmap32.c create mode 100644 arch/x86_64/mm/mmap.c diff --git a/arch/x86_64/ia32/Makefile b/arch/x86_64/ia32/Makefile index 051608d5592..929e6b0771f 100644 --- a/arch/x86_64/ia32/Makefile +++ b/arch/x86_64/ia32/Makefile @@ -3,7 +3,8 @@ # obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_signal.o tls32.o \ - ia32_binfmt.o fpu32.o ptrace32.o syscall32.o syscall32_syscall.o + ia32_binfmt.o fpu32.o ptrace32.o syscall32.o syscall32_syscall.o \ + mmap32.o sysv-$(CONFIG_SYSVIPC) := ipc32.o obj-$(CONFIG_IA32_EMULATION) += $(sysv-y) diff --git a/arch/x86_64/ia32/mmap32.c b/arch/x86_64/ia32/mmap32.c new file mode 100644 index 00000000000..079f4132575 --- /dev/null +++ b/arch/x86_64/ia32/mmap32.c @@ -0,0 +1,78 @@ +/* + * linux/arch/x86_64/ia32/mm/mmap.c + * + * flexible mmap layout support + * + * Based on the i386 version which was + * + * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. + * All Rights Reserved. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * + * Started by Ingo Molnar + */ + +#include +#include +#include + +/* + * Top of mmap area (just below the process stack). + * + * Leave an at least ~128 MB hole. + */ +#define MIN_GAP (128*1024*1024) +#define MAX_GAP (TASK_SIZE/6*5) + +static inline unsigned long mmap_base(struct mm_struct *mm) +{ + unsigned long gap = current->signal->rlim[RLIMIT_STACK].rlim_cur; + unsigned long random_factor = 0; + + if (current->flags & PF_RANDOMIZE) + random_factor = get_random_int() % (1024*1024); + + if (gap < MIN_GAP) + gap = MIN_GAP; + else if (gap > MAX_GAP) + gap = MAX_GAP; + + return PAGE_ALIGN(TASK_SIZE - gap - random_factor); +} + +/* + * This function, called very early during the creation of a new + * process VM image, sets up which VM layout function to use: + */ +void ia32_pick_mmap_layout(struct mm_struct *mm) +{ + /* + * Fall back to the standard layout if the personality + * bit is set, or if the expected stack growth is unlimited: + */ + if (sysctl_legacy_va_layout || + (current->personality & ADDR_COMPAT_LAYOUT) || + current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) { + mm->mmap_base = TASK_UNMAPPED_BASE; + mm->get_unmapped_area = arch_get_unmapped_area; + mm->unmap_area = arch_unmap_area; + } else { + mm->mmap_base = mmap_base(mm); + mm->get_unmapped_area = arch_get_unmapped_area_topdown; + mm->unmap_area = arch_unmap_area_topdown; + } +} diff --git a/arch/x86_64/mm/Makefile b/arch/x86_64/mm/Makefile index 1d232a87f11..d25ac86fe27 100644 --- a/arch/x86_64/mm/Makefile +++ b/arch/x86_64/mm/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux x86_64-specific parts of the memory manager. # -obj-y := init.o fault.o ioremap.o extable.o pageattr.o +obj-y := init.o fault.o ioremap.o extable.o pageattr.o mmap.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o obj-$(CONFIG_NUMA) += numa.o obj-$(CONFIG_K8_NUMA) += k8topology.o diff --git a/arch/x86_64/mm/mmap.c b/arch/x86_64/mm/mmap.c new file mode 100644 index 00000000000..43e9b99bdf2 --- /dev/null +++ b/arch/x86_64/mm/mmap.c @@ -0,0 +1,30 @@ +/* Copyright 2005 Andi Kleen, SuSE Labs. + * Licensed under GPL, v.2 + */ +#include +#include +#include +#include +#include + +/* Notebook: move the mmap code from sys_x86_64.c over here. */ + +void arch_pick_mmap_layout(struct mm_struct *mm) +{ +#ifdef CONFIG_IA32_EMULATION + if (current_thread_info()->flags & _TIF_IA32) + return ia32_pick_mmap_layout(mm); +#endif + mm->mmap_base = TASK_UNMAPPED_BASE; + if (current->flags & PF_RANDOMIZE) { + /* Add 28bit randomness which is about 40bits of address space + because mmap base has to be page aligned. + or ~1/128 of the total user VM + (total user address space is 47bits) */ + unsigned rnd = get_random_int() & 0xfffffff; + mm->mmap_base += ((unsigned long)rnd) << PAGE_SHIFT; + } + mm->get_unmapped_area = arch_get_unmapped_area; + mm->unmap_area = arch_unmap_area; +} + diff --git a/include/asm-x86_64/ia32.h b/include/asm-x86_64/ia32.h index c7bc9c0525b..e6b7f2234e4 100644 --- a/include/asm-x86_64/ia32.h +++ b/include/asm-x86_64/ia32.h @@ -169,6 +169,8 @@ int ia32_child_tls(struct task_struct *p, struct pt_regs *childregs); struct linux_binprm; extern int ia32_setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top, int exec_stack); +struct mm_struct; +extern void ia32_pick_mmap_layout(struct mm_struct *mm); #endif diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h index a1ba7c97465..8c8d88c036e 100644 --- a/include/asm-x86_64/processor.h +++ b/include/asm-x86_64/processor.h @@ -477,4 +477,6 @@ extern unsigned long boot_option_idle_override; /* Boot loader type from the setup header */ extern int bootloader_type; +#define HAVE_ARCH_PICK_MMAP_LAYOUT 1 + #endif /* __ASM_X86_64_PROCESSOR_H */ -- GitLab From 44df75e629106efcada087cead6c3f33ed6bcc60 Mon Sep 17 00:00:00 2001 From: Matt Tolentino Date: Tue, 17 Jan 2006 07:03:41 +0100 Subject: [PATCH 408/465] [PATCH] x86_64: add x86-64 support for memory hot-add Add x86-64 specific memory hot-add functions, Kconfig options, and runtime kernel page table update functions to make hot-add usable on x86-64 machines. Also, fixup the nefarious conditional locking and exports pointed out by Andi. Tested on Intel and IBM x86-64 memory hot-add capable systems. Signed-off-by: Matt Tolentino Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds --- arch/x86_64/Kconfig | 7 +- arch/x86_64/mm/init.c | 160 +++++++++++++++++++++++++++++++++--------- 2 files changed, 134 insertions(+), 33 deletions(-) diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 787feff0e8a..2f9deca31cc 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -305,7 +305,11 @@ config ARCH_DISCONTIGMEM_DEFAULT config ARCH_SPARSEMEM_ENABLE def_bool y - depends on NUMA + depends on (NUMA || EXPERIMENTAL) + +config ARCH_MEMORY_PROBE + def_bool y + depends on MEMORY_HOTPLUG config ARCH_FLATMEM_ENABLE def_bool y @@ -315,6 +319,7 @@ source "mm/Kconfig" config HAVE_ARCH_EARLY_PFN_TO_NID def_bool y + depends on NUMA config NR_CPUS int "Maximum number of CPUs (2-256)" diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c index 307d1ac0ef3..7af1742aa95 100644 --- a/arch/x86_64/mm/init.c +++ b/arch/x86_64/mm/init.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include @@ -180,13 +182,19 @@ static struct temp_map { {} }; -static __init void *alloc_low_page(int *index, unsigned long *phys) +static __meminit void *alloc_low_page(int *index, unsigned long *phys) { struct temp_map *ti; int i; unsigned long pfn = table_end++, paddr; void *adr; + if (after_bootmem) { + adr = (void *)get_zeroed_page(GFP_ATOMIC); + *phys = __pa(adr); + return adr; + } + if (pfn >= end_pfn) panic("alloc_low_page: ran out of memory"); for (i = 0; temp_mappings[i].allocated; i++) { @@ -199,55 +207,86 @@ static __init void *alloc_low_page(int *index, unsigned long *phys) ti->allocated = 1; __flush_tlb(); adr = ti->address + ((pfn << PAGE_SHIFT) & ~PMD_MASK); + memset(adr, 0, PAGE_SIZE); *index = i; *phys = pfn * PAGE_SIZE; return adr; } -static __init void unmap_low_page(int i) +static __meminit void unmap_low_page(int i) { - struct temp_map *ti = &temp_mappings[i]; + struct temp_map *ti; + + if (after_bootmem) + return; + + ti = &temp_mappings[i]; set_pmd(ti->pmd, __pmd(0)); ti->allocated = 0; } -static void __init phys_pud_init(pud_t *pud, unsigned long address, unsigned long end) +static void __meminit +phys_pmd_init(pmd_t *pmd, unsigned long address, unsigned long end) +{ + int i; + + for (i = 0; i < PTRS_PER_PMD; pmd++, i++, address += PMD_SIZE) { + unsigned long entry; + + if (address > end) { + for (; i < PTRS_PER_PMD; i++, pmd++) + set_pmd(pmd, __pmd(0)); + break; + } + entry = _PAGE_NX|_PAGE_PSE|_KERNPG_TABLE|_PAGE_GLOBAL|address; + entry &= __supported_pte_mask; + set_pmd(pmd, __pmd(entry)); + } +} + +static void __meminit +phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end) +{ + pmd_t *pmd = pmd_offset(pud, (unsigned long)__va(address)); + + if (pmd_none(*pmd)) { + spin_lock(&init_mm.page_table_lock); + phys_pmd_init(pmd, address, end); + spin_unlock(&init_mm.page_table_lock); + __flush_tlb_all(); + } +} + +static void __meminit phys_pud_init(pud_t *pud, unsigned long address, unsigned long end) { - long i, j; + long i = pud_index(address); - i = pud_index(address); pud = pud + i; + + if (after_bootmem && pud_val(*pud)) { + phys_pmd_update(pud, address, end); + return; + } + for (; i < PTRS_PER_PUD; pud++, i++) { int map; unsigned long paddr, pmd_phys; pmd_t *pmd; - paddr = address + i*PUD_SIZE; - if (paddr >= end) { - for (; i < PTRS_PER_PUD; i++, pud++) - set_pud(pud, __pud(0)); + paddr = (address & PGDIR_MASK) + i*PUD_SIZE; + if (paddr >= end) break; - } - if (!e820_mapped(paddr, paddr+PUD_SIZE, 0)) { + if (!after_bootmem && !e820_mapped(paddr, paddr+PUD_SIZE, 0)) { set_pud(pud, __pud(0)); continue; } pmd = alloc_low_page(&map, &pmd_phys); + spin_lock(&init_mm.page_table_lock); set_pud(pud, __pud(pmd_phys | _KERNPG_TABLE)); - for (j = 0; j < PTRS_PER_PMD; pmd++, j++, paddr += PMD_SIZE) { - unsigned long pe; - - if (paddr >= end) { - for (; j < PTRS_PER_PMD; j++, pmd++) - set_pmd(pmd, __pmd(0)); - break; - } - pe = _PAGE_NX|_PAGE_PSE | _KERNPG_TABLE | _PAGE_GLOBAL | paddr; - pe &= __supported_pte_mask; - set_pmd(pmd, __pmd(pe)); - } + phys_pmd_init(pmd, paddr, end); + spin_unlock(&init_mm.page_table_lock); unmap_low_page(map); } __flush_tlb(); @@ -272,12 +311,15 @@ static void __init find_early_table_space(unsigned long end) table_start >>= PAGE_SHIFT; table_end = table_start; + + early_printk("kernel direct mapping tables up to %lx @ %lx-%lx\n", + end, table_start << PAGE_SHIFT, table_end << PAGE_SHIFT); } /* Setup the direct mapping of the physical memory at PAGE_OFFSET. This runs before bootmem is initialized and gets pages directly from the physical memory. To access them they are temporarily mapped. */ -void __init init_memory_mapping(unsigned long start, unsigned long end) +void __meminit init_memory_mapping(unsigned long start, unsigned long end) { unsigned long next; @@ -289,7 +331,8 @@ void __init init_memory_mapping(unsigned long start, unsigned long end) * mapped. Unfortunately this is done currently before the nodes are * discovered. */ - find_early_table_space(end); + if (!after_bootmem) + find_early_table_space(end); start = (unsigned long)__va(start); end = (unsigned long)__va(end); @@ -297,20 +340,26 @@ void __init init_memory_mapping(unsigned long start, unsigned long end) for (; start < end; start = next) { int map; unsigned long pud_phys; - pud_t *pud = alloc_low_page(&map, &pud_phys); + pgd_t *pgd = pgd_offset_k(start); + pud_t *pud; + + if (after_bootmem) + pud = pud_offset_k(pgd, __PAGE_OFFSET); + else + pud = alloc_low_page(&map, &pud_phys); + next = start + PGDIR_SIZE; if (next > end) next = end; phys_pud_init(pud, __pa(start), __pa(next)); - set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys)); + if (!after_bootmem) + set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys)); unmap_low_page(map); } - asm volatile("movq %%cr4,%0" : "=r" (mmu_cr4_features)); + if (!after_bootmem) + asm volatile("movq %%cr4,%0" : "=r" (mmu_cr4_features)); __flush_tlb_all(); - early_printk("kernel direct mapping tables upto %lx @ %lx-%lx\n", end, - table_start<> PAGE_SHIFT, holes); @@ -425,6 +477,50 @@ void __init clear_kernel_mapping(unsigned long address, unsigned long size) __flush_tlb_all(); } +/* + * Memory hotplug specific functions + * These are only for non-NUMA machines right now. + */ +#ifdef CONFIG_MEMORY_HOTPLUG + +void online_page(struct page *page) +{ + ClearPageReserved(page); + set_page_count(page, 1); + __free_page(page); + totalram_pages++; + num_physpages++; +} + +int add_memory(u64 start, u64 size) +{ + struct pglist_data *pgdat = NODE_DATA(0); + struct zone *zone = pgdat->node_zones + MAX_NR_ZONES-2; + unsigned long start_pfn = start >> PAGE_SHIFT; + unsigned long nr_pages = size >> PAGE_SHIFT; + int ret; + + ret = __add_pages(zone, start_pfn, nr_pages); + if (ret) + goto error; + + init_memory_mapping(start, (start + size -1)); + + return ret; +error: + printk("%s: Problem encountered in __add_pages!\n", __func__); + return ret; +} +EXPORT_SYMBOL_GPL(add_memory); + +int remove_memory(u64 start, u64 size) +{ + return -EINVAL; +} +EXPORT_SYMBOL_GPL(remove_memory); + +#endif + static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, kcore_modules, kcore_vsyscall; -- GitLab From c09b42404d29c8a9266f8186632330dc8474bf2e Mon Sep 17 00:00:00 2001 From: Matt Tolentino Date: Tue, 17 Jan 2006 07:03:44 +0100 Subject: [PATCH 409/465] [PATCH] x86_64: add __meminit for memory hotplug Add __meminit to the __init lineup to ensure functions default to __init when memory hotplug is not enabled. Replace __devinit with __meminit on functions that were changed when the memory hotplug code was introduced. Signed-off-by: Matt Tolentino Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds --- arch/i386/mm/init.c | 2 +- include/linux/init.h | 12 ++++++++++++ mm/page_alloc.c | 14 +++++++------- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index 7df494b51a5..2700f01994b 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c @@ -268,7 +268,7 @@ static void __init permanent_kmaps_init(pgd_t *pgd_base) pkmap_page_table = pte; } -static void __devinit free_new_highpage(struct page *page) +static void __meminit free_new_highpage(struct page *page) { set_page_count(page, 1); __free_page(page); diff --git a/include/linux/init.h b/include/linux/init.h index 59008c3826c..ff8d8b8632f 100644 --- a/include/linux/init.h +++ b/include/linux/init.h @@ -241,6 +241,18 @@ void __init parse_early_param(void); #define __cpuexitdata __exitdata #endif +#ifdef CONFIG_MEMORY_HOTPLUG +#define __meminit +#define __meminitdata +#define __memexit +#define __memexitdata +#else +#define __meminit __init +#define __meminitdata __initdata +#define __memexit __exit +#define __memexitdata __exitdata +#endif + /* Functions marked as __devexit may be discarded at kernel link time, depending on config options. Newer versions of binutils detect references from retained sections to discarded sections and flag an error. Pointers to diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 8c960b46959..c2e29743a8d 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1735,7 +1735,7 @@ static void __init calculate_zone_totalpages(struct pglist_data *pgdat, * up by free_all_bootmem() once the early boot process is * done. Non-atomic initialization, single-pass. */ -void __devinit memmap_init_zone(unsigned long size, int nid, unsigned long zone, +void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone, unsigned long start_pfn) { struct page *page; @@ -1788,7 +1788,7 @@ void zonetable_add(struct zone *zone, int nid, int zid, unsigned long pfn, memmap_init_zone((size), (nid), (zone), (start_pfn)) #endif -static int __devinit zone_batchsize(struct zone *zone) +static int __meminit zone_batchsize(struct zone *zone) { int batch; @@ -1882,7 +1882,7 @@ static struct per_cpu_pageset * Dynamically allocate memory for the * per cpu pageset array in struct zone. */ -static int __devinit process_zones(int cpu) +static int __meminit process_zones(int cpu) { struct zone *zone, *dzone; @@ -1923,7 +1923,7 @@ static inline void free_zone_pagesets(int cpu) } } -static int __devinit pageset_cpuup_callback(struct notifier_block *nfb, +static int __meminit pageset_cpuup_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -1963,7 +1963,7 @@ void __init setup_per_cpu_pageset(void) #endif -static __devinit +static __meminit void zone_wait_table_init(struct zone *zone, unsigned long zone_size_pages) { int i; @@ -1983,7 +1983,7 @@ void zone_wait_table_init(struct zone *zone, unsigned long zone_size_pages) init_waitqueue_head(zone->wait_table + i); } -static __devinit void zone_pcp_init(struct zone *zone) +static __meminit void zone_pcp_init(struct zone *zone) { int cpu; unsigned long batch = zone_batchsize(zone); @@ -2001,7 +2001,7 @@ static __devinit void zone_pcp_init(struct zone *zone) zone->name, zone->present_pages, batch); } -static __devinit void init_currently_empty_zone(struct zone *zone, +static __meminit void init_currently_empty_zone(struct zone *zone, unsigned long zone_start_pfn, unsigned long size) { struct pglist_data *pgdat = zone->zone_pgdat; -- GitLab From 2ddb55f091a9c74a297d72b50f8310c0c8ed7d1d Mon Sep 17 00:00:00 2001 From: Ravikiran G Thirumalai Date: Tue, 17 Jan 2006 07:03:47 +0100 Subject: [PATCH 410/465] [PATCH] x86_64: Fix VSMP build Patch fixes a build problem with CONFIG_X86_VSMP. The vSMP bits probably gathered some fuzz on its way to mainline, and safe_halt() which was outside the #endif (CONFIG_X86_VSMP) somehow got inside the !CONFIG_X86_VSMP condition, hence being undefined and breaking CONFIG_X86_VSMP builds. Patch takes safe_halt() and halt() macros out of the #endif Signed-off-by: Ravikiran Thirumalai Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds --- include/asm-x86_64/system.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/asm-x86_64/system.h b/include/asm-x86_64/system.h index 0eacbefb7dd..a73f0c789d8 100644 --- a/include/asm-x86_64/system.h +++ b/include/asm-x86_64/system.h @@ -354,11 +354,6 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, #define local_irq_disable() __asm__ __volatile__("cli": : :"memory") #define local_irq_enable() __asm__ __volatile__("sti": : :"memory") -/* used in the idle loop; sti takes one instruction cycle to complete */ -#define safe_halt() __asm__ __volatile__("sti; hlt": : :"memory") -/* used when interrupts are already enabled or to shutdown the processor */ -#define halt() __asm__ __volatile__("hlt": : :"memory") - #define irqs_disabled() \ ({ \ unsigned long flags; \ @@ -370,6 +365,11 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, #define local_irq_save(x) do { warn_if_not_ulong(x); __asm__ __volatile__("# local_irq_save \n\t pushfq ; popq %0 ; cli":"=g" (x): /* no input */ :"memory"); } while (0) #endif +/* used in the idle loop; sti takes one instruction cycle to complete */ +#define safe_halt() __asm__ __volatile__("sti; hlt": : :"memory") +/* used when interrupts are already enabled or to shutdown the processor */ +#define halt() __asm__ __volatile__("hlt": : :"memory") + void cpu_idle_wait(void); extern unsigned long arch_align_stack(unsigned long sp); -- GitLab From ea13dbc89caecd982500894d4238766a6bd3c8f4 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 16 Jan 2006 10:59:41 +0100 Subject: [PATCH 411/465] [PATCH] kernel/hrtimer.c sparse warning fix fix the following sparse warning: kernel/hrtimer.c:665:34: warning: incorrect type in argument 2 (different address spaces) kernel/hrtimer.c:665:34: expected void const *from kernel/hrtimer.c:665:34: got struct timespec [noderef] * kernel/hrtimer.c:664:2: warning: dereference of noderef expression Signed-off-by: Ingo Molnar Signed-off-by: Linus Torvalds --- kernel/hrtimer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index f5ca6142233..f1c4155b49a 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -641,7 +641,8 @@ schedule_hrtimer_interruptible(struct hrtimer *timer, static long __sched nanosleep_restart(struct restart_block *restart, clockid_t clockid) { - struct timespec __user *rmtp, tu; + struct timespec __user *rmtp; + struct timespec tu; void *rfn_save = restart->fn; struct hrtimer timer; ktime_t rem; -- GitLab From a462e9ff524f33da3e504fc71b8dd2b7584e4f28 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 15 Jan 2006 23:32:53 -0500 Subject: [PATCH 412/465] [PATCH] Fix compile warning in bt8xx module Signed-off-by: Dmitry Torokhov Signed-off-by: Linus Torvalds --- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index 44fcbe77c8f..ea27b15007e 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -893,7 +893,7 @@ static int dvb_bt8xx_probe(struct bttv_sub_device *sub) return 0; } -static int dvb_bt8xx_remove(struct bttv_sub_device *sub) +static void dvb_bt8xx_remove(struct bttv_sub_device *sub) { struct dvb_bt8xx_card *card = dev_get_drvdata(&sub->dev); @@ -911,8 +911,6 @@ static int dvb_bt8xx_remove(struct bttv_sub_device *sub) dvb_unregister_adapter(&card->dvb_adapter); kfree(card); - - return 0; } static struct bttv_sub_driver driver = { -- GitLab From 4f4e2dc3ce46d279a311e5250ac3cbd394279c31 Mon Sep 17 00:00:00 2001 From: Xose Vazquez Perez Date: Sat, 14 Jan 2006 19:56:28 +0100 Subject: [PATCH 413/465] [PATCH] README updated Replace old information with newer from kernel.org Signed-off-by: Linus Torvalds --- README | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/README b/README index cd5e2eb6213..0d318abaf7f 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ - Linux kernel release 2.6.xx + Linux kernel release 2.6.xx These are the release notes for Linux version 2.6. Read them carefully, as they tell you what this is all about, explain how to install the @@ -6,23 +6,31 @@ kernel, and what to do if something goes wrong. WHAT IS LINUX? - Linux is a Unix clone written from scratch by Linus Torvalds with - assistance from a loosely-knit team of hackers across the Net. - It aims towards POSIX compliance. + Linux is a clone of the operating system Unix, written from scratch by + Linus Torvalds with assistance from a loosely-knit team of hackers across + the Net. It aims towards POSIX and Single UNIX Specification compliance. - It has all the features you would expect in a modern fully-fledged - Unix, including true multitasking, virtual memory, shared libraries, - demand loading, shared copy-on-write executables, proper memory - management and TCP/IP networking. + It has all the features you would expect in a modern fully-fledged Unix, + including true multitasking, virtual memory, shared libraries, demand + loading, shared copy-on-write executables, proper memory management, + and multistack networking including IPv4 and IPv6. It is distributed under the GNU General Public License - see the accompanying COPYING file for more details. ON WHAT HARDWARE DOES IT RUN? - Linux was first developed for 386/486-based PCs. These days it also - runs on ARMs, DEC Alphas, SUN Sparcs, M68000 machines (like Atari and - Amiga), MIPS and PowerPC, and others. + Although originally developed first for 32-bit x86-based PCs (386 or higher), + today Linux also runs on (at least) the Compaq Alpha AXP, Sun SPARC and + UltraSPARC, Motorola 68000, PowerPC, PowerPC64, ARM, Hitachi SuperH, + IBM S/390, MIPS, HP PA-RISC, Intel IA-64, DEC VAX, AMD x86-64, AXIS CRIS, + and Renesas M32R architectures. + + Linux is easily portable to most general-purpose 32- or 64-bit architectures + as long as they have a paged memory management unit (PMMU) and a port of the + GNU C compiler (gcc) (part of The GNU Compiler Collection, GCC). Linux has + also been ported to a number of architectures without a PMMU, although + functionality is then obviously somewhat limited. DOCUMENTATION: -- GitLab From f504fb59c7e356d00ac56933a4462a6ba74d0c1d Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 16:44:05 +0000 Subject: [PATCH 414/465] [PATCH] Remove brates.h from rio driver (unused file) Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/rio/brates.h | 106 -------------------------------------- 1 file changed, 106 deletions(-) delete mode 100644 drivers/char/rio/brates.h diff --git a/drivers/char/rio/brates.h b/drivers/char/rio/brates.h deleted file mode 100644 index dd686d58fd6..00000000000 --- a/drivers/char/rio/brates.h +++ /dev/null @@ -1,106 +0,0 @@ -/**************************************************************************** - ******* ******* - ******* BRATES.H ******* - ******* ******* - **************************************************************************** - - Author : Jeremy Rolls - Date : 1 Nov 1990 - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ - -#ifndef _brates_h -#ifndef lint -/* static char * _brates_h_sccs = "@(#)brates.h 1.4"; */ -#endif -#define _brates_h 1 -/* List of baud rate defines. Most are borrowed from /usr/include/sys/termio.h -*/ -#ifndef INKERNEL - -#define B0 0x00 -#define B50 0x01 -#define B75 0x02 -#define B110 0x03 -#define B134 0x04 -#define B150 0x05 -#define B200 0x06 -#define B300 0x07 -#define B600 0x08 -#define B1200 0x09 -#define B1800 0x0a -#define B2400 0x0b -#define B4800 0x0c -#define B9600 0x0d -#define B19200 0x0e -#define B38400 0x0f - -#endif - -/* -** The following baudrates may or may not be defined -** on various UNIX systems. -** If they are not then we define them. -** If they are then we do not define them ;-) -** -** This is appalling that we use same definitions as UNIX -** for our own download code as there is no garuntee that -** B57600 will be defined as 0x11 by a UNIX system.... -** Arghhhhh!!!!!!!!!!!!!! -*/ -#if !defined(B56000) -#define B56000 0x10 -#endif - -#if !defined(B57600) -#define B57600 0x11 -#endif - -#if !defined(B64000) -#define B64000 0x12 -#endif - -#if !defined(B115200) -#define B115200 0x13 -#endif - - -#if !defined(B2000) -#define B2000 0x14 -#endif - - -#define MAX_RATE B2000 - -struct baud_rate { /* Tag for baud rates */ - /* short host_rate, *//* As passed by the driver */ - short divisor, /* The divisor */ - prescaler; /* The pre-scaler */ -}; - -#endif -- GitLab From e8a9858aa2af3d14a37eafc6182d3b12923be41c Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 16:45:18 +0000 Subject: [PATCH 415/465] [PATCH] Remove cmd.h from rio driver (unused file) Signed-off-by: Linus Torvalds --- drivers/char/rio/cmd.h | 83 ------------------------------------------ 1 file changed, 83 deletions(-) delete mode 100644 drivers/char/rio/cmd.h diff --git a/drivers/char/rio/cmd.h b/drivers/char/rio/cmd.h deleted file mode 100644 index 797b62400c9..00000000000 --- a/drivers/char/rio/cmd.h +++ /dev/null @@ -1,83 +0,0 @@ - - -/**************************************************************************** - ******* ******* - ******* C O M M A N D P A C K E T H E A D E R S - ******* ******* - **************************************************************************** - - Author : Ian Nandhra - Date : - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ - - -#ifndef _cmd_h -#define _cmd_h - -#ifndef lint -#ifdef SCCS -static char *_rio_cmd_h_sccs = "@(#)cmd.h 1.1"; -#endif -#endif - - -#define PRE_EMPTIVE_CMD 0x80 -#define INLINE_CMD ~PRE_EMPTIVE_CMD - -#define CMD_IGNORE_PKT ( (ushort) 0) -#define CMD_STATUS_REQ ( (ushort) 1) -#define CMD_UNIT_STATUS_REQ ( (ushort) 2) /* Is this needed ??? */ -#define CMD_CONF_PORT ( (ushort) 3) -#define CMD_CONF_UNIT ( (ushort) 4) -#define CMD_ROUTE_MAP_REQ ( (ushort) 5) -#define CMD_FLUSH_TX ( (ushort) 6) -#define CMD_FLUSH_RX ( (ushort) 7) -#define CMD_PARTION_PORT ( (ushort) 8) -#define CMD_RESET_PORT ( (ushort) 0x0a) -#define CMD_BOOT_UNIT ( (ushort) 0x0b) -#define CMD_FOUND_UNIT ( (ushort) 0x0c) -#define CMD_ATTACHED_RTA_2 ( (ushort) 0x0d) -#define CMD_PROVIDE_BOOT ( (ushort) 0x0e) -#define CMD_CIRRUS ( (ushort) 0x0f) - -#define FORM_STATUS_PKT ( (ushort) 1 ) -#define FORM_POLL_PKT ( (ushort) 2 ) -#define FORM_LINK_STATUS_PKT ( (ushort) 3 ) - - -#define CMD_DATA_PORT ( (ushort) 1 ) -#define CMD_DATA ( (ushort) 2 ) - -#define CMD_TX_PART ( (ushort) 2 ) -#define CMD_RX_PART ( (ushort) 3 ) -#define CMD_RX_LIMIT ( (ushort) 4 ) - -#endif - -/*********** end of file ***********/ -- GitLab From 98da212f0d22cb6ef7fee96e62572c763194c77b Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 16:46:17 +0000 Subject: [PATCH 416/465] [PATCH] Remove chan.h from rio driver (unused file) Signed-off-by: Linus Torvalds --- drivers/char/rio/chan.h | 33 --------------------------------- 1 file changed, 33 deletions(-) delete mode 100644 drivers/char/rio/chan.h diff --git a/drivers/char/rio/chan.h b/drivers/char/rio/chan.h deleted file mode 100644 index af14311f9b6..00000000000 --- a/drivers/char/rio/chan.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ -#ifndef _chan_h -#define _chan_h - -#ifndef lint -#ifdef SCCS -static char *_rio_chan_h_sccs = "@(#)chan.h 1.1"; -#endif -#endif - -#define Link0 0 -#define Link1 1 -#define Link2 2 -#define Link3 3 - -#endif -- GitLab From 4198d8c3687418f245d7b351fd34702fb7fe0668 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 16:47:14 +0000 Subject: [PATCH 417/465] [PATCH] Remove data.h from rio driver (unused file) Signed-off-by: Linus Torvalds --- drivers/char/rio/data.h | 40 ---------------------------------------- 1 file changed, 40 deletions(-) delete mode 100644 drivers/char/rio/data.h diff --git a/drivers/char/rio/data.h b/drivers/char/rio/data.h deleted file mode 100644 index dabc2d1fa40..00000000000 --- a/drivers/char/rio/data.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : data.h -** SID : 1.2 -** Last Modified : 11/6/98 11:34:09 -** Retrieved : 11/6/98 11:34:21 -** -** ident @(#)data.h 1.2 -** -** ----------------------------------------------------------------------------- -*/ - -#ifndef __rio_datadex__ -#define __rio_datadex__ - -#ifndef lint -static char *_data_h_sccs_ = "@(#)data.h 1.2"; -#endif - -#endif -- GitLab From 0d233681274013a554194ce8e2fe8945cd49979f Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 16:48:12 +0000 Subject: [PATCH 418/465] [PATCH] Remove debug.h from rio.h (unused file) Signed-off-by: Linus Torvalds --- drivers/char/rio/debug.h | 39 --------------------------------------- 1 file changed, 39 deletions(-) delete mode 100644 drivers/char/rio/debug.h diff --git a/drivers/char/rio/debug.h b/drivers/char/rio/debug.h deleted file mode 100644 index 6ae95c00db4..00000000000 --- a/drivers/char/rio/debug.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -** File: debug.h -** -** Author: David Dix -** -** Created: 12th March 1993 -** -** Last modified: 93/04/27 -** - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifndef _debug_h_ -#define _debug_h_ - - -#if defined(DCIRRUS) -#define DBPACKET(pkt, opt, str, chn) debug_packet((pkt), (opt), (str), (chn)) -#else -#define DBPACKET(pkt, opt, str, c) -#endif /* DCIRRUS */ - - -#endif /* _debug_h_ */ -- GitLab From e67f76a6b1ab418b8232791d99ee728a395bd335 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 16:49:15 +0000 Subject: [PATCH 419/465] [PATCH] Remove enable.h from rio driver (unused file) Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/rio/eisa.h | 104 ---------------------------------------- 1 file changed, 104 deletions(-) delete mode 100644 drivers/char/rio/eisa.h diff --git a/drivers/char/rio/eisa.h b/drivers/char/rio/eisa.h deleted file mode 100644 index c2abaf0eab0..00000000000 --- a/drivers/char/rio/eisa.h +++ /dev/null @@ -1,104 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : eisa.h -** SID : 1.2 -** Last Modified : 11/6/98 11:34:10 -** Retrieved : 11/6/98 11:34:21 -** -** ident @(#)eisa.h 1.2 -** -** ----------------------------------------------------------------------------- -*/ - -#ifndef __rio_eisa_h__ -#define __rio_eisa_h__ - -#ifdef SCCS_LABELS -#ifndef lint -static char *_eisa_h_sccs_ = "@(#)eisa.h 1.2"; -#endif -#endif - -/* -** things to do with the EISA bus -*/ - -#define RIO_EISA_STRING_ADDRESS 0xfffd9 /* where EISA is stored */ - -#define RIO_MAX_EISA_SLOTS 16 /* how many EISA slots? */ - -#define RIO_EISA_IDENT 0x984D /* Specialix */ -#define RIO_EISA_PRODUCT_CODE 0x14 /* Code 14 */ -#define RIO_EISA_ENABLE_BIT 0x01 /* To enable card */ - -#define EISA_MEMORY_BASE_LO 0xC00 /* A16-A23 */ -#define EISA_MEMORY_BASE_HI 0xC01 /* A24-A31 */ -#define EISA_INTERRUPT_VEC 0xC02 /* see below */ -#define EISA_CONTROL_PORT 0xC02 /* see below */ -#define EISA_INTERRUPT_RESET 0xC03 /* read to clear IRQ */ - -#define EISA_PRODUCT_IDENT_LO 0xC80 /* where RIO_EISA_IDENT is */ -#define EISA_PRODUCT_IDENT_HI 0xC81 -#define EISA_PRODUCT_NUMBER 0xC82 /* where PROD_CODE is */ -#define EISA_REVISION_NUMBER 0xC83 /* revision (1dp) */ -#define EISA_ENABLE 0xC84 /* set LSB to enable card */ -#define EISA_UNIQUE_NUM_0 0xC88 /* vomit */ -#define EISA_UNIQUE_NUM_1 0xC8A -#define EISA_UNIQUE_NUM_2 0xC90 /* bit strangely arranged */ -#define EISA_UNIQUE_NUM_3 0xC92 -#define EISA_MANUF_YEAR 0xC98 /* when */ -#define EISA_MANUF_WEEK 0xC9A /* more when */ - -#define EISA_TP_BOOT_FROM_RAM 0x01 -#define EISA_TP_BOOT_FROM_LINK 0x00 -#define EISA_TP_FAST_LINKS 0x02 -#define EISA_TP_SLOW_LINKS 0x00 -#define EISA_TP_BUS_ENABLE 0x04 -#define EISA_TP_BUS_DISABLE 0x00 -#define EISA_TP_RUN 0x08 -#define EISA_TP_RESET 0x00 -#define EISA_POLLED 0x00 -#define EISA_IRQ_3 0x30 -#define EISA_IRQ_4 0x40 -#define EISA_IRQ_5 0x50 -#define EISA_IRQ_6 0x60 -#define EISA_IRQ_7 0x70 -#define EISA_IRQ_9 0x90 -#define EISA_IRQ_10 0xA0 -#define EISA_IRQ_11 0xB0 -#define EISA_IRQ_12 0xC0 -#define EISA_IRQ_14 0xE0 -#define EISA_IRQ_15 0xF0 - -#define EISA_INTERRUPT_MASK 0xF0 -#define EISA_CONTROL_MASK 0x0F - -#define RIO_EISA_DEFAULT_MODE EISA_TP_SLOW_LINKS - -#define RIOEisaToIvec(X) (uchar )((uchar)((X) & EISA_INTERRUPT_MASK)>>4) - -#define INBZ(z,x) inb(((z)<<12) | (x)) -#define OUTBZ(z,x,y) outb((((z)<<12) | (x)), y) - -#endif /* __rio_eisa_h__ */ -- GitLab From bed445d41e0ca4b09ffbb82274fb79fb444030e7 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 16:50:07 +0000 Subject: [PATCH 420/465] [PATCH] Remove enable.h from rio (unused file) Signed-off-by: Linus Torvalds --- drivers/char/rio/enable.h | 48 --------------------------------------- 1 file changed, 48 deletions(-) delete mode 100644 drivers/char/rio/enable.h diff --git a/drivers/char/rio/enable.h b/drivers/char/rio/enable.h deleted file mode 100644 index e06673fa48c..00000000000 --- a/drivers/char/rio/enable.h +++ /dev/null @@ -1,48 +0,0 @@ -/**************************************************************************** - ******* ******* - ******* E N A B L E H E A D E R S - ******* ******* - **************************************************************************** - - Author : Ian Nandhra - Date : - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ - -#ifndef lint -#ifdef SCCS -static char *_rio_enable_h_sccs = "@(#)enable.h 1.1"; -#endif -#endif - - -#define ENABLE_LTT TRUE -#define ENABLE_LRT TRUE - - -/*********** end of file ***********/ -- GitLab From 85ae2f9cabbb029b0fce3fa8c641de7f0983e308 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 16:51:37 +0000 Subject: [PATCH 421/465] [PATCH] Remove formpkt.h from rio (unused file) Signed-off-by: Linus Torvalds --- drivers/char/rio/formpkt.h | 153 ------------------------------------- 1 file changed, 153 deletions(-) delete mode 100644 drivers/char/rio/formpkt.h diff --git a/drivers/char/rio/formpkt.h b/drivers/char/rio/formpkt.h deleted file mode 100644 index 3c7c91ace3e..00000000000 --- a/drivers/char/rio/formpkt.h +++ /dev/null @@ -1,153 +0,0 @@ - - -/**************************************************************************** - ******* ******* - ******* F O R M P A C K E T H E A D E R F I L E - ******* ******* - **************************************************************************** - - Author : Ian Nandhra - Date : - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ - -#ifndef _formpkt_h -#define _formpkt_h 1 - -#ifndef lint -#ifdef SCCS -static char *_rio_formpkt_h_sccs = "@(#)formpkt.h 1.1"; -#endif -#endif - -typedef struct FORM_BOOT_PKT_1 FORM_BOOT_PKT_1; -struct FORM_BOOT_PKT_1 { - ushort pkt_number; - ushort pkt_total; - ushort boot_top; -}; - -typedef struct FORM_BOOT_PKT_2 FORM_BOOT_PKT_2; -struct FORM_BOOT_PKT_2 { - ushort pkt_number; - char boot_data[10]; -}; - - -typedef struct FORM_ATTACH_RTA FORM_ATTACH_RTA; -struct FORM_ATTACH_RTA { - char cmd_code; - char booter_serial[4]; - char booter_link; - char bootee_serial[4]; - char bootee_link; -}; - - -typedef struct FORM_BOOT_ID FORM_BOOT_ID; -struct FORM_BOOT_ID { - char cmd_code; - char bootee_serial[4]; - char bootee_prod_id; - char bootee_link; -}; - - - -typedef struct FORM_ROUTE_1 FORM_ROUTE_1; -struct FORM_ROUTE_1 { - char cmd_code; - char pkt_number; - char total_in_sequence; - char unit_id; - char host_unit_id; -}; - -typedef struct FORM_ROUTE_2 FORM_ROUTE_2; -struct FORM_ROUTE_2 { - char cmd_code; - char pkt_number; - char total_in_sequence; - char route_data[9]; -}; - -typedef struct FORM_ROUTE_REQ FORM_ROUTE_REQ; -struct FORM_ROUTE_REQ { - char cmd_code; - char pkt_number; - char total_in_sequence; - char route_data[10]; -}; - - -typedef struct FORM_ERROR FORM_ERROR; -struct FORM_ERROR { - char cmd_code; - char error_code; - -}; - -typedef struct FORM_STATUS FORM_STATUS; -struct FORM_STATUS { - char cmd_code; - char status_code; - char last_packet_valid; - char tx_buffer; - char rx_buffer; - char port_status; - char phb_status; -}; - - -typedef struct FORM_LINK_STATUS FORM_LINK_STATUS; -struct FORM_LINK_STATUS { - char cmd_code; - char status_code; - char link_number; - ushort rx_errors; - ushort tx_errors; - ushort csum_errors; - ushort disconnects; -}; - - - -typedef struct FORM_PARTITION FORM_PARTITION; -struct FORM_PARTITION { - char cmd_code; - char status_code; - char port_number; - char tx_max; - char rx_max; - char rx_limit; -}; - - -#endif - -/*********** end of file ***********/ -- GitLab From b52a90dbe654c89bb9a50c90462a69931701428f Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 16:52:36 +0000 Subject: [PATCH 422/465] [PATCH] Remove hosthw.h from rio (unused file) Signed-off-by: Linus Torvalds --- drivers/char/rio/hosthw.h | 55 --------------------------------------- 1 file changed, 55 deletions(-) delete mode 100644 drivers/char/rio/hosthw.h diff --git a/drivers/char/rio/hosthw.h b/drivers/char/rio/hosthw.h deleted file mode 100644 index 6281fe47f4e..00000000000 --- a/drivers/char/rio/hosthw.h +++ /dev/null @@ -1,55 +0,0 @@ -/**************************************************************************** - ******* ******* - ******* H O S T H A R D W A R E - ******* ******* - **************************************************************************** - - Author : Ian Nandhra / Jeremy Rolls - Date : - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ - - -#ifndef lint -#ifdef SCCS_LABELS -static char *_rio_hosthw_h_sccs = "@(#)hosthw.h 1.2"; -#endif -#endif - -#define SET_OTHER_INTERRUPT ( (volatile u_short *) 0x7c80 ) -#define SET_EISA_INTERRUPT ( (volatile u_short *) 0x7ef0 ) - -#define EISA_HOST 0x30 -#define AT_HOST 0xa0 -#define MCA_HOST 0xb0 -#define PCI_HOST 0xd0 - -#define PRODUCT_MASK 0xf0 - - -/*********** end of file ***********/ -- GitLab From 67abbfe7deccf4a800fb246f9cecd6b7836ab150 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 16:53:38 +0000 Subject: [PATCH 423/465] [PATCH] Remove internal firmware building files from rio Signed-off-by: Linus Torvalds --- drivers/char/rio/lrt.h | 52 -------------------------------------- drivers/char/rio/ltt.h | 52 -------------------------------------- drivers/char/rio/lttwake.h | 50 ------------------------------------ 3 files changed, 154 deletions(-) delete mode 100644 drivers/char/rio/lrt.h delete mode 100644 drivers/char/rio/ltt.h delete mode 100644 drivers/char/rio/lttwake.h diff --git a/drivers/char/rio/lrt.h b/drivers/char/rio/lrt.h deleted file mode 100644 index b41764d7a22..00000000000 --- a/drivers/char/rio/lrt.h +++ /dev/null @@ -1,52 +0,0 @@ -/**************************************************************************** - ******* ******* - ******* L R T - ******* ******* - **************************************************************************** - - Author : Ian Nandhra / Jeremy Rolls - Date : - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ - -#ifndef lint -#ifdef SCCS_LABELS -static char *_rio_lrt_h_sccs = "@(#)lrt.h 1.1"; -#endif -#endif - - -#ifdef DCIRRUS -#define LRT_STACK (unsigned short) 600 -#else -#define LRT_STACK (ushort) 200 -#endif - - - -/*********** end of file ***********/ diff --git a/drivers/char/rio/ltt.h b/drivers/char/rio/ltt.h deleted file mode 100644 index ab04004d404..00000000000 --- a/drivers/char/rio/ltt.h +++ /dev/null @@ -1,52 +0,0 @@ -/**************************************************************************** - ******* ******* - ******* L T T - ******* ******* - **************************************************************************** - - Author : Ian Nandhra / Jeremy Rolls - Date : - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ - -#ifndef lint -#ifdef SCCS_LABELS -static char *_rio_ltt_h_sccs = "@(#)ltt.h 1.1"; -#endif -#endif - -#ifdef DCIRRUS -#define LTT_STACK (unsigned short) 600 -#else -#define LTT_STACK (ushort) 200 -#endif - - - - -/*********** end of file ***********/ diff --git a/drivers/char/rio/lttwake.h b/drivers/char/rio/lttwake.h deleted file mode 100644 index fdf0c1f250a..00000000000 --- a/drivers/char/rio/lttwake.h +++ /dev/null @@ -1,50 +0,0 @@ - - - -/**************************************************************************** - ******* ******* - ******* L T T W A K E U P H E A D E R - ******* ******* - **************************************************************************** - - Author : Ian Nandhra - Date : - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ - -#ifndef lint -#ifdef SCCS_LABELS -static char *_rio_lttwake_h_sccs = "@(#)lttwake.h 1.1"; -#endif -#endif - -#define LTT_WAKEUP_STACK 500 -#define LTT_WAKEUP_INTERVAL (int) (500 * MILLISECOND) - - -/*********** end of file ***********/ -- GitLab From 125ca8fb5bbab8ff726bb538120b553f30cd136f Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 16:54:30 +0000 Subject: [PATCH 424/465] [PATCH] Remove mca.h from rio driver (unused file) Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/rio/mca.h | 73 ------------------------------------------ 1 file changed, 73 deletions(-) delete mode 100644 drivers/char/rio/mca.h diff --git a/drivers/char/rio/mca.h b/drivers/char/rio/mca.h deleted file mode 100644 index d01e76be7a1..00000000000 --- a/drivers/char/rio/mca.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : mca.h -** SID : 1.2 -** Last Modified : 11/6/98 11:34:11 -** Retrieved : 11/6/98 11:34:21 -** -** ident @(#)mca.h 1.2 -** -** ----------------------------------------------------------------------------- -*/ - -#ifndef __rio_mca_h__ -#define __rio_mca_h__ - -#ifdef SCCS_LABELS -static char *_mca_h_sccs_ = "@(#)mca.h 1.2"; -#endif - -/* -** Micro Channel stuff -*/ - -#define McaMaxSlots 8 -#define McaSlotSelect 0x96 -#define McaSlotEnable 0x08 -#define McaIdLow 0x100 -#define McaIdHigh 0x101 -#define McaIrqEnable 0x102 -#define McaMemory 0x103 -#define McaRIOId 0x6a5c -#define McaIrq9 0x00 -#define McaIrq3 0x02 -#define McaIrq4 0x04 -#define McaIrq7 0x06 -#define McaIrq10 0x08 -#define McaIrq11 0x0A -#define McaIrq12 0x0C -#define McaIrq15 0x0E -#define McaIrqMask 0x0E -#define McaCardEnable 0x01 -#define McaAddress(X) (((X)&0xFF)<<16) - -#define McaTpFastLinks 0x40 -#define McaTpSlowLinks 0x00 -#define McaTpBootFromRam 0x01 -#define McaTpBootFromLink 0x00 -#define McaTpBusEnable 0x02 -#define McaTpBusDisable 0x00 - -#define RIO_MCA_DEFAULT_MODE SLOW_LINKS - -#endif /* __rio_mca_h__ */ -- GitLab From 009c4cb8aa0a32548c5aaec5b7b49b307fb6bf6a Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 16:56:16 +0000 Subject: [PATCH 425/465] [PATCH] Remove mesg.h from rio driver (unused file) Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/rio/mesg.h | 41 ----------------------------------------- 1 file changed, 41 deletions(-) delete mode 100644 drivers/char/rio/mesg.h diff --git a/drivers/char/rio/mesg.h b/drivers/char/rio/mesg.h deleted file mode 100644 index dd9be586ec6..00000000000 --- a/drivers/char/rio/mesg.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : mesg.h -** SID : 1.2 -** Last Modified : 11/6/98 11:34:12 -** Retrieved : 11/6/98 11:34:21 -** -** ident @(#)mesg.h 1.2 -** -** ----------------------------------------------------------------------------- -*/ - -#ifndef __rio_mesg_h__ -#define __rio_mesg_h__ - -#ifdef SCCS_LABELS -static char *_mesg_h_sccs_ = "@(#)mesg.h 1.2"; -#endif - - -#endif /* __rio_mesg_h__ */ -- GitLab From 735f88c62ec8df5a3ec730c1bbf47907d76b6f75 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 16:57:18 +0000 Subject: [PATCH 426/465] [PATCH] Remove poll.h from rio driver (unused file) Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/rio/poll.h | 73 ----------------------------------------- 1 file changed, 73 deletions(-) delete mode 100644 drivers/char/rio/poll.h diff --git a/drivers/char/rio/poll.h b/drivers/char/rio/poll.h deleted file mode 100644 index 9616ee4c6cd..00000000000 --- a/drivers/char/rio/poll.h +++ /dev/null @@ -1,73 +0,0 @@ -/**************************************************************************** - ******* ******* - ******* P O L L - ******* ******* - **************************************************************************** - - Author : Ian Nandhra / Jeremy Rolls - Date : - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ - -#ifndef _poll_h -#define _poll_h - -#ifndef lint -#ifdef SCCS_LABELS -static char *_rio_poll_h_sccs = "@(#)poll.h 1.2"; -#endif -#endif - - -#ifdef HOST -#define POLL_STACK 100 -#endif -#ifdef RTA -#define POLL_STACK 200 -#endif - -#define POLL_PERIOD (int) SECOND - -/* The various poll commands */ -#define POLL_POLL 0 /* We are connected and happy.. */ -#define POLL_INTRO 1 /* Introduction packet */ -#define POLL_TOPOLOGY 2 /* Topology update */ -#define POLL_ASSIGN 3 /* ID assign */ -#define POLL_FOAD 4 /* F*** Off And Die */ -#define POLL_LMD 5 /* Let Me Die */ -#define POLL_DYB 6 /* Die You Ba***** */ - -/* The way data fields are split up for POLL packets */ -#define POLL_HOST_SERIAL 2 /* Host who booted me */ -#define POLL_MY_SERIAL 6 /* My serial number */ -#define POLL_YOUR_ID 1 /* Your ID number */ -#define POLL_TOPOLOGY_FIELDS 2 /* Topology maps */ - -#endif - -/*********** end of file ***********/ -- GitLab From 0d336ceb1e35e12ec26936be421da99eeff0a3de Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 16:58:38 +0000 Subject: [PATCH 427/465] [PATCH] Remove proto.h from rio driver (unused file) Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/rio/proto.h | 244 --------------------------------------- 1 file changed, 244 deletions(-) delete mode 100644 drivers/char/rio/proto.h diff --git a/drivers/char/rio/proto.h b/drivers/char/rio/proto.h deleted file mode 100644 index f9a3376333e..00000000000 --- a/drivers/char/rio/proto.h +++ /dev/null @@ -1,244 +0,0 @@ -/* - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#ifndef _prototypes_h -#define _prototypes_h - - -/* -** boot.c -*/ -void init_boot(char *p, short stage); - -/* -** disconct.c -*/ -void kill_boot(LPB * link); -void disconnected(LPB * link); -short boot_3(LPB * link, PKT * pkt); -short send_3_pkt(LPB * link, PKT * pkt); - -/* -** error.c -*/ -void du_error(void); - -/* -** formpkt.c -*/ -ushort sum_it(PKT * pkt); -void form_rup_pkt(RUP * form_rup, PKT * pkt); -void form_poll_pkt(int type, LPB * link, int node); -void form_route_pkt(int type, PKT * pkt, LPB * link); - -/* -** idle.c -*/ -void idle(Process * idle_p); - -/* -** init.c -*/ -void general_init(void); -void mem_halt(int error); - -/* -** linkinit.c -*/ -void initlink(u_short number, LPB * link); -void runlink(LPB * link); - -/* -** list.c -*/ -PKT *get_free_start(void); -void put_free_start(PKT * pkt); - -#ifdef HOST -int can_remove_transmit(PKT ** pkt, PKT * pointer); -#endif - -#ifdef RTA -int spl7(void); -int spl0(void); -Q_BUF *get_free_q(void); -PKT *get_free_end(void); -int add_end(PKT * pkt, PHB * phb, int type); -unsigned short free_packets(PHB * phb, int type); -int can_remove_start(PKT ** pkt, PHB * phb, int type); -int can_add_start(PHB * phb, int type); -int can_add_end(PHB * phb, int type); -void put_free_end(PKT * pkt); -int remove_start(PKT ** pkt, PHB * phb, int type); -#endif - -/* -** Lrt.c -*/ -void lrt(Process * lrt_p, LPB * link); - -#ifdef RTA -void set_led_red(LPB * link); -#endif - -/* -** ltt.c -*/ -void ltt(Process * ltt_p, LPB * link, PHB * phb_ptr[]); -void send_poll(LPB * link); -void request_id(LPB * link); -void send_topology_update(LPB * link); -void send_topology(LPB * link); -void supply_id(LPB * link); - -#ifdef RTA -void redirect_queue(LPB * link, ushort flush); -int obtain_rup(int rup_number, PKT ** pkt_address, LPB * link); -#endif - -#ifdef TESTING_PERF -int consume_cpu(void); -#endif - -/* -** lttwake.c -*/ -#ifdef HOST -void ltt_wakeup(Process * ltt_wakeup_p); -#endif - -/* -** mapgen.c -*/ -void generate_id_map(short mapping, ROUTE_STR route[]); -void gen_map(int mapping, int looking_at, int come_from, ROUTE_STR route[], int link, int *ttl); -void adjust_ttl(int mapping, int looking_at, int come_from, ROUTE_STR route[], int link, int *ttl); -void init_sys_map(void); - -/* -** mmu.c -*/ -char *rio_malloc(unsigned int amount); -char *rio_calloc(unsigned int num, unsigned int size); -ERROR rio_mmu_init(uint total_mem); - -/* -** partn.c -*/ -void partition_tx(struct PHB *phb, u_short tx_size, u_short rx_size, u_short rx_limit); - -/* -** poll.c -*/ -void tx_poll(Process * tx_poll_p); - -/* -** process.c -*/ -int get_proc_space(Process ** pd, int **pws, int wssize); - -/* -** readrom.c -*/ -void read_serial_number(char *buf); - -/* -** rio.c -*/ -int main(void); - -/* -** route.c -*/ -void route_update(PKT * pkt, LPB * link); - -/* -** rtainit.c -*/ -#if defined(RTA) -void rta_init(ushort RtaType); -#endif /* defined(RTA) */ - -/* -** rupboot.c -*/ -void rup_boot(PKT * pkt, RUP * this_rup, LPB * link); - -#ifdef RTA -void kill_your_neighbour(int link_to_kill); -#endif - -/* -** rupcmd.c -*/ -void rup_command(PKT * pkt, struct RUP *this_rup, LPB * link); - -/* -** ruperr.c -*/ -void rup_error(PKT * pkt, RUP * this_rup, LPB * link); -void illegal_cmd(PKT * src_pkt); - -/* -** ruppoll.c -*/ -void rup_poll(PKT * pkt, RUP * this_rup, LPB * link); - -/* -** ruppower.c -*/ -void rup_power(PKT * pkt, RUP * this_rup, LPB * link); - -/* -** ruprm.c -*/ -void rup_route_map(PKT * pkt, RUP * this_rup, LPB * link); - -/* -** rupstat.c -*/ -void rup_status(PKT * pkt, RUP * this_rup, LPB * link); - -/* -** rupsync.c -*/ -void rup_sync(PKT * pkt); - -/* -** rxpkt.c -*/ -ERROR rx_pkt(PKT_ptr_ptr pkt_address, LPB * link); - -/* -** sendsts.c -*/ -void send_status(PKT * requesting_pkt, RUP * this_rup); - -/* -** serial.c -*/ -void assign_serial(char *ser_in, char *ser_out); -int cmp_serial(char *ser_1, char *ser_2); - -/* -** txpkt.c -*/ -ERROR tx_pkt(PKT * pkt, LPB * link); -short send_sync(LPB * link); - -#endif /* _prototypes_h */ -- GitLab From 8618751503b66f1c2b1f8e715ffc006fa91c2400 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 16:59:40 +0000 Subject: [PATCH 428/465] [PATCH] Remove file riolocks.h from rio driver (unused file) Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/rio/riolocks.h | 43 ------------------------------------- 1 file changed, 43 deletions(-) delete mode 100644 drivers/char/rio/riolocks.h diff --git a/drivers/char/rio/riolocks.h b/drivers/char/rio/riolocks.h deleted file mode 100644 index 0e0cdacebe0..00000000000 --- a/drivers/char/rio/riolocks.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : riolocks.h -** SID : 1.2 -** Last Modified : 11/6/98 11:34:13 -** Retrieved : 11/6/98 11:34:22 -** -** ident @(#)riolocks.h 1.2 -** -** ----------------------------------------------------------------------------- -*/ - -#ifndef __rio_riolocks_h__ -#define __rio_riolocks_h__ - -#ifdef SCCS_LABELS -static char *_riolocks_h_sccs_ = "@(#)riolocks.h 1.2"; -#endif - -#define LOCKB(lk) lockb(lk); -#define UNLOCKB(lk, oldspl) unlockb(lk, oldspl); - -#endif -- GitLab From 69da7f9a63679a8af67325c572a3bd1338c05df8 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 17:01:41 +0000 Subject: [PATCH 429/465] [PATCH] Remove riotime.h from rio driver (unused file) Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/rio/riotime.h | 63 -------------------------------------- 1 file changed, 63 deletions(-) delete mode 100644 drivers/char/rio/riotime.h diff --git a/drivers/char/rio/riotime.h b/drivers/char/rio/riotime.h deleted file mode 100644 index 35e01cd103d..00000000000 --- a/drivers/char/rio/riotime.h +++ /dev/null @@ -1,63 +0,0 @@ -/**************************************************************************** - ******* ******* - ******* T I M E - ******* ******* - **************************************************************************** - - Author : Jeremy Rolls - Date : - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ - -#ifndef _riotime_h -#define _riotime_h 1 - -#ifndef lint -#ifdef SCCS -static char *_rio_riotime_h_sccs = "@(#)riotime.h 1.1"; -#endif -#endif - -#define TWO_POWER_FIFTEEN (ushort)32768 -#define RioTime() riotime -#define RioTimeAfter(time1,time2) ((ushort)time1 - (ushort)time2) < TWO_POWER_FIFTEEN -#define RioTimePlus(time1,time2) ((ushort)time1 + (ushort)time2) - -/************************************** - * Convert a RIO tick (1/10th second) - * into transputer low priority ticks - *************************************/ -#define RioTimeToLow(time) (time*(100000 / 64)) -#define RioLowToTime(time) ((time*64)/100000) - -#define RIOTENTHSECOND (ushort)1 -#define RIOSECOND (ushort)(RIOTENTHSECOND * 10) -#endif - -/*********** end of file ***********/ -- GitLab From a09be029bbf8ceded3d9dd9715df70f1f8297b80 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 17:02:43 +0000 Subject: [PATCH 430/465] [PATCH] Remove file riowinif.h from rio driver (unused file) Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/rio/riowinif.h | 1329 ----------------------------------- 1 file changed, 1329 deletions(-) delete mode 100644 drivers/char/rio/riowinif.h diff --git a/drivers/char/rio/riowinif.h b/drivers/char/rio/riowinif.h deleted file mode 100644 index f802d7593b8..00000000000 --- a/drivers/char/rio/riowinif.h +++ /dev/null @@ -1,1329 +0,0 @@ -/************************************************************************/ -/* */ -/* Title : RIO Shared Memory Window Inteface */ -/* */ -/* Author : N.P.Vassallo */ -/* */ -/* Creation : 7th June 1999 */ -/* */ -/* Version : 1.0.0 */ -/* */ -/* Copyright : (c) Specialix International Ltd. 1999 * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * */ -/* Description : Prototypes, structures and definitions */ -/* describing RIO host card shared memory */ -/* window interface structures: */ -/* PARMMAP */ -/* RUP */ -/* PHB */ -/* LPB */ -/* PKT */ -/* */ -/************************************************************************/ - -/* History... - -1.0.0 07/06/99 NPV Creation. (based on PARMMAP.H) - -*/ - -#ifndef _riowinif_h /* If RIOWINDIF.H not already defined */ -#define _riowinif_h 1 - -/***************************************************************************** -******************************** ********************************* -******************************** General ********************************* -******************************** ********************************* -*****************************************************************************/ - -#define TPNULL ((_u16)(0x8000)) - -/***************************************************************************** -******************************** ******************************** -******************************** PARM_MAP ******************************** -******************************** ******************************** -*****************************************************************************/ - -/* The PARM_MAP structure defines global values relating to the Host Card / RTA - and is the main structure from which all other structures are referenced. */ - -typedef struct _PARM_MAP { - _u16 phb_ptr; /* 0x00 Pointer to the PHB array */ - _u16 phb_num_ptr; /* 0x02 Ptr to Number of PHB's */ - _u16 free_list; /* 0x04 Free List pointer */ - _u16 free_list_end; /* 0x06 Free List End pointer */ - _u16 q_free_list_ptr; /* 0x08 Ptr to Q_BUF variable */ - _u16 unit_id_ptr; /* 0x0A Unit Id */ - _u16 link_str_ptr; /* 0x0C Link Structure Array */ - _u16 bootloader_1; /* 0x0E 1st Stage Boot Loader */ - _u16 bootloader_2; /* 0x10 2nd Stage Boot Loader */ - _u16 port_route_map_ptr; /* 0x12 Port Route Map */ - _u16 route_ptr; /* 0x14 Route Map */ - _u16 map_present; /* 0x16 Route Map present */ - _u16 pkt_num; /* 0x18 Total number of packets */ - _u16 q_num; /* 0x1A Total number of Q packets */ - _u16 buffers_per_port; /* 0x1C Number of buffers per port */ - _u16 heap_size; /* 0x1E Initial size of heap */ - _u16 heap_left; /* 0x20 Current Heap left */ - _u16 error; /* 0x22 Error code */ - _u16 tx_max; /* 0x24 Max number of tx pkts per phb */ - _u16 rx_max; /* 0x26 Max number of rx pkts per phb */ - _u16 rx_limit; /* 0x28 For high / low watermarks */ - _u16 links; /* 0x2A Links to use */ - _u16 timer; /* 0x2C Interrupts per second */ - _u16 rups; /* 0x2E Pointer to the RUPs */ - _u16 max_phb; /* 0x30 Mostly for debugging */ - _u16 living; /* 0x32 Just increments!! */ - _u16 init_done; /* 0x34 Initialisation over */ - _u16 booting_link; /* 0x36 */ - _u16 idle_count; /* 0x38 Idle time counter */ - _u16 busy_count; /* 0x3A Busy counter */ - _u16 idle_control; /* 0x3C Control Idle Process */ - _u16 tx_intr; /* 0x3E TX interrupt pending */ - _u16 rx_intr; /* 0x40 RX interrupt pending */ - _u16 rup_intr; /* 0x42 RUP interrupt pending */ - -} PARM_MAP; - -/* Same thing again, but defined as offsets... */ - -#define PM_phb_ptr 0x00 /* 0x00 Pointer to the PHB array */ -#define PM_phb_num_ptr 0x02 /* 0x02 Ptr to Number of PHB's */ -#define PM_free_list 0x04 /* 0x04 Free List pointer */ -#define PM_free_list_end 0x06 /* 0x06 Free List End pointer */ -#define PM_q_free_list_ptr 0x08 /* 0x08 Ptr to Q_BUF variable */ -#define PM_unit_id_ptr 0x0A /* 0x0A Unit Id */ -#define PM_link_str_ptr 0x0C /* 0x0C Link Structure Array */ -#define PM_bootloader_1 0x0E /* 0x0E 1st Stage Boot Loader */ -#define PM_bootloader_2 0x10 /* 0x10 2nd Stage Boot Loader */ -#define PM_port_route_map_ptr 0x12 /* 0x12 Port Route Map */ -#define PM_route_ptr 0x14 /* 0x14 Route Map */ -#define PM_map_present 0x16 /* 0x16 Route Map present */ -#define PM_pkt_num 0x18 /* 0x18 Total number of packets */ -#define PM_q_num 0x1A /* 0x1A Total number of Q packets */ -#define PM_buffers_per_port 0x1C /* 0x1C Number of buffers per port */ -#define PM_heap_size 0x1E /* 0x1E Initial size of heap */ -#define PM_heap_left 0x20 /* 0x20 Current Heap left */ -#define PM_error 0x22 /* 0x22 Error code */ -#define PM_tx_max 0x24 /* 0x24 Max number of tx pkts per phb */ -#define PM_rx_max 0x26 /* 0x26 Max number of rx pkts per phb */ -#define PM_rx_limit 0x28 /* 0x28 For high / low watermarks */ -#define PM_links 0x2A /* 0x2A Links to use */ -#define PM_timer 0x2C /* 0x2C Interrupts per second */ -#define PM_rups 0x2E /* 0x2E Pointer to the RUPs */ -#define PM_max_phb 0x30 /* 0x30 Mostly for debugging */ -#define PM_living 0x32 /* 0x32 Just increments!! */ -#define PM_init_done 0x34 /* 0x34 Initialisation over */ -#define PM_booting_link 0x36 /* 0x36 */ -#define PM_idle_count 0x38 /* 0x38 Idle time counter */ -#define PM_busy_count 0x3A /* 0x3A Busy counter */ -#define PM_idle_control 0x3C /* 0x3C Control Idle Process */ -#define PM_tx_intr 0x3E /* 0x4E TX interrupt pending */ -#define PM_rx_intr 0x40 /* 0x40 RX interrupt pending */ -#define PM_rup_intr 0x42 /* 0x42 RUP interrupt pending */ -#define sizeof_PARM_MAP 0x44 /* structure size = 0x44 */ - -/* PARM_MAP.error definitions... */ -#define E_NO_ERROR 0x00 -#define E_PROCESS_NOT_INIT 0x01 -#define E_LINK_TIMEOUT 0x02 -#define E_NO_ROUTE 0x03 -#define E_CONFUSED 0x04 -#define E_HOME 0x05 -#define E_CSUM_FAIL 0x06 -#define E_DISCONNECTED 0x07 -#define E_BAD_RUP 0x08 -#define E_NO_VIRGIN 0x09 -#define E_BOOT_RUP_BUSY 0x10 -#define E_CHANALLOC 0x80 -#define E_POLL_ALLOC 0x81 -#define E_LTTWAKE 0x82 -#define E_LTT_ALLOC 0x83 -#define E_LRT_ALLOC 0x84 -#define E_CIRRUS 0x85 -#define E_MONITOR 0x86 -#define E_PHB_ALLOC 0x87 -#define E_ARRAY_ALLOC 0x88 -#define E_QBUF_ALLOC 0x89 -#define E_PKT_ALLOC 0x8a -#define E_GET_TX_Q_BUF 0x8b -#define E_GET_RX_Q_BUF 0x8c -#define E_MEM_OUT 0x8d -#define E_MMU_INIT 0x8e -#define E_LTT_INIT 0x8f -#define E_LRT_INIT 0x90 -#define E_LINK_RUN 0x91 -#define E_MONITOR_ALLOC 0x92 -#define E_MONITOR_INIT 0x93 -#define E_POLL_INIT 0x94 - -/* PARM_MAP.links definitions... */ -#define RIO_LINK_ENABLE 0x80FF - -/***************************************************************************** -********************************** *********************************** -********************************** RUP *********************************** -********************************** *********************************** -*****************************************************************************/ - -/* The RUP (Remote Unit Port) structure relates to the Remote Terminal Adapters - attached to the system and there is normally an array of MAX_RUPS (=16) structures - in a host card, defined by PARM_MAP->rup. */ - -typedef struct _RUP { - _u16 txpkt; /* 0x00 Outgoing packet */ - _u16 rxpkt; /* 0x02 ncoming packet */ - _u16 link; /* 0x04 Which link to send packet down ? */ - _u8 rup_dest_unit[2]; /* 0x06 Destination Unit */ - _u16 handshake; /* 0x08 Handshaking */ - _u16 timeout; /* 0x0A Timeout */ - _u16 status; /* 0x0C Status */ - _u16 txcontrol; /* 0x0E Transmit control */ - _u16 rxcontrol; /* 0x10 Receive control */ - -} RUP; - -/* Same thing again, but defined as offsets... */ - -#define RUP_txpkt 0x00 /* 0x00 Outgoing packet */ -#define RUP_rxpkt 0x02 /* 0x02 Incoming packet */ -#define RUP_link 0x04 /* 0x04 Which link to send packet down ? */ -#define RUP_rup_dest_unit 0x06 /* 0x06 Destination Unit */ -#define RUP_handshake 0x08 /* 0x08 Handshaking */ -#define RUP_timeout 0x0A /* 0x0A Timeout */ -#define RUP_status 0x0C /* 0x0C Status */ -#define RUP_txcontrol 0x0E /* 0x0E Transmit control */ -#define RUP_rxcontrol 0x10 /* 0x10 Receive control */ -#define sizeof_RUP 0x12 /* structure size = 0x12 */ - -#define MAX_RUP 16 - -/* RUP.txcontrol definitions... */ -#define TX_RUP_INACTIVE 0 /* Nothing to transmit */ -#define TX_PACKET_READY 1 /* Transmit packet ready */ -#define TX_LOCK_RUP 2 /* Transmit side locked */ - -/* RUP.txcontrol definitions... */ -#define RX_RUP_INACTIVE 0 /* Nothing received */ -#define RX_PACKET_READY 1 /* Packet received */ - -#define RUP_NO_OWNER 0xFF /* RUP not owned by any process */ - -/***************************************************************************** -********************************** *********************************** -********************************** PHB *********************************** -********************************** *********************************** -*****************************************************************************/ - -/* The PHB (Port Header Block) structure relates to the serial ports attached - to the system and there is normally an array of MAX_PHBS (=128) structures - in a host card, defined by PARM_MAP->phb_ptr and PARM_MAP->phb_num_ptr. */ - -typedef struct _PHB { - _u16 source; /* 0x00 Location of the PHB in the host card */ - _u16 handshake; /* 0x02 Used to manage receive packet flow control */ - _u16 status; /* 0x04 Internal port transmit/receive status */ - _u16 timeout; /* 0x06 Time period to wait for an ACK */ - _u16 link; /* 0x08 The host link associated with the PHB */ - _u16 destination; /* 0x0A Location of the remote port on the network */ - - _u16 tx_start; /* 0x0C first entry in the packet array for transmit packets */ - _u16 tx_end; /* 0x0E last entry in the packet array for transmit packets */ - _u16 tx_add; /* 0x10 position in the packet array for new transmit packets */ - _u16 tx_remove; /* 0x12 current position in the packet pointer array */ - - _u16 rx_start; /* 0x14 first entry in the packet array for receive packets */ - _u16 rx_end; /* 0x16 last entry in the packet array for receive packets */ - _u16 rx_add; /* 0x18 position in the packet array for new receive packets */ - _u16 rx_remove; /* 0x1A current position in the packet pointer array */ - -} PHB; - -/* Same thing again, but defined as offsets... */ - -#define PHB_source 0x00 /* 0x00 Location of the PHB in the host card */ -#define PHB_handshake 0x02 /* 0x02 Used to manage receive packet flow control */ -#define PHB_status 0x04 /* 0x04 Internal port transmit/receive status */ -#define PHB_timeout 0x06 /* 0x06 Time period to wait for an ACK */ -#define PHB_link 0x08 /* 0x08 The host link associated with the PHB */ -#define PHB_destination 0x0A /* 0x0A Location of the remote port on the network */ -#define PHB_tx_start 0x0C /* 0x0C first entry in the packet array for transmit packets */ -#define PHB_tx_end 0x0E /* 0x0E last entry in the packet array for transmit packets */ -#define PHB_tx_add 0x10 /* 0x10 position in the packet array for new transmit packets */ -#define PHB_tx_remove 0x12 /* 0x12 current position in the packet pointer array */ -#define PHB_rx_start 0x14 /* 0x14 first entry in the packet array for receive packets */ -#define PHB_rx_end 0x16 /* 0x16 last entry in the packet array for receive packets */ -#define PHB_rx_add 0x18 /* 0x18 position in the packet array for new receive packets */ -#define PHB_rx_remove 0x1A /* 0x1A current position in the packet pointer array */ -#define sizeof_PHB 0x1C /* structure size = 0x1C */ - -/* PHB.handshake definitions... */ -#define PHB_HANDSHAKE_SET 0x0001 /* Set by LRT */ -#define PHB_HANDSHAKE_RESET 0x0002 /* Set by ISR / driver */ -#define PHB_HANDSHAKE_FLAGS (PHB_HANDSHAKE_RESET|PHB_HANDSHAKE_SET) - /* Reset by ltt */ - -#define MAX_PHB 128 /* range 0-127 */ - -/***************************************************************************** -********************************** *********************************** -********************************** LPB *********************************** -********************************** *********************************** -*****************************************************************************/ - -/* The LPB (Link Parameter Block) structure relates to a RIO Network Link - and there is normally an array of MAX_LINKS (=4) structures in a host card, - defined by PARM_MAP->link_str_ptr. */ - -typedef struct _LPB { - _u16 link_number; /* 0x00 Link Number */ - _u16 in_ch; /* 0x02 Link In Channel */ - _u16 out_ch; /* 0x04 Link Out Channel */ - _u8 attached_serial[4]; /* 0x06 Attached serial number */ - _u8 attached_host_serial[4]; /* 0x0A Serial number of Host who booted other end */ - _u16 descheduled; /* 0x0E Currently Descheduled */ - _u16 state; /* 0x10 Current state */ - _u16 send_poll; /* 0x12 Send a Poll Packet */ - _u16 ltt_p; /* 0x14 Process Descriptor */ - _u16 lrt_p; /* 0x16 Process Descriptor */ - _u16 lrt_status; /* 0x18 Current lrt status */ - _u16 ltt_status; /* 0x1A Current ltt status */ - _u16 timeout; /* 0x1C Timeout value */ - _u16 topology; /* 0x1E Topology bits */ - _u16 mon_ltt; /* 0x20 */ - _u16 mon_lrt; /* 0x22 */ - _u16 num_pkts; /* 0x24 */ - _u16 add_packet_list; /* 0x26 Add packets to here */ - _u16 remove_packet_list; /* 0x28 Send packets from here */ - - _u16 lrt_fail_chan; /* 0x2A Lrt's failure channel */ - _u16 ltt_fail_chan; /* 0x2C Ltt's failure channel */ - - RUP rup; /* 0x2E RUP structure for HOST to driver comms */ - RUP link_rup; /* 0x40 RUP for the link (POLL, topology etc.) */ - _u16 attached_link; /* 0x52 Number of attached link */ - _u16 csum_errors; /* 0x54 csum errors */ - _u16 num_disconnects; /* 0x56 number of disconnects */ - _u16 num_sync_rcvd; /* 0x58 # sync's received */ - _u16 num_sync_rqst; /* 0x5A # sync requests */ - _u16 num_tx; /* 0x5C Num pkts sent */ - _u16 num_rx; /* 0x5E Num pkts received */ - _u16 module_attached; /* 0x60 Module tpyes of attached */ - _u16 led_timeout; /* 0x62 LED timeout */ - _u16 first_port; /* 0x64 First port to service */ - _u16 last_port; /* 0x66 Last port to service */ - -} LPB; - -/* Same thing again, but defined as offsets... */ - -#define LPB_link_number 0x00 /* 0x00 Link Number */ -#define LPB_in_ch 0x02 /* 0x02 Link In Channel */ -#define LPB_out_ch 0x04 /* 0x04 Link Out Channel */ -#define LPB_attached_serial 0x06 /* 0x06 Attached serial number */ -#define LPB_attached_host_serial 0x0A /* 0x0A Serial number of Host who booted other end */ -#define LPB_descheduled 0x0E /* 0x0E Currently Descheduled */ -#define LPB_state 0x10 /* 0x10 Current state */ -#define LPB_send_poll 0x12 /* 0x12 Send a Poll Packet */ -#define LPB_ltt_p 0x14 /* 0x14 Process Descriptor */ -#define LPB_lrt_p 0x16 /* 0x16 Process Descriptor */ -#define LPB_lrt_status 0x18 /* 0x18 Current lrt status */ -#define LPB_ltt_status 0x1A /* 0x1A Current ltt status */ -#define LPB_timeout 0x1C /* 0x1C Timeout value */ -#define LPB_topology 0x1E /* 0x1E Topology bits */ -#define LPB_mon_ltt 0x20 /* 0x20 */ -#define LPB_mon_lrt 0x22 /* 0x22 */ -#define LPB_num_pkts 0x24 /* 0x24 */ -#define LPB_add_packet_list 0x26 /* 0x26 Add packets to here */ -#define LPB_remove_packet_list 0x28 /* 0x28 Send packets from here */ -#define LPB_lrt_fail_chan 0x2A /* 0x2A Lrt's failure channel */ -#define LPB_ltt_fail_chan 0x2C /* 0x2C Ltt's failure channel */ -#define LPB_rup 0x2E /* 0x2E RUP structure for HOST to driver comms */ -#define LPB_link_rup 0x40 /* 0x40 RUP for the link (POLL, topology etc.) */ -#define LPB_attached_link 0x52 /* 0x52 Number of attached link */ -#define LPB_csum_errors 0x54 /* 0x54 csum errors */ -#define LPB_num_disconnects 0x56 /* 0x56 number of disconnects */ -#define LPB_num_sync_rcvd 0x58 /* 0x58 # sync's received */ -#define LPB_num_sync_rqst 0x5A /* 0x5A # sync requests */ -#define LPB_num_tx 0x5C /* 0x5C Num pkts sent */ -#define LPB_num_rx 0x5E /* 0x5E Num pkts received */ -#define LPB_module_attached 0x60 /* 0x60 Module tpyes of attached */ -#define LPB_led_timeout 0x62 /* 0x62 LED timeout */ -#define LPB_first_port 0x64 /* 0x64 First port to service */ -#define LPB_last_port 0x66 /* 0x66 Last port to service */ -#define sizeof_LPB 0x68 /* structure size = 0x68 */ - -#define LINKS_PER_UNIT 4 /* number of links from a host */ - -/***************************************************************************** -******************************** ******************************* -******************************** FREE_LIST ******************************* -******************************** ******************************* -*****************************************************************************/ - -/* Used to overlay packet headers when allocating/freeing packets from the free list */ - -typedef struct _FREE_LIST { - _u16 next; /* 0x00 offset of next list item */ - _u16 prev; /* 0x02 offset of previous list item */ - -} FREE_LIST; - -/* Same thing again, but defined as offsets... */ - -#define FL_next 0x00 /* 0x00 offset of next list item */ -#define FL_prev 0x02 /* 0x02 offset of previous list item */ - -/***************************************************************************** -********************************** *********************************** -********************************** PKT *********************************** -********************************** *********************************** -*****************************************************************************/ - -/* The PKT is the main unit of communication between Host Cards and RTAs across - the RIO network. */ - -#define PKT_MAX_DATA_LEN 72 /* Size of packet data */ - -typedef struct _PKT { - _u8 dest_unit; /* 0x00 Destination Unit Id */ - _u8 dest_port; /* 0x01 Destination Port */ - _u8 src_unit; /* 0x02 Source Unit Id */ - _u8 src_port; /* 0x03 Source Port */ - _u8 len; /* 0x04 Length (in bytes) of data field */ - _u8 control; /* 0x05 */ - _u8 data[PKT_MAX_DATA_LEN]; /* 0x06 Actual data */ - _u16 csum; /* 0x4E C-SUM */ - -} PKT; - -/* Same thing again, but defined as offsets... */ - -#define PKT_dest_unit 0x00 /* 0x00 Destination Unit Id */ -#define PKT_dest_port 0x01 /* 0x01 Destination Port */ -#define PKT_src_unit 0x02 /* 0x02 Source Unit Id */ -#define PKT_src_port 0x03 /* 0x03 Source Port */ -#define PKT_len 0x04 /* 0x04 Length (in bytes) of data field */ -#define PKT_control 0x05 /* 0x05 */ -#define PKT_data 0x06 /* 0x06 Actual data */ -#define PKT_csum 0x4E /* 0x4E C-SUM */ -#define sizeof_PKT 0x50 /* structure size = 0x50 */ - -/* PKT.len definitions... */ -#define PKT_CMD_BIT 0x80 -#define PKT_CMD_DATA 0x80 -#define PKT_LEN_MASK 0x7F - -/* PKT.control definitions... */ -#define PKT_ACK 0x40 -#define PKT_TGL 0x20 -#define DATA_WNDW 0x10 -#define PKT_TTL_MASK 0x0F -#define MAX_TTL 0x0F - -/***************************************************************************** -***************************** **************************** -***************************** Control Packets **************************** -***************************** **************************** -*****************************************************************************/ - -/* The following definitions and structures define the control packets sent - between the driver and RIO Ports, RTAs and Host Cards. */ - -#define PRE_EMPTIVE 0x80 /* Pre-emptive command (sent via port's RUP) */ - -/* "in-band" and "pre-emptive" port commands... */ -#define OPEN 0x00 /* Driver->RIO Open a port */ -#define CONFIG 0x01 /* Driver->RIO Configure a port */ -#define MOPEN 0x02 /* Driver->RIO Modem open (wait for DCD) */ -#define CLOSE 0x03 /* Driver->RIO Close a port */ -#define WFLUSH (0x04|PRE_EMPTIVE) /* Driver->RIO Write flush */ -#define RFLUSH (0x05|PRE_EMPTIVE) /* Driver->RIO Read flush */ -#define RESUME (0x06|PRE_EMPTIVE) /* Driver->RIO Behave as if XON received */ -#define SBREAK 0x07 /* Driver->RIO Start break */ -#define EBREAK 0x08 /* Driver->RIO End break */ -#define SUSPEND (0x09|PRE_EMPTIVE) /* Driver->RIO Behave as if XOFF received */ -#define FCLOSE (0x0A|PRE_EMPTIVE) /* Driver->RIO Force close */ -#define XPRINT 0x0B /* Driver->RIO Xprint packet */ -#define MBIS (0x0C|PRE_EMPTIVE) /* Driver->RIO Set modem lines */ -#define MBIC (0x0D|PRE_EMPTIVE) /* Driver->RIO Clear modem lines */ -#define MSET (0x0E|PRE_EMPTIVE) /* Driver->RIO Set modem lines */ -#define PCLOSE 0x0F /* Driver->RIO Pseudo close */ -#define MGET (0x10|PRE_EMPTIVE) /* Driver->RIO Force update of modem status */ -#define MEMDUMP (0x11|PRE_EMPTIVE) /* Driver->RIO DEBUG request for RTA memory */ -#define READ_REGISTER (0x12|PRE_EMPTIVE) /* Driver->RIO DEBUG read CD1400 register */ - -/* Remote Unit Port (RUP) packet definitions... (specified in PKT.dest_unit and PKT.src_unit) */ -#define SYNC_RUP 0xFF /* Download internal */ -#define COMMAND_RUP 0xFE /* Command ack/status */ -#define ERROR_RUP 0xFD /* Download internal */ -#define POLL_RUP 0xFC /* Download internal */ -#define BOOT_RUP 0xFB /* Used to boot RTAs */ -#define ROUTE_RUP 0xFA /* Used to specify routing/topology */ -#define STATUS_RUP 0xF9 /* Not used */ -#define POWER_RUP 0xF8 /* Download internal */ - -/* COMMAND_RUP definitions... */ -#define COMPLETE (0x20|PRE_EMPTIVE) /* RIO->Driver Command complete */ -#define BREAK_RECEIVED (0x21|PRE_EMPTIVE) /* RIO->Driver Break received */ -#define MODEM_STATUS (0x22|PRE_EMPTIVE) /* RIO->Driver Modem status change */ - -/* BOOT_RUP definitions... */ -#define BOOT_REQUEST 0x00 /* RIO->Driver Request for boot */ -#define BOOT_ABORT 0x01 /* Driver->RIO Abort a boot */ -#define BOOT_SEQUENCE 0x02 /* Driver->RIO Packet with firmware details */ -#define BOOT_COMPLETED 0x03 /* RIO->Driver Boot completed */ -#define IFOAD 0x2F /* Driver->RIO Shutdown/Reboot RTA (Fall Over And Die) */ -#define IDENTIFY 0x30 /* Driver->RIO Identify RTA */ -#define ZOMBIE 0x31 /* Driver->RIO Shutdown/Flash LEDs */ -#define UFOAD 0x32 /* Driver->RIO Shutdown/Reboot neighbouring RTA */ -#define IWAIT 0x33 /* Driver->RIO Pause booting process */ - -/* ROUTE_RUP definitions... */ -#define ROUTE_REQUEST 0x00 /* RIO->Driver Request an ID */ -#define ROUTE_FOAD 0x01 /* Driver->RIO Shutdown/reboot RTA */ -#define ROUTE_ALREADY 0x02 /* Driver->RIO Not used */ -#define ROUTE_USED 0x03 /* Driver->RIO Not used */ -#define ROUTE_ALLOCATE 0x04 /* Driver->RIO Allocate RTA RUP numbers */ -#define ROUTE_REQ_TOP 0x05 /* Driver->RIO Not used */ -#define ROUTE_TOPOLOGY 0x06 /* RIO->Driver Route/Topology status */ - -/***************************************************************************** -********************************** ********************************** -********************************** OPEN ********************************** -********************************** ********************************** -*****************************************************************************/ - -/* (Driver->RIO,in-band) - - Sent to open a port. - Structure of configuration info used with OPEN, CONFIG and MOPEN packets... */ - -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#define PKT_Cor1 (PKT_Data+1) /* Channel Option Register 1 */ -#define PKT_Cor2 (PKT_Data+2) /* Channel Option Register 2 */ -#define PKT_Cor4 (PKT_Data+3) /* Channel Option Register 4 */ -#define PKT_Cor5 (PKT_Data+4) /* Channel Option Register 5 */ -#define PKT_TxXon (PKT_Data+5) /* Transmit XON character */ -#define PKT_TxXoff (PKT_Data+6) /* Transmit XOFF character */ -#define PKT_RxXon (PKT_Data+7) /* Receive XON character */ -#define PKT_RxXoff (PKT_Data+8) /* Receive XOFF character */ -#define PKT_Lnext (PKT_Data+9) /* Lnext character */ -#define PKT_TxBaud (PKT_Data+10) /* Transmit baud rate */ -#define PKT_RxBaud (PKT_Data+11) /* Receive baud rate */ - -/* COR1 definitions... */ -#define COR1_PARITY 0xE0 /* Parity mask */ -#define COR1_NONE 0x00 /* No parity */ -#define COR1_SPACE 0x20 /* Space parity */ -#define COR1_EVEN 0x40 /* Even parity */ -#define COR1_MARK 0xA0 /* Mark parity */ -#define COR1_ODD 0xC0 /* Odd parity */ - -#define COR1_STOPBITS 0x0C /* Stop bits mask */ -#define COR1_STOP1 0x00 /* 1 stop bit */ -#define COR1_STOP1_5 0x04 /* 1.5 stop bits */ -#define COR1_STOP2 0x08 /* 2 stop bits */ - -#define COR1_DATABITS 0x03 /* Data bits mask */ -#define COR1_DATA5 0x00 /* 5 data bits */ -#define COR1_DATA6 0x01 /* 6 data bits */ -#define COR1_DATA7 0x02 /* 7 data bits */ -#define COR1_DATA8 0x03 /* 8 data bits */ - -/* COR2 definitions... */ -#define COR2_XON_TXFLOW 0x40 /* XON/XOFF Transmit Flow */ -#define COR2_XANY_TXFLOW 0xC0 /* XON/XANY Transmit Flow */ -#define COR2_HUPCL 0x20 /* Hang Up On Close */ -#define COR2_DSR_TXFLOW 0x08 /* DSR Transmit Flow Control */ -#define COR2_RTS_RXFLOW 0x04 /* RTS Receive Flow Control */ -#define COR2_CTS_TXFLOW 0x02 /* CTS Transmit Flow Control */ -#define COR2_XON_RXFLOW 0x01 /* XON/XOFF Receive Flow */ - -/* COR4 definition... */ -#define COR4_IGNCR 0x80 /* Discard received CR */ -#define COR4_ICRNL 0x40 /* Map received CR -> NL */ -#define COR4_INLCR 0x20 /* Map received NL -> CR */ -#define COR4_IGNBRK 0x10 /* Ignore Received Break */ -#define COR4_NBRKINT 0x08 /* No interrupt on rx Break */ -#define COR4_IGNPAR 0x04 /* ignore rx parity error chars */ -#define COR4_PARMRK 0x02 /* Mark rx parity error chars */ -#define COR4_RAISEMOD 0x01 /* Raise modem lines on !0 baud */ - -/* COR5 definitions... */ -#define COR5_ISTRIP 0x80 /* Strip input chars to 7 bits */ -#define COR5_LNE 0x40 /* Enable LNEXT processing */ -#define COR5_CMOE 0x20 /* Match good & error characters */ -#define COR5_TAB3 0x10 /* TAB3 mode */ -#define COR5_TSTATE_ON 0x08 /* Enable tbusy/tstop monitoring */ -#define COR5_TSTATE_OFF 0x04 /* Disable tbusy/tstop monitoring */ -#define COR5_ONLCR 0x02 /* NL -> CR NL on output */ -#define COR5_OCRNL 0x01 /* CR -> NL on output */ - -/* RxBaud and TxBaud definitions... */ -#define RIO_B0 0x00 /* RTS / DTR signals dropped */ -#define RIO_B50 0x01 /* 50 baud */ -#define RIO_B75 0x02 /* 75 baud */ -#define RIO_B110 0x03 /* 110 baud */ -#define RIO_B134 0x04 /* 134.5 baud */ -#define RIO_B150 0x05 /* 150 baud */ -#define RIO_B200 0x06 /* 200 baud */ -#define RIO_B300 0x07 /* 300 baud */ -#define RIO_B600 0x08 /* 600 baud */ -#define RIO_B1200 0x09 /* 1200 baud */ -#define RIO_B1800 0x0A /* 1800 baud */ -#define RIO_B2400 0x0B /* 2400 baud */ -#define RIO_B4800 0x0C /* 4800 baud */ -#define RIO_B9600 0x0D /* 9600 baud */ -#define RIO_B19200 0x0E /* 19200 baud */ -#define RIO_B38400 0x0F /* 38400 baud */ -#define RIO_B56000 0x10 /* 56000 baud */ -#define RIO_B57600 0x11 /* 57600 baud */ -#define RIO_B64000 0x12 /* 64000 baud */ -#define RIO_B115200 0x13 /* 115200 baud */ -#define RIO_B2000 0x14 /* 2000 baud */ - -/***************************************************************************** -********************************* ********************************* -********************************* CONFIG ********************************* -********************************* ********************************* -*****************************************************************************/ - -/* (Driver->RIO,in-band) - - CONFIG is sent from the driver to configure an already opened port. - Packet structure is same as OPEN. */ - -/***************************************************************************** -********************************* ********************************** -********************************* MOPEN ********************************** -********************************* ********************************** -*****************************************************************************/ - -/* (Driver->RIO,in-band) - - MOPEN is sent from the driver to open a port attached to a modem. (in-band) - Packet structure is same as OPEN. */ - -/***************************************************************************** -********************************* ********************************** -********************************* CLOSE ********************************** -********************************* ********************************** -*****************************************************************************/ - -/* (Driver->RIO,in-band) - - CLOSE is sent from the driver to close a previously opened port. - No parameters. - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#endif -/***************************************************************************** -********************************* ********************************* -********************************* WFLUSH ********************************* -********************************* ********************************* -*****************************************************************************/ - -/* (Driver->RIO,pre-emptive) - - WFLUSH is sent pre-emptively from the driver to flush the write buffers and - packets of a port. (pre-emptive) - - WFLUSH is also sent in-band from the driver to a port as a marker to end - write flushing previously started by a pre-emptive WFLUSH packet. (in-band) - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#endif -#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ - -/***************************************************************************** -********************************* ********************************* -********************************* RFLUSH ********************************* -********************************* ********************************* -*****************************************************************************/ - -/* (Driver->RIO,pre-emptive) - - RFLUSH is sent pre-emptively from the driver to flush the read buffers and - packets of a port. - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ -#endif - -/***************************************************************************** -********************************* ********************************* -********************************* RESUME ********************************* -********************************* ********************************* -*****************************************************************************/ - -/* (Driver->RIO,pre-emptive) - - RESUME is sent pre-emptively from the driver to cause a port to resume - transmission of data if blocked by XOFF. (as if XON had been received) - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ -#endif - -/***************************************************************************** -********************************* ********************************* -********************************* SBREAK ********************************* -********************************* ********************************* -*****************************************************************************/ - -/* (Driver->RIO,in-band) - - SBREAK is sent in-band from the driver to a port to suspend data and start - break signal transmission. - - If the break delay is 0, the break signal will be acknowledged with a - RUP_COMMAND, COMPLETE packet and continue until an EBREAK packet is received. - - Otherwise, there is no acknowledgement and the break signal will last for the - specified number of mS. - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#endif -#define PKT_BreakDelay (PKT_Data+1) /* Break delay in mS */ - -/***************************************************************************** -********************************* ********************************* -********************************* EBREAK ********************************* -********************************* ********************************* -*****************************************************************************/ - -/* (Driver->RIO,in-band) - - EBREAK is sent in-band from the driver to a port to stop transmission of a - break signal. - - No parameters. */ - -/***************************************************************************** -********************************* ******************************** -********************************* SUSPEND ******************************** -********************************* ******************************** -*****************************************************************************/ - -/* (Driver->RIO,pre-emptive) - - SUSPEND is sent pre-emptively from the driver to cause a port to suspend - transmission of data. (as if XOFF had been received) - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ -#endif - -/***************************************************************************** -********************************* ********************************* -********************************* FCLOSE ********************************* -********************************* ********************************* -*****************************************************************************/ - -/* (Driver->RIO,pre-emptive) - - FCLOSE is sent pre-emptively from the driver to force close a port. - A force close flushes receive and transmit queues, and also lowers all output - modem signals if the COR5_HUPCL (Hang Up On Close) flag is set. - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ -#endif - -/***************************************************************************** -********************************* ********************************* -********************************* XPRINT ********************************* -********************************* ********************************* -*****************************************************************************/ - -/* (Driver->RIO,in-band) - - XPRINT is sent as a normal I/O data packet except that the PKT_CMD_BIT of - the "len" field is set, and the first "data" byte is XPRINT. - - The I/O data in the XPRINT packet will contain the following: - - Transparent Print Start Sequence - - Transparent Print Data - - Transparent Print Stop Sequence. - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ -#endif - -/***************************************************************************** -********************************** ********************************** -********************************** MBIS ********************************** -********************************** ********************************** -*****************************************************************************/ - -/* (Driver->RIO,pre-emptive) - - MBIS is sent pre-emptively from the driver to set a port's modem signals. - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ -#endif -#define PKT_ModemSet (PKT_Data+4) /* Modem set signals mask */ - -/* ModemSet definitions... */ -#define MBIS_RTS 0x01 /* RTS modem signal */ -#define MBIS_DTR 0x02 /* DTR modem signal */ - -/***************************************************************************** -********************************** ********************************** -********************************** MBIC ********************************** -********************************** ********************************** -*****************************************************************************/ - -/* (Driver->RIO,pre-emptive) - - MBIC is sent pre-emptively from the driver to clear a port's modem signals. - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ -#endif - -#define PKT_ModemClear (PKT_Data+4) /* Modem clear signals mask */ - -/* ModemClear definitions... */ -#define MBIC_RTS 0x01 /* RTS modem signal */ -#define MBIC_DTR 0x02 /* DTR modem signal */ - -/***************************************************************************** -********************************** ********************************** -********************************** MSET ********************************** -********************************** ********************************** -*****************************************************************************/ - -/* (Driver->RIO,pre-emptive) - - MSET is sent pre-emptively from the driver to set/clear a port's modem signals. */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ -#endif - -#define PKT_ModemSet (PKT_Data+4) /* Modem set signals mask */ - -/* ModemSet definitions... */ -#define MSET_RTS 0x01 /* RTS modem signal */ -#define MSET_DTR 0x02 /* DTR modem signal */ - -/***************************************************************************** -********************************* ********************************* -********************************* PCLOSE ********************************* -********************************* ********************************* -*****************************************************************************/ - -/* (Driver->RIO,in-band) - - PCLOSE is sent from the driver to pseudo close a previously opened port. - - The port will close when all data has been sent/received, however, the - port's transmit / receive and modem signals will be left enabled and the - port marked internally as Pseudo Closed. */ - -#define PKT_Cmd (PKT_Data+0) /* Command code */ - -/***************************************************************************** -********************************** ********************************** -********************************** MGET ********************************** -********************************** ********************************** -*****************************************************************************/ - -/* (Driver->RIO,pre-emptive) - - MGET is sent pre-emptively from the driver to request the port's current modem signals. */ - -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ - -/***************************************************************************** -********************************* ******************************** -********************************* MEMDUMP ******************************** -********************************* ******************************** -*****************************************************************************/ - -/* (Driver->RIO,pre-emptive) - - MEMDUMP is sent pre-emptively from the driver to request a dump of 32 bytes - of the specified port's RTA address space. - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#endif -#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ -#define PKT_SubCmd (PKT_Data+5) /* Sub Command */ -#define PKT_Address (PKT_Data+6) /* Requested address */ - -/***************************************************************************** -****************************** ***************************** -****************************** READ_REGISTER ***************************** -****************************** ***************************** -*****************************************************************************/ - -/* (Driver->RIO,pre-emptive) - - READ_REGISTER is sent pre-emptively from the driver to request the contents - of the CD1400 register specified in address. - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#endif -#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ -#define PKT_SubCmd (PKT_Data+5) /* Sub Command */ -#define PKT_Address (PKT_Data+6) /* Requested address */ - -/***************************************************************************** -************************ ************************** -************************ COMMAND_RUP - COMPLETE ************************** -************************ ************************** -*****************************************************************************/ - -/* (RIO->Driver,pre-emptive) - - COMMAND_RUP - COMPLETE is sent in response to all port I/O control command - packets, except MEMDUMP and READ_REGISTER. - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#endif -#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ -#define PKT_Cmd2 (PKT_Data+2) /* Command code copy */ -#define PKT_ModemStatus (PKT_Data+3) /* Modem signal status */ -#define PKT_PortStatus (PKT_Data+4) /* Port signal status */ -#define PKT_SubCmd (PKT_Data+5) /* Sub Command */ - -/* ModemStatus definitions... */ -#define MODEM_DSR 0x80 /* Data Set Ready modem state */ -#define MODEM_CTS 0x40 /* Clear To Send modem state */ -#define MODEM_RI 0x20 /* Ring Indicate modem state */ -#define MODEM_CD 0x10 /* Carrier Detect modem state */ -#define MODEM_TSTOP 0x08 /* Transmit Stopped state */ -#define MODEM_TEMPTY 0x04 /* Transmit Empty state */ -#define MODEM_DTR 0x02 /* DTR modem output state */ -#define MODEM_RTS 0x01 /* RTS modem output state */ - -/* PortStatus definitions... */ -#define PORT_ISOPEN 0x01 /* Port open ? */ -#define PORT_HUPCL 0x02 /* Hangup on close? */ -#define PORT_MOPENPEND 0x04 /* Modem open pending */ -#define PORT_ISPARALLEL 0x08 /* Parallel port */ -#define PORT_BREAK 0x10 /* Port on break */ -#define PORT_STATUSPEND 0020 /* Status packet pending */ -#define PORT_BREAKPEND 0x40 /* Break packet pending */ -#define PORT_MODEMPEND 0x80 /* Modem status packet pending */ - -/***************************************************************************** -************************ ************************** -************************ COMMAND_RUP - COMPLETE ************************** -************************ ************************** -*****************************************************************************/ - -/* (RIO->Driver,pre-emptive) - - COMMAND_RUP - COMPLETE is sent in response to all port I/O control command - packets, except MEMDUMP and READ_REGISTER. - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ -#define PKT_Cmd2 (PKT_Data+2) /* Command code copy */ -#endif -#define PKT_ModemStatus (PKT_Data+3) /* Modem signal status */ -#define PKT_PortStatus (PKT_Data+4) /* Port signal status */ -#if 0 -#define PKT_SubCmd (PKT_Data+5) /* Sub Command */ -#endif - -/* ModemStatus definitions... */ -#define MODEM_DSR 0x80 /* Data Set Ready modem state */ -#define MODEM_CTS 0x40 /* Clear To Send modem state */ -#define MODEM_RI 0x20 /* Ring Indicate modem state */ -#define MODEM_CD 0x10 /* Carrier Detect modem state */ -#define MODEM_TSTOP 0x08 /* Transmit Stopped state */ -#define MODEM_TEMPTY 0x04 /* Transmit Empty state */ -#define MODEM_DTR 0x02 /* DTR modem output state */ -#define MODEM_RTS 0x01 /* RTS modem output state */ - -/* PortStatus definitions... */ -#define PORT_ISOPEN 0x01 /* Port open ? */ -#define PORT_HUPCL 0x02 /* Hangup on close? */ -#define PORT_MOPENPEND 0x04 /* Modem open pending */ -#define PORT_ISPARALLEL 0x08 /* Parallel port */ -#define PORT_BREAK 0x10 /* Port on break */ -#define PORT_STATUSPEND 0020 /* Status packet pending */ -#define PORT_BREAKPEND 0x40 /* Break packet pending */ -#define PORT_MODEMPEND 0x80 /* Modem status packet pending */ - -/***************************************************************************** -******************** ******************** -******************** COMMAND_RUP - COMPLETE - MEMDUMP ******************** -******************** ******************** -*****************************************************************************/ - -/* (RIO->Driver,pre-emptive) - - COMMAND_RUP - COMPLETE - MEMDUMP is sent as an acknowledgement for a MEMDUMP - port I/O control command packet. - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ -#define PKT_Cmd2 (PKT_Data+2) /* Command code copy */ -#define PKT_ModemStatus (PKT_Data+3) /* Modem signal status */ -#define PKT_PortStatus (PKT_Data+4) /* Port signal status */ -#define PKT_SubCmd (PKT_Data+5) /* Sub Command */ -#define PKT_Address (PKT_Data+6) /* Requested address */ -#endif -#define PKT_Dump (PKT_Data+8) /* 32bytes of requested dump data */ - -/***************************************************************************** -***************** ***************** -***************** COMMAND_RUP - COMPLETE - READ_REGISTER ***************** -***************** ***************** -*****************************************************************************/ - -/* (RIO->Driver,pre-emptive) - - COMMAND_RUP - COMPLETE - READ_REGISTER is sent as an acknowledgement for a - READ_REGISTER port I/O control command packet. - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /*Command code */ -#define PKT_PhbNum (PKT_Data+1) /*Port number wrt RTA */ -#define PKT_Cmd2 (PKT_Data+2) /* Command code copy */ -#endif -#define PKT_RegisterValue (PKT_Data+3) /* Modem signal status */ -#if 0 -#define PKT_PortStatus (PKT_Data+4) /* Port signal status */ -#define PKT_SubCmd (PKT_Data+5) /* Sub Command */ -#endif - -/***************************************************************************** -********************* *********************** -********************* COMMAND_RUP - BREAK_RECEIVED *********************** -********************* *********************** -*****************************************************************************/ - -/* (RIO->Driver,pre-emptive) - - COMMAND_RUP - BREAK_RECEIVED packets are sent when the port detects a receive BREAK signal. - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ -#define PKT_Cmd2 (PKT_Data+2) /* Command code copy */ -#endif - -/***************************************************************************** -********************* ************************* -********************* COMMAND_RUP - MODEM_STATUS ************************* -********************* ************************* -*****************************************************************************/ - -/* (RIO->Driver,pre-emptive) - - COMMAND_RUP - MODEM_STATUS packets are sent whenever the port detects a - change in the input modem signal states. - - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ -#define PKT_Cmd2 (PKT_Data+2) /* Command code copy */ -#define PKT_ModemStatus (PKT_Data+3) /* Modem signal status */ -#endif - -/***************************************************************************** -************************ ************************* -************************ BOOT_RUP - BOOT_REQUEST ************************* -************************ ************************* -*****************************************************************************/ - -/* (RIO->Driver,pre-emptive) - - BOOT_RUP - BOOT_REQUEST packets are sent to the Driver from RIO to request - firmware code to load onto attached RTAs. - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#endif - -/***************************************************************************** -************************ ************************ -************************ BOOT_RUP - BOOT_SEQUENCE ************************ -************************ ************************ -*****************************************************************************/ - -/* (Driver->RIO,pre-emptive) - - BOOT_RUP - BOOT_SEQUENCE packets are sent from the Driver to RIO in response - to a BOOT_RUP - BOOT_REQUEST packet. - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#endif -#define PKT_NumPackets (PKT_Data+2) /* Packets required to load firmware */ -#define PKT_LoadBase (PKT_Data+4) /* RTA firmware load address */ -#define PKT_CodeSize (PKT_Data+6) /* Size of firmware in bytes */ -#define PKT_CmdString (PKT_Data+8) /* Command string */ - -/***************************************************************************** -************************ *********************** -************************ BOOT_RUP - BOOT_COMPLETED *********************** -************************ *********************** -*****************************************************************************/ - -/* (RIO->Driver,pre-emptive) - - BOOT_RUP - BOOT_COMPLETE is sent to the Driver from RIO when downloading of - RTA firmware has completed. - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#endif -#define PKT_LinkNumber (PKT_Data+1) /* Link number RTA booted on */ -#define PKT_SerialNumber (PKT_Data+2) /* 4 byte serial number */ - -/***************************************************************************** -************************ *********************** -************************ BOOT_RUP - Packet Request *********************** -************************ *********************** -*****************************************************************************/ - -/* (RIO->Driver,pre-emptive) - - BOOT_RUP packet without the PKT_CMD_BIT set in the PKT->len field is sent - from RIO to the Driver as a request for a firmware boot packet. */ - -#define PKT_SequenceNumber (PKT_Data+0) /* Packet sequence number */ - -/***************************************************************************** -*********************** *********************** -*********************** BOOT_RUP - Packet Response *********************** -*********************** *********************** -*****************************************************************************/ - -/* (Driver->RIO,pre-emptive) - - In response to a BOOT_RUP boot packet request, the driver fills out the response - packet with the 70 bytes of the requested sequence. - */ -#if 0 -#define PKT_SequenceNumber (PKT_Data+0) /* Packet sequence number */ -#endif -#define PKT_FirmwarePacket (PKT_Data+2) /* Firmware packet */ - -/***************************************************************************** -**************************** **************************** -**************************** BOOT_RUP - IFOAD **************************** -**************************** **************************** -*****************************************************************************/ - -/* (Driver->RIO,pre-emptive) - - BOOT_RUP - IFOAD packets are sent from the Driver to an RTA to cause the - RTA to shut down and reboot. - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#endif -#define PKT_IfoadId1 (PKT_Data+2) /* IFOAD Id 1 */ -#define PKT_IfoadId2 (PKT_Data+3) /* IFOAD Id 2 */ - -#define IFOADID1 0xAD -#define IFOADID2 0xF0 - -/***************************************************************************** -************************** *************************** -************************** BOOT_RUP - IDENTIFY *************************** -************************** *************************** -*****************************************************************************/ - -/* (Driver->RIO,pre-emptive) - - BOOT_RUP - IDENTIFY packets are sent from the Driver to an RTA to cause the - RTA to flash its LEDs for a period of time. - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#endif -#define PKT_IdentifyId (PKT_Data+2) /* defines pattern to flash */ - -/***************************************************************************** -**************************** *************************** -**************************** BOOT_RUP - ZOMBIE *************************** -**************************** *************************** -*****************************************************************************/ - -/* (Driver->RIO,pre-emptive) - - BOOT_RUP - ZOMBIE packets are sent from the Driver to an RTA to cause the - RTA to shut down and flash it's LEDs. - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#endif -#define PKT_ZombieId1 (PKT_Data+2) /* ZOMBIE Id 1 */ -#define PKT_ZombieId2 (PKT_Data+3) /* ZOMBIE Id 2 */ - -#define ZOMBIEID1 0x52 -#define ZOMBIEID2 0x21 - -/***************************************************************************** -**************************** **************************** -**************************** BOOT_RUP - UFOAD **************************** -**************************** **************************** -*****************************************************************************/ - -/* (Driver->RIO,pre-emptive) - - BOOT_RUP - UFOAD packets are sent from the Driver to an RTA to cause the RTA - to ask it's neighbouring RTA to shut down and reboot. - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#define PKT_LinkNumber (PKT_Data+1) /* Link number of RTA to UFOAD */ -#endif -#define PKT_UfoadId1 (PKT_Data+2) /* UFOAD Id 1 */ -#define PKT_UfoadId2 (PKT_Data+3) /* UFOAD Id 2 */ - -#define UFOADID1 0x1E -#define UFOADID2 0x0D - -/***************************************************************************** -**************************** **************************** -**************************** BOOT_RUP - IWAIT **************************** -**************************** **************************** -*****************************************************************************/ - -/* (Driver->RIO,pre-emptive) - - BOOT_RUP - IWAIT packets are sent from the Driver to an RTA to cause the RTA - to pause booting on the specified link for 30 seconds. - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#define PKT_LinkNumber (PKT_Data+1) /* Link number of RTA to UFOAD */ -#endif -#define PKT_IwaitId1 (PKT_Data+2) /* IWAIT Id 1 */ -#define PKT_IwaitId2 (PKT_Data+3) /* IWAIT Id 2 */ - -#define IWAITID1 0xDE -#define IWAITID2 0xB1 - -/***************************************************************************** -************************ *********************** -************************ ROUTE_RUP - ROUTE_REQUEST *********************** -************************ *********************** -*****************************************************************************/ - -/* (RIO->Driver,pre-emptive) - - ROUTE_RUP - ROUTE_REQUEST packets are sent from a newly booted or connected - RTA to a Driver to request an ID (RUP or unit number). - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#endif -#define PKT_SerialNumber (PKT_Data+2) /* 4 byte serial number */ -#define PKT_ModuleTypes (PKT_Data+6) /* RTA Module types */ - -/* ModuleTypes definitions... */ -#define MOD_BLANK 0x0F /* Blank plate attached */ -#define MOD_RS232DB25 0x00 /* RS232 DB25 connector */ -#define MOD_RS232RJ45 0x01 /* RS232 RJ45 connector */ -#define MOD_RS422DB25 0x02 /* RS422 DB25 connector */ -#define MOD_RS485DB25 0x03 /* RS485 DB25 connector */ -#define MOD_PARALLEL 0x04 /* Centronics parallel */ - -#define MOD2 0x08 /* Set to indicate Rev2 module */ - -/***************************************************************************** -************************* ************************* -************************* ROUTE_RUP - ROUTE_FOAD ************************* -************************* ************************* -*****************************************************************************/ - -/* (Driver->RIO,pre-emptive) - - ROUTE_RUP - ROUTE_FOAD packet is sent as a response to a ROUTE_RUP - ROUTE_REQUEST - packet to cause the RTA to "Fall Over And Die"., i.e. shutdown and reboot. - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#endif -#define PKT_RouteCmdString (PKT_Data+2) /* Command string */ - -/***************************************************************************** -*********************** *********************** -*********************** ROUTE_RUP - ROUTE_ALLOCATE *********************** -*********************** *********************** -*****************************************************************************/ - -/* (Driver->RIO,pre-emptive) - - ROUTE_RUP - ROUTE_ALLOCATE packet is sent as a response to a ROUTE_RUP - ROUTE_REQUEST - packet to allocate the RTA's Id number (RUP number 1..16) - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#endif -#define PKT_IdNum (PKT_Data+1) /* RUP number for ports 1..8 */ -#if 0 -#define PKT_RouteCmdString (PKT_Data+2) /* Command string */ -#endif -#define PKT_IdNum2 (PKT_Data+0x17) /* RUP number for ports 9..16 */ - -/***************************************************************************** -*********************** *********************** -*********************** ROUTE_RUP - ROUTE_TOPOLOGY *********************** -*********************** *********************** -*****************************************************************************/ - -/* (RIO->Driver,pre-emptive) - - ROUTE_RUP - ROUTE_TOPOLOGY packet is sent to inform the driver of an RTA's - current link status. - */ -#if 0 -#define PKT_Cmd (PKT_Data+0) /* Command code */ -#endif -#define PKT_Link1Rup (PKT_Data+2) /* Link 1 RUP number */ -#define PKT_Link1Link (PKT_Data+3) /* Link 1 link number */ -#define PKT_Link2Rup (PKT_Data+4) /* Link 2 RUP number */ -#define PKT_Link2Link (PKT_Data+5) /* Link 2 link number */ -#define PKT_Link3Rup (PKT_Data+6) /* Link 3 RUP number */ -#define PKT_Link3Link (PKT_Data+7) /* Link 3 link number */ -#define PKT_Link4Rup (PKT_Data+8) /* Link 4 RUP number */ -#define PKT_Link4Link (PKT_Data+9) /* Link 4 link number */ -#define PKT_RtaVpdProm (PKT_Data+10) /* 32 bytes of RTA VPD PROM Contents */ - -#endif /* _sxwinif_h */ - -/* End of RIOWINIF.H */ -- GitLab From 169da21f403adf6698ef9bbb759e27c1f496b2b5 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 17:03:49 +0000 Subject: [PATCH 431/465] [PATCH] Remove file riscos.h from rio driver (unused file) Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/rio/riscos.h | 63 --------------------------------------- 1 file changed, 63 deletions(-) delete mode 100644 drivers/char/rio/riscos.h diff --git a/drivers/char/rio/riscos.h b/drivers/char/rio/riscos.h deleted file mode 100644 index 60d66d0056a..00000000000 --- a/drivers/char/rio/riscos.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** Perle Specialix driver for Linux -** Ported from existing RIO Driver for SCO sources. - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -** -** Module : riscos.h -** SID : 1.2 -** Last Modified : 11/6/98 11:34:19 -** Retrieved : 11/6/98 11:34:22 -** -** ident @(#)riscos.h 1.2 -** -** ----------------------------------------------------------------------------- -*/ - -#ifndef __rio_riscos_h__ -#define __rio_riscos_h__ - -#ifdef SCCS_LABELS -static char *_riscos_h_sccs_ = "@(#)riscos.h 1.2"; -#endif - -/* -** This module used to define all those little itsy bits required for RISC/OS -** now it's full of null macros. -*/ - -/* -** RBYTE reads a byte from a location. -** RWORD reads a word from a location. -** WBYTE writes a byte to a location. -** WWORD writes a word to a location. -** RINDW reads a word through a pointer. -** WINDW writes a word through a pointer. -** RIOSWAB swaps the two bytes of a word, if needed. -*/ - -#define RIOSWAB(N) (N) -#define WBYTE(A,V) (A)=(uchar)(V) -#define WWORD(A,V) (A)=(ushort)(V) -#define RBYTE(A) (uchar)(A) -#define RWORD(A) (ushort)(A) -#define RINDW(A) (*(ushort *)(A)) -#define WINDW(A,V) (*(ushort *)(A)=(ushort)(V)) - -#endif /* __rio_riscos_h__ */ -- GitLab From 3918276ce5e3f5473428f307194fef422c0b12b8 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 17:05:55 +0000 Subject: [PATCH 432/465] [PATCH] Remove rtahw.h from rio driver (unused file) Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/rio/rtahw.h | 75 ---------------------------------------- 1 file changed, 75 deletions(-) delete mode 100644 drivers/char/rio/rtahw.h diff --git a/drivers/char/rio/rtahw.h b/drivers/char/rio/rtahw.h deleted file mode 100644 index e6c2cdfd3a1..00000000000 --- a/drivers/char/rio/rtahw.h +++ /dev/null @@ -1,75 +0,0 @@ - -/**************************************************************************** - ******* ******* - ******* R T A H A R D W A R E - ******* ******* - **************************************************************************** - - Author : Ian Nandhra - Date : - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ - -#ifndef lint -#ifdef SCCS_LABELS -static char *_rio_rtahw_h_sccs = "@(#)rtahw.h 1.5"; -#endif -#endif - -#define WATCHDOG_ADDR ((unsigned short *)0x7a00) -#define RTA_LED_ADDR ((unsigned short *)0x7c00) -#define SERIALNUM_ADDR ((unsigned char *)0x7809) -#define LATCH_ADDR ((unsigned char *)0x7800) - -/* -** Here we define where the cd1400 chips are in memory. -*/ -#define CD1400_ONE_ADDR (0x7300) -#define CD1400_TWO_ADDR (0x7200) -#define CD1400_THREE_ADDR (0x7100) -#define CD1400_FOUR_ADDR (0x7000) - -/* -** Define the different types of modules we can have -*/ -enum module { - MOD_BLANK = 0x0f, /* Blank plate attached */ - MOD_RS232DB25 = 0x00, /* RS232 DB25 connector */ - MOD_RS232RJ45 = 0x01, /* RS232 RJ45 connector */ - MOD_RS422DB25 = 0x02, /* RS422 DB25 connector */ - MOD_RS485DB25 = 0x03, /* RS485 DB25 connector */ - MOD_PARALLEL = 0x04 /* Centronics parallel */ -}; - -#define TYPE_HOST 0 -#define TYPE_RTA8 1 -#define TYPE_RTA16 2 - -#define WATCH_DOG WATCHDOG_ADDR - -/*********** end of file ***********/ -- GitLab From 09979236d6dc6a51c21131c4a8c0be7e1992a398 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 17:07:54 +0000 Subject: [PATCH 433/465] [PATCH] Remove old firmware headers from rio drivers Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/rio/rupstat.h | 50 ------------------------- drivers/char/rio/selftest.h | 73 ------------------------------------- drivers/char/rio/sysmap.h | 62 ------------------------------- drivers/char/rio/timeouts.h | 50 ------------------------- 4 files changed, 235 deletions(-) delete mode 100644 drivers/char/rio/rupstat.h delete mode 100644 drivers/char/rio/selftest.h delete mode 100644 drivers/char/rio/sysmap.h delete mode 100644 drivers/char/rio/timeouts.h diff --git a/drivers/char/rio/rupstat.h b/drivers/char/rio/rupstat.h deleted file mode 100644 index 56d828c63d2..00000000000 --- a/drivers/char/rio/rupstat.h +++ /dev/null @@ -1,50 +0,0 @@ -/**************************************************************************** - ******* ******* - ******* RUPSTAT - ******* ******* - **************************************************************************** - - Author : Jeremy Rolls - Date : - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ - -#ifndef _rupstat_h -#define _rupstat_h - -#ifndef lint -#ifdef SCCS_LABELS -static char *_rio_rupstat_h_sccs = "@(#)rupstat.h 1.1"; -#endif -#endif - -#define STATUS_SYNC 0 -#define STATUS_REQ_TOP 1 -#define STATUS_TOPOLOGY 2 - -#endif diff --git a/drivers/char/rio/selftest.h b/drivers/char/rio/selftest.h deleted file mode 100644 index 7a3dba35232..00000000000 --- a/drivers/char/rio/selftest.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -** File: selftest.h -** -** Author: David Dix -** -** Created: 15th March 1993 -** -** Last modified: 94/06/14 -** - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifndef _selftests_h_ -#define _selftests_h_ - -/* -** Selftest identifier... -*/ -#define SELFTEST_MAGIC 0x5a5a - -/* -** This is the structure of the packet that is sent back after each -** selftest on a booting RTA. -*/ -typedef struct { - short magic; /* Identifies packet type */ - int test; /* Test number, see below */ - unsigned int result; /* Result value */ - unsigned int dataIn; - unsigned int dataOut; -} selftestStruct; - -/* -** The different tests are identified by the following data values. -*/ -enum test { - TESTS_COMPLETE = 0x00, - MEMTEST_ADDR = 0x01, - MEMTEST_BIT = 0x02, - MEMTEST_FILL = 0x03, - MEMTEST_DATABUS = 0x04, - MEMTEST_ADDRBUS = 0x05, - CD1400_INIT = 0x10, - CD1400_LOOP = 0x11, - CD1400_INTERRUPT = 0x12 -}; - -enum result { - E_PORT = 0x10, - E_TX = 0x11, - E_RX = 0x12, - E_EXCEPT = 0x13, - E_COMPARE = 0x14, - E_MODEM = 0x15, - E_TIMEOUT = 0x16, - E_INTERRUPT = 0x17 -}; -#endif /* _selftests_h_ */ diff --git a/drivers/char/rio/sysmap.h b/drivers/char/rio/sysmap.h deleted file mode 100644 index e1c6f1160df..00000000000 --- a/drivers/char/rio/sysmap.h +++ /dev/null @@ -1,62 +0,0 @@ - -/**************************************************************************** - ******* ******* - ******* S Y S T E M M A P H E A D E R - ******* ******* - **************************************************************************** - - Author : Ian Nandhra - Date : - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ - -#ifndef lint -#ifdef SCCS_LABELS -static char *_rio_sysmap_h_sccs = "@(#)sysmap.h 1.1"; -#endif -#endif - -#define SYSTEM_MAP_LEN 64 /* Len of System Map array */ - - -typedef struct SYS_MAP SYS_MAP; -typedef struct SYS_MAP_LINK SYS_MAP_LINK; - -struct SYS_MAP_LINK { - short id; /* Unit Id */ - short link; /* Id's Link */ - short been_here; /* Used by map_gen */ -}; - -struct SYS_MAP { - char serial_num[4]; - SYS_MAP_LINK link[4]; -}; - - -/*********** end of file ***********/ diff --git a/drivers/char/rio/timeouts.h b/drivers/char/rio/timeouts.h deleted file mode 100644 index a8b5be3ca9b..00000000000 --- a/drivers/char/rio/timeouts.h +++ /dev/null @@ -1,50 +0,0 @@ - -/**************************************************************************** - ******* ******* - ******* T I M E O U T S - ******* ******* - **************************************************************************** - - Author : Ian Nandhra - Date : - - * - * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Version : 0.01 - - - Mods - ---------------------------------------------------------------------------- - Date By Description - ---------------------------------------------------------------------------- - - ***************************************************************************/ - -#ifndef lint -#ifdef SCCS_LABELS -static char *_rio_defaults_h_sccs = "@(#)timeouts.h 1.3"; -#endif -#endif - -#define MILLISECOND (int) (1000/64) /* 15.625 low ticks */ -#define SECOND (int) 15625 /* Low priority ticks */ - -#define TX_TIMEOUT (int) (200 * MILLISECOND) - - -/*********** end of file ***********/ -- GitLab From 925d70d64bfeccb669c0750943585944abb28b51 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 17:10:23 +0000 Subject: [PATCH 434/465] [PATCH] Remove long dead #if 0 code from rio_param Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/rio/rioparam.c | 43 ------------------------------------- 1 file changed, 43 deletions(-) diff --git a/drivers/char/rio/rioparam.c b/drivers/char/rio/rioparam.c index 4cc7f4942bf..c622f46d6d7 100644 --- a/drivers/char/rio/rioparam.c +++ b/drivers/char/rio/rioparam.c @@ -195,27 +195,6 @@ int SleepFlag; ** paramed with OPEN, we want to restore the saved port termio, but ** only if StoredTermio has been saved, i.e. NOT 1st open after reboot. */ -#if 0 - if (PortP->FirstOpen) { - PortP->StoredTty.iflag = TtyP->tm.c_iflag; - PortP->StoredTty.oflag = TtyP->tm.c_oflag; - PortP->StoredTty.cflag = TtyP->tm.c_cflag; - PortP->StoredTty.lflag = TtyP->tm.c_lflag; - PortP->StoredTty.line = TtyP->tm.c_line; - for (i = 0; i < NCC + 5; i++) - PortP->StoredTty.cc[i] = TtyP->tm.c_cc[i]; - PortP->FirstOpen = 0; - } else if (PortP->Store || PortP->Lock) { - rio_dprintk(RIO_DEBUG_PARAM, "OPEN: Restoring stored/locked params\n"); - TtyP->tm.c_iflag = PortP->StoredTty.iflag; - TtyP->tm.c_oflag = PortP->StoredTty.oflag; - TtyP->tm.c_cflag = PortP->StoredTty.cflag; - TtyP->tm.c_lflag = PortP->StoredTty.lflag; - TtyP->tm.c_line = PortP->StoredTty.line; - for (i = 0; i < NCC + 5; i++) - TtyP->tm.c_cc[i] = PortP->StoredTty.cc[i]; - } -#endif } /* @@ -273,16 +252,6 @@ int SleepFlag; phb_param_ptr = (struct phb_param *) PacketP->data; -#if 0 - /* - ** COR 1 - */ - if (TtyP->tm.c_iflag & INPCK) { - rio_dprintk(RIO_DEBUG_PARAM, "Parity checking on input enabled\n"); - Cor1 |= COR1_INPCK; - } -#endif - switch (TtyP->termios->c_cflag & CSIZE) { case CS5: { @@ -523,10 +492,6 @@ int SleepFlag; #ifdef XMT1EN if (TtyP->termios->c_cflag & XMT1EN) rio_dprintk(RIO_DEBUG_PARAM, "XMT1EN (?)\n"); -#endif -#if 0 - if (TtyP->termios->c_cflag & LOBLK) - rio_dprintk(RIO_DEBUG_PARAM, "LOBLK - JCL output blocks when not current\n"); #endif if (TtyP->termios->c_lflag & ISIG) rio_dprintk(RIO_DEBUG_PARAM, "Input character signal generating enabled\n"); @@ -572,14 +537,6 @@ int SleepFlag; rio_dprintk(RIO_DEBUG_PARAM, "Carriage return delay set\n"); if (TtyP->termios->c_oflag & TABDLY) rio_dprintk(RIO_DEBUG_PARAM, "Tab delay set\n"); -#if 0 - if (TtyP->termios->c_oflag & BSDLY) - rio_dprintk(RIO_DEBUG_PARAM, "Back-space delay set\n"); - if (TtyP->termios->c_oflag & VTDLY) - rio_dprintk(RIO_DEBUG_PARAM, "Vertical tab delay set\n"); - if (TtyP->termios->c_oflag & FFDLY) - rio_dprintk(RIO_DEBUG_PARAM, "Form-feed delay set\n"); -#endif /* ** These things are kind of useful in a later life! */ -- GitLab From a6176eeab0ef1750ce21790a6c6f61ba6c9ffc63 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 17:11:50 +0000 Subject: [PATCH 435/465] [PATCH] Remove #if 0 and other long dead code from rio_tty Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/rio/riotty.c | 583 -------------------------------------- 1 file changed, 583 deletions(-) diff --git a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c index 5894a25b011..6379816ed17 100644 --- a/drivers/char/rio/riotty.c +++ b/drivers/char/rio/riotty.c @@ -89,16 +89,9 @@ static char *_riotty_c_sccs_ = "@(#)riotty.c 1.3"; #include "list.h" #include "sam.h" -#if 0 -static void ttyseth_pv(struct Port *, struct ttystatics *, struct termios *sg, int); -#endif - static void RIOClearUp(struct Port *PortP); int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg); -#if 0 -static int RIOCookMode(struct ttystatics *); -#endif extern int conv_vb[]; /* now defined in ttymgr.c */ extern int conv_bv[]; /* now defined in ttymgr.c */ @@ -226,33 +219,6 @@ int riotopen(struct tty_struct *tty, struct file *filp) ** until the RTA is present then we must spin here waiting for ** the RTA to boot. */ -#if 0 - if (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)) { - if (PortP->WaitUntilBooted) { - rio_dprintk(RIO_DEBUG_TTY, "Waiting for RTA to boot\n"); - do { - if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { - rio_dprintk(RIO_DEBUG_TTY, "RTA EINTR in delay \n"); - func_exit(); - return -EINTR; - } - if (repeat_this-- <= 0) { - rio_dprintk(RIO_DEBUG_TTY, "Waiting for RTA to boot timeout\n"); - RIOPreemptiveCmd(p, PortP, FCLOSE); - pseterr(EINTR); - func_exit(); - return -EIO; - } - } while (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)); - rio_dprintk(RIO_DEBUG_TTY, "RTA has been booted\n"); - } else { - rio_dprintk(RIO_DEBUG_TTY, "RTA never booted\n"); - pseterr(ENXIO); - func_exit(); - return 0; - } - } -#else /* I find the above code a bit hairy. I find the below code easier to read and shorter. Now, if it works too that would be great... -- REW @@ -281,21 +247,10 @@ int riotopen(struct tty_struct *tty, struct file *filp) } } rio_dprintk(RIO_DEBUG_TTY, "RTA has been booted\n"); -#endif -#if 0 - tp = PortP->TtyP; /* get tty struct */ -#endif rio_spin_lock_irqsave(&PortP->portSem, flags); if (p->RIOHalted) { goto bombout; } -#if 0 - retval = gs_init_port(&PortP->gs); - if (retval) { - func_exit(); - return retval; - } -#endif /* ** If the port is in the final throws of being closed, @@ -363,11 +318,6 @@ int riotopen(struct tty_struct *tty, struct file *filp) command piggybacks the parameters immediately. -- REW */ RIOParam(PortP, OPEN, Modem, OK_TO_SLEEP); /* Open the port */ -#if 0 - /* This delay of 1 second was annoying. I removed it. -- REW */ - RIODelay(PortP, HUNDRED_MS * 10); - RIOParam(PortP, CONFIG, Modem, OK_TO_SLEEP); /* Config the port */ -#endif rio_spin_lock_irqsave(&PortP->portSem, flags); /* @@ -439,9 +389,6 @@ int riotopen(struct tty_struct *tty, struct file *filp) PortP->State |= RIO_WOPEN; rio_spin_unlock_irqrestore(&PortP->portSem, flags); if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) -#if 0 - if (sleep((caddr_t) & tp->tm.c_canqo, TTIPRI | PCATCH)) -#endif { /* ** ACTION: verify that this is a good thing @@ -505,10 +452,6 @@ int riotopen(struct tty_struct *tty, struct file *filp) */ int riotclose(void *ptr) { -#if 0 - register uint SysPort = dev; - struct ttystatics *tp; /* pointer to our ttystruct */ -#endif struct Port *PortP = ptr; /* pointer to the port structure */ int deleted = 0; int try = -1; /* Disable the timeouts by setting them to -1 */ @@ -534,13 +477,6 @@ int riotclose(void *ptr) end_time = jiffies + MAX_SCHEDULE_TIMEOUT; Modem = rio_ismodem(tty); -#if 0 - /* What F.CKING cache? Even then, a higly idle multiprocessor, - system with large caches this won't work . Better find out when - this doesn't work asap, and fix the cause. -- REW */ - - RIODelay(PortP, HUNDRED_MS * 10); /* To flush the cache */ -#endif rio_spin_lock_irqsave(&PortP->portSem, flags); /* @@ -703,45 +639,6 @@ int riotclose(void *ptr) } -/* -** decide if we need to use the line discipline. -** This routine can return one of three values: -** COOK_RAW if no processing has to be done by the line discipline or the card -** COOK_WELL if the line discipline must be used to do the processing -** COOK_MEDIUM if the card can do all the processing necessary. -*/ -#if 0 -static int RIOCookMode(struct ttystatics *tp) -{ - /* - ** We can't handle tm.c_mstate != 0 on SCO - ** We can't handle mapping - ** We can't handle non-ttwrite line disc. - ** We can't handle lflag XCASE - ** We can handle oflag OPOST & (OCRNL, ONLCR, TAB3) - */ - -#ifdef CHECK - CheckTtyP(tp); -#endif - if (!(tp->tm.c_oflag & OPOST)) /* No post processing */ - return COOK_RAW; /* Raw mode o/p */ - - if (tp->tm.c_lflag & XCASE) - return COOK_WELL; /* Use line disc */ - - if (tp->tm.c_oflag & ~(OPOST | ONLCR | OCRNL | TAB3)) - return COOK_WELL; /* Use line disc for strange modes */ - - if (tp->tm.c_oflag == OPOST) /* If only OPOST is set, do RAW */ - return COOK_RAW; - - /* - ** So, we need to output process! - */ - return COOK_MEDIUM; -} -#endif static void RIOClearUp(PortP) struct Port *PortP; @@ -776,11 +673,6 @@ int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len unsigned long flags; rio_dprintk(RIO_DEBUG_TTY, "entering shortcommand.\n"); -#ifdef CHECK - CheckPortP(PortP); - if (len < 1 || len > 2) - cprintf(("STUPID LENGTH %d\n", len)); -#endif if (PortP->State & RIO_DELETED) { rio_dprintk(RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n"); @@ -852,478 +744,3 @@ int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len } -#if 0 -/* -** This is an ioctl interface. This is the twentieth century. You know what -** its all about. -*/ -int riotioctl(struct rio_info *p, struct tty_struct *tty, int cmd, caddr_t arg) -{ - register struct Port *PortP; - register struct ttystatics *tp; - int current; - int ParamSemIncremented = 0; - int old_oflag, old_cflag, old_iflag, changed, oldcook; - int i; - unsigned char sio_regs[5]; /* Here be magic */ - short vpix_cflag; - short divisor; - int baud; - uint SysPort = rio_minor(tty); - int Modem = rio_ismodem(tty); - int ioctl_processed; - - rio_dprintk(RIO_DEBUG_TTY, "port ioctl SysPort %d command 0x%x argument 0x%x %s\n", SysPort, cmd, arg, Modem ? "Modem" : "tty"); - - if (SysPort >= RIO_PORTS) { - rio_dprintk(RIO_DEBUG_TTY, "Bad port number %d\n", SysPort); - return -ENXIO; - } - - PortP = p->RIOPortp[SysPort]; - tp = PortP->TtyP; - - rio_spin_lock_irqsave(&PortP->portSem, flags); - -#ifdef STATS - PortP->Stat.IoctlCnt++; -#endif - - if (PortP->State & RIO_DELETED) { - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return -EIO; - } - - - if (p->RIOHalted) { - RIOClearUp(PortP); - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return -EIO; - } - - /* - ** Count ioctls for port statistics reporting - */ - if (PortP->statsGather) - PortP->ioctls++; - - /* - ** Specialix RIO Ioctl calls - */ - switch (cmd) { - - case TCRIOTRIAD: - if (arg) - PortP->State |= RIO_TRIAD_MODE; - else - PortP->State &= ~RIO_TRIAD_MODE; - /* - ** Normally, when istrip is set on a port, a config is - ** sent to the RTA instructing the CD1400 to do the - ** stripping. In TRIAD mode, the interrupt receive routine - ** must do the stripping instead, since it has to detect - ** an 8 bit function key sequence. If istrip is set with - ** TRIAD mode on(off), and 8 bit data is being read by - ** the port, the user then turns TRIAD mode off(on), the RTA - ** must be reconfigured (not) to do the stripping. - ** Hence we call RIOParam here. - */ - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - RIOParam(PortP, CONFIG, Modem, OK_TO_SLEEP); - return 0; - - case TCRIOTSTATE: - rio_dprintk(RIO_DEBUG_TTY, "tbusy/tstop monitoring %sabled\n", arg ? "en" : "dis"); - /* MonitorTstate = 0 ; */ - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - RIOParam(PortP, CONFIG, Modem, OK_TO_SLEEP); - return 0; - - case TCRIOSTATE: /* current state of Modem input pins */ - rio_dprintk(RIO_DEBUG_TTY, "TCRIOSTATE\n"); - if (RIOPreemptiveCmd(p, PortP, MGET) == RIO_FAIL) - rio_dprintk(RIO_DEBUG_TTY, "TCRIOSTATE command failed\n"); - PortP->State |= RIO_BUSY; - current = PortP->ModemState; - if (copyout((caddr_t) & current, (int) arg, sizeof(current)) == COPYFAIL) { - rio_dprintk(RIO_DEBUG_TTY, "Copyout failed\n"); - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - pseterr(EFAULT); - } - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return 0; - - case TCRIOMBIS: /* Set modem lines */ - case TCRIOMBIC: /* Clear modem lines */ - rio_dprintk(RIO_DEBUG_TTY, "TCRIOMBIS/TCRIOMBIC\n"); - if (cmd == TCRIOMBIS) { - uint state; - state = (uint) arg; - PortP->ModemState |= (ushort) state; - PortP->ModemLines = (ulong) arg; - if (RIOPreemptiveCmd(p, PortP, MBIS) == RIO_FAIL) - rio_dprintk(RIO_DEBUG_TTY, "TCRIOMBIS command failed\n"); - } else { - uint state; - - state = (uint) arg; - PortP->ModemState &= ~(ushort) state; - PortP->ModemLines = (ulong) arg; - if (RIOPreemptiveCmd(p, PortP, MBIC) == RIO_FAIL) - rio_dprintk(RIO_DEBUG_TTY, "TCRIOMBIC command failed\n"); - } - PortP->State |= RIO_BUSY; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return 0; - - case TCRIOXPON: /* set Xprint ON string */ - rio_dprintk(RIO_DEBUG_TTY, "TCRIOXPON\n"); - if (copyin((int) arg, (caddr_t) PortP->Xprint.XpOn, MAX_XP_CTRL_LEN) == COPYFAIL) { - rio_dprintk(RIO_DEBUG_TTY, "Copyin failed\n"); - PortP->Xprint.XpOn[0] = '\0'; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - pseterr(EFAULT); - } - PortP->Xprint.XpOn[MAX_XP_CTRL_LEN - 1] = '\0'; - PortP->Xprint.XpLen = strlen(PortP->Xprint.XpOn) + strlen(PortP->Xprint.XpOff); - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return 0; - - case TCRIOXPOFF: /* set Xprint OFF string */ - rio_dprintk(RIO_DEBUG_TTY, "TCRIOXPOFF\n"); - if (copyin((int) arg, (caddr_t) PortP->Xprint.XpOff, MAX_XP_CTRL_LEN) == COPYFAIL) { - rio_dprintk(RIO_DEBUG_TTY, "Copyin failed\n"); - PortP->Xprint.XpOff[0] = '\0'; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - pseterr(EFAULT); - } - PortP->Xprint.XpOff[MAX_XP_CTRL_LEN - 1] = '\0'; - PortP->Xprint.XpLen = strlen(PortP->Xprint.XpOn) + strlen(PortP->Xprint.XpOff); - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return 0; - - case TCRIOXPCPS: /* set Xprint CPS string */ - rio_dprintk(RIO_DEBUG_TTY, "TCRIOXPCPS\n"); - if ((uint) arg > p->RIOConf.MaxXpCps || (uint) arg < p->RIOConf.MinXpCps) { - rio_dprintk(RIO_DEBUG_TTY, "%d CPS out of range\n", arg); - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - pseterr(EINVAL); - return 0; - } - PortP->Xprint.XpCps = (uint) arg; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return 0; - - case TCRIOXPRINT: - rio_dprintk(RIO_DEBUG_TTY, "TCRIOXPRINT\n"); - if (copyout((caddr_t) & PortP->Xprint, (int) arg, sizeof(struct Xprint)) == COPYFAIL) { - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - pseterr(EFAULT); - } - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return 0; - - case TCRIOIXANYON: - rio_dprintk(RIO_DEBUG_TTY, "TCRIOIXANYON\n"); - PortP->Config |= RIO_IXANY; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return 0; - - case TCRIOIXANYOFF: - rio_dprintk(RIO_DEBUG_TTY, "TCRIOIXANYOFF\n"); - PortP->Config &= ~RIO_IXANY; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return 0; - - case TCRIOIXONON: - rio_dprintk(RIO_DEBUG_TTY, "TCRIOIXONON\n"); - PortP->Config |= RIO_IXON; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return 0; - - case TCRIOIXONOFF: - rio_dprintk(RIO_DEBUG_TTY, "TCRIOIXONOFF\n"); - PortP->Config &= ~RIO_IXON; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return 0; - -/* -** 15.10.1998 ARG - ESIL 0761 part fix -** Added support for CTS and RTS flow control ioctls : -*/ - case TCRIOCTSFLOWEN: - rio_dprintk(RIO_DEBUG_TTY, "TCRIOCTSFLOWEN\n"); - PortP->Config |= RIO_CTSFLOW; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - RIOParam(PortP, CONFIG, Modem, OK_TO_SLEEP); - return 0; - - case TCRIOCTSFLOWDIS: - rio_dprintk(RIO_DEBUG_TTY, "TCRIOCTSFLOWDIS\n"); - PortP->Config &= ~RIO_CTSFLOW; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - RIOParam(PortP, CONFIG, Modem, OK_TO_SLEEP); - return 0; - - case TCRIORTSFLOWEN: - rio_dprintk(RIO_DEBUG_TTY, "TCRIORTSFLOWEN\n"); - PortP->Config |= RIO_RTSFLOW; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - RIOParam(PortP, CONFIG, Modem, OK_TO_SLEEP); - return 0; - - case TCRIORTSFLOWDIS: - rio_dprintk(RIO_DEBUG_TTY, "TCRIORTSFLOWDIS\n"); - PortP->Config &= ~RIO_RTSFLOW; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - RIOParam(PortP, CONFIG, Modem, OK_TO_SLEEP); - return 0; - -/* end ESIL 0761 part fix */ - - } - - - /* Lynx IOCTLS */ - switch (cmd) { - case TIOCSETP: - case TIOCSETN: - case OTIOCSETP: - case OTIOCSETN: - ioctl_processed++; - ttyseth(PortP, tp, (struct old_sgttyb *) arg); - break; - case TCSETA: - case TCSETAW: - case TCSETAF: - ioctl_processed++; - rio_dprintk(RIO_DEBUG_TTY, "NON POSIX ioctl\n"); - ttyseth_pv(PortP, tp, (struct termios *) arg, 0); - break; - case TCSETAP: /* posix tcsetattr() */ - case TCSETAWP: /* posix tcsetattr() */ - case TCSETAFP: /* posix tcsetattr() */ - rio_dprintk(RIO_DEBUG_TTY, "NON POSIX SYSV ioctl\n"); - ttyseth_pv(PortP, tp, (struct termios *) arg, 1); - ioctl_processed++; - break; - } - - /* - ** If its any of the commands that require the port to be in the - ** non-busy state wait until all output has drained - */ - if (!ioctl_processed) - switch (cmd) { - case TCSETAW: - case TCSETAF: - case TCSETA: - case TCSBRK: -#define OLD_POSIX ('x' << 8) -#define OLD_POSIX_SETA (OLD_POSIX | 2) -#define OLD_POSIX_SETAW (OLD_POSIX | 3) -#define OLD_POSIX_SETAF (OLD_POSIX | 4) -#define NEW_POSIX (('i' << 24) | ('X' << 16)) -#define NEW_POSIX_SETA (NEW_POSIX | 2) -#define NEW_POSIX_SETAW (NEW_POSIX | 3) -#define NEW_POSIX_SETAF (NEW_POSIX | 4) - case OLD_POSIX_SETA: - case OLD_POSIX_SETAW: - case OLD_POSIX_SETAF: - case NEW_POSIX_SETA: - case NEW_POSIX_SETAW: - case NEW_POSIX_SETAF: -#ifdef TIOCSETP - case TIOCSETP: -#endif - case TIOCSETD: - case TIOCSETN: - rio_dprintk(RIO_DEBUG_TTY, "wait for non-BUSY, semaphore set\n"); - /* - ** Wait for drain here, at least as far as the double buffer - ** being empty. - */ - /* XXX Does the above comment mean that this has - still to be implemented? -- REW */ - /* XXX Is the locking OK together with locking - in txenable? (Deadlock?) -- REW */ - - RIOTxEnable((char *) PortP); - break; - default: - break; - } - - old_cflag = tp->tm.c_cflag; - old_iflag = tp->tm.c_iflag; - old_oflag = tp->tm.c_oflag; - oldcook = PortP->CookMode; - - if (p->RIOHalted) { - RIOClearUp(PortP); - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - pseterr(EIO); - return 0; - } - - PortP->FlushCmdBodge = 0; - - /* - ** If the port is locked, and it is reconfigured, we want - ** to restore the state of the tty structure so the change is NOT - ** made. - */ - if (PortP->Lock) { - tp->tm.c_iflag = PortP->StoredTty.iflag; - tp->tm.c_oflag = PortP->StoredTty.oflag; - tp->tm.c_cflag = PortP->StoredTty.cflag; - tp->tm.c_lflag = PortP->StoredTty.lflag; - tp->tm.c_line = PortP->StoredTty.line; - for (i = 0; i < NCC + 1; i++) - tp->tm.c_cc[i] = PortP->StoredTty.cc[i]; - } else { - /* - ** If the port is set to store the parameters, and it is - ** reconfigured, we want to save the current tty struct so it - ** may be restored on the next open. - */ - if (PortP->Store) { - PortP->StoredTty.iflag = tp->tm.c_iflag; - PortP->StoredTty.oflag = tp->tm.c_oflag; - PortP->StoredTty.cflag = tp->tm.c_cflag; - PortP->StoredTty.lflag = tp->tm.c_lflag; - PortP->StoredTty.line = tp->tm.c_line; - for (i = 0; i < NCC + 1; i++) - PortP->StoredTty.cc[i] = tp->tm.c_cc[i]; - } - } - - changed = (tp->tm.c_cflag != old_cflag) || (tp->tm.c_iflag != old_iflag) || (tp->tm.c_oflag != old_oflag); - - PortP->CookMode = RIOCookMode(tp); /* Set new cooking mode */ - - rio_dprintk(RIO_DEBUG_TTY, "RIOIoctl changed %d newcook %d oldcook %d\n", changed, PortP->CookMode, oldcook); - -#ifdef MODEM_SUPPORT - /* - ** kludge to force CARR_ON if CLOCAL set - */ - if ((tp->tm.c_cflag & CLOCAL) || (PortP->ModemState & MSVR1_CD)) { - tp->tm.c_state |= CARR_ON; - wakeup((caddr_t) & tp->tm.c_canq); - } -#endif - - if (p->RIOHalted) { - RIOClearUp(PortP); - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - pseterr(EIO); - return 0; - } - /* - ** Re-configure if modes or cooking have changed - */ - if (changed || oldcook != PortP->CookMode || (ioctl_processed)) { - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - rio_dprintk(RIO_DEBUG_TTY, "Ioctl changing the PORT settings\n"); - RIOParam(PortP, CONFIG, Modem, OK_TO_SLEEP); - rio_spin_lock_irqsave(&PortP->portSem, flags); - } - - if (p->RIOHalted) { - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - RIOClearUp(PortP); - pseterr(EIO); - return 0; - } - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return 0; -} - -/* - ttyseth -- set hardware dependent tty settings -*/ -void ttyseth(PortP, s, sg) -struct Port *PortP; -struct ttystatics *s; -struct old_sgttyb *sg; -{ - struct old_sgttyb *tsg; - struct termios *tp = &s->tm; - - tsg = &s->sg; - - if (sg->sg_flags & (EVENP | ODDP)) { - tp->c_cflag &= PARENB; - if (sg->sg_flags & EVENP) { - if (sg->sg_flags & ODDP) { - tp->c_cflag &= V_CS7; - tp->c_cflag &= ~PARENB; - } else { - tp->c_cflag &= V_CS7; - tp->c_cflag &= PARENB; - tp->c_cflag &= PARODD; - } - } else if (sg->sg_flags & ODDP) { - tp->c_cflag &= V_CS7; - tp->c_cflag &= PARENB; - tp->c_cflag &= PARODD; - } else { - tp->c_cflag &= V_CS7; - tp->c_cflag &= PARENB; - } - } -/* - * Use ispeed as the desired speed. Most implementations don't handle - * separate input and output speeds very well. If the RIO handles this, - * I will have to use separate sets of flags to store them in the - * Port structure. - */ - if (!sg->sg_ospeed) - sg->sg_ospeed = sg->sg_ispeed; - else - sg->sg_ispeed = sg->sg_ospeed; - if (sg->sg_ispeed > V_EXTB) - sg->sg_ispeed = V_EXTB; - if (sg->sg_ispeed < V_B0) - sg->sg_ispeed = V_B0; - *tsg = *sg; - tp->c_cflag = (tp->c_cflag & ~V_CBAUD) | conv_bv[(int) sg->sg_ispeed]; -} - -/* - ttyseth_pv -- set hardware dependent tty settings using either the - POSIX termios structure or the System V termio structure. - sysv = 0 => (POSIX): struct termios *sg - sysv != 0 => (System V): struct termio *sg -*/ -static void ttyseth_pv(PortP, s, sg, sysv) -struct Port *PortP; -struct ttystatics *s; -struct termios *sg; -int sysv; -{ - int speed; - unsigned char csize; - unsigned char cread; - unsigned int lcr_flags; - int ps; - - if (sysv) { - /* sg points to a System V termio structure */ - csize = ((struct termio *) sg)->c_cflag & CSIZE; - cread = ((struct termio *) sg)->c_cflag & CREAD; - speed = conv_vb[((struct termio *) sg)->c_cflag & V_CBAUD]; - } else { - /* sg points to a POSIX termios structure */ - csize = sg->c_cflag & CSIZE; - cread = sg->c_cflag & CREAD; - speed = conv_vb[sg->c_cflag & V_CBAUD]; - } - if (s->sg.sg_ispeed != speed || s->sg.sg_ospeed != speed) { - s->sg.sg_ispeed = speed; - s->sg.sg_ospeed = speed; - s->tm.c_cflag = (s->tm.c_cflag & ~V_CBAUD) | conv_bv[(int) s->sg.sg_ispeed]; - } -} -#endif -- GitLab From c7306c02874bf4d22bc0b1dbea34282d0b9a3df1 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 17:14:25 +0000 Subject: [PATCH 436/465] [PATCH] Remove unused code from rioboot Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/rio/rioinit.c | 1152 ------------------------------------ 1 file changed, 1152 deletions(-) diff --git a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c index 898a126ae3e..0d44ef464e6 100644 --- a/drivers/char/rio/rioinit.c +++ b/drivers/char/rio/rioinit.c @@ -87,222 +87,8 @@ static char *_rioinit_c_sccs_ = "@(#)rioinit.c 1.3"; int RIOPCIinit(struct rio_info *p, int Mode); -#if 0 -static void RIOAllocateInterrupts(struct rio_info *); -static int RIOReport(struct rio_info *); -static void RIOStopInterrupts(struct rio_info *, int, int); -#endif - static int RIOScrub(int, BYTE *, int); -#if 0 -extern int rio_intr(); - -/* -** Init time code. -*/ -void -rioinit( p, info ) -struct rio_info * p; -struct RioHostInfo * info; -{ - /* - ** Multi-Host card support - taking the easy way out - sorry ! - ** We allocate and set up the Host and Port structs when the - ** driver is called to 'install' the first host. - ** We check for this first 'call' by testing the RIOPortp pointer. - */ - if ( !p->RIOPortp ) - { - rio_dprintk (RIO_DEBUG_INIT, "Allocating and setting up driver data structures\n"); - - RIOAllocDataStructs(p); /* allocate host/port structs */ - RIOSetupDataStructs(p); /* setup topology structs */ - } - - RIOInitHosts( p, info ); /* hunt down the hardware */ - - RIOAllocateInterrupts(p); /* allocate interrupts */ - RIOReport(p); /* show what we found */ -} - -/* -** Initialise the Cards -*/ -void -RIOInitHosts(p, info) -struct rio_info * p; -struct RioHostInfo * info; -{ -/* -** 15.10.1998 ARG - ESIL 0762 part fix -** If there is no ISA card definition - we always look for PCI cards. -** As we currently only support one host card this lets an ISA card -** definition take precedence over PLUG and PLAY. -** No ISA card - we are PLUG and PLAY with PCI. -*/ - - /* - ** Note - for PCI both these will be zero, that's okay because - ** RIOPCIInit() fills them in if a card is found. - */ - p->RIOHosts[p->RIONumHosts].Ivec = info->vector; - p->RIOHosts[p->RIONumHosts].PaddrP = info->location; - - /* - ** Check that we are able to accommodate another host - */ - if ( p->RIONumHosts >= RIO_HOSTS ) - { - p->RIOFailed++; - return; - } - - if ( info->bus & ISA_BUS ) - { - rio_dprintk (RIO_DEBUG_INIT, "initialising card %d (ISA)\n", p->RIONumHosts); - RIOISAinit(p, p->mode); - } - else - { - rio_dprintk (RIO_DEBUG_INIT, "initialising card %d (PCI)\n", p->RIONumHosts); - RIOPCIinit(p, RIO_PCI_DEFAULT_MODE); - } - - rio_dprintk (RIO_DEBUG_INIT, "Total hosts initialised so far : %d\n", p->RIONumHosts); - - -#ifdef FUTURE_RELEASE - if (p->bus & EISA_BUS) - /* EISA card */ - RIOEISAinit(p, RIO_EISA_DEFAULT_MODE); - - if (p->bus & MCA_BUS) - /* MCA card */ - RIOMCAinit(p, RIO_MCA_DEFAULT_MODE); -#endif -} - -/* -** go through memory for an AT host that we pass in the device info -** structure and initialise -*/ -void -RIOISAinit(p, mode) -struct rio_info * p; -int mode; -{ - - /* XXX Need to implement this. */ -#if 0 - p->intr_tid = iointset(p->RIOHosts[p->RIONumHosts].Ivec, - (int (*)())rio_intr, (char*)p->RIONumHosts); - - rio_dprintk (RIO_DEBUG_INIT, "Set interrupt handler, intr_tid = 0x%x\n", p->intr_tid ); - - if (RIODoAT(p, p->RIOHosts[p->RIONumHosts].PaddrP, mode)) { - return; - } - else { - rio_dprintk (RIO_DEBUG_INIT, "RIODoAT failed\n"); - p->RIOFailed++; - } -#endif - -} - -/* -** RIODoAT : -** -** Map in a boards physical address, check that the board is there, -** test the board and if everything is okay assign the board an entry -** in the Rio Hosts structure. -*/ -int -RIODoAT(p, Base, mode) -struct rio_info * p; -int Base; -int mode; -{ -#define FOUND 1 -#define NOT_FOUND 0 - - caddr_t cardAddr; - - /* - ** Check to see if we actually have a board at this physical address. - */ - if ((cardAddr = RIOCheckForATCard(Base)) != 0) { - /* - ** Now test the board to see if it is working. - */ - if (RIOBoardTest(Base, cardAddr, RIO_AT, 0) == RIO_SUCCESS) { - /* - ** Fill out a slot in the Rio host structure. - */ - if (RIOAssignAT(p, Base, cardAddr, mode)) { - return(FOUND); - } - } - RIOMapout(Base, RIO_AT_MEM_SIZE, cardAddr); - } - return(NOT_FOUND); -} - -caddr_t -RIOCheckForATCard(Base) -int Base; -{ - int off; - struct DpRam *cardp; /* (Points at the host) */ - caddr_t virtAddr; - unsigned char RIOSigTab[24]; -/* -** Table of values to search for as prom signature of a host card -*/ - strcpy(RIOSigTab, "JBJGPGGHINSMJPJR"); - - /* - ** Hey! Yes, You reading this code! Yo, grab a load a this: - ** - ** IF the card is using WORD MODE rather than BYTE MODE - ** then it will occupy 128K of PHYSICAL memory area. So, - ** you might think that the following Mapin is wrong. Well, - ** it isn't, because the SECOND 64K of occupied space is an - ** EXACT COPY of the FIRST 64K. (good?), so, we need only - ** map it in in one 64K block. - */ - if (RIOMapin(Base, RIO_AT_MEM_SIZE, &virtAddr) == -1) { - rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Couldn't map the board in!\n"); - return((caddr_t)0); - } - - /* - ** virtAddr points to the DP ram of the system. - ** We now cast this to a pointer to a RIO Host, - ** and have a rummage about in the PROM. - */ - cardp = (struct DpRam *)virtAddr; - - for (off=0; RIOSigTab[off]; off++) { - if ((RBYTE(cardp->DpSignature[off]) & 0xFF) != RIOSigTab[off]) { - /* - ** Signature mismatch - card not at this address - */ - RIOMapout(Base, RIO_AT_MEM_SIZE, virtAddr); - rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Couldn't match the signature 0x%x 0x%x!\n", - (int)cardp, off); - return((caddr_t)0); - } - } - - /* - ** If we get here then we must have found a valid board so return - ** its virtual address. - */ - return(virtAddr); -} -#endif /** ** RIOAssignAT : @@ -367,667 +153,6 @@ int mode; rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Tests Passed at 0x%x\n", Base); return(1); } -#if 0 -#ifdef FUTURE_RELEASE -int RIOMCAinit(int Mode) -{ - uchar SlotNumber; - caddr_t Caddr; - uint Paddr; - uint Ivec; - int Handle; - int ret = 0; - - /* - ** Valid mode information for MCA cards - ** is only FAST LINKS - */ - Mode = (Mode & FAST_LINKS) ? McaTpFastLinks : McaTpSlowLinks; - rio_dprintk (RIO_DEBUG_INIT, "RIOMCAinit(%d)\n",Mode); - - - /* - ** Check out each of the slots - */ - for (SlotNumber = 0; SlotNumber < McaMaxSlots; SlotNumber++) { - /* - ** Enable the slot we want to talk to - */ - outb( McaSlotSelect, SlotNumber | McaSlotEnable ); - - /* - ** Read the ID word from the slot - */ - if (((inb(McaIdHigh)<< 8)|inb(McaIdLow)) == McaRIOId) - { - rio_dprintk (RIO_DEBUG_INIT, "Potential MCA card in slot %d\n", SlotNumber); - - /* - ** Card appears to be a RIO MCA card! - */ - RIOMachineType |= (1<= RIO_HOSTS ) - { - Rprintf(RIOMesgTooManyCards); - return(ret); - } - - /* - ** McaIrqEnable contains the interrupt vector, and a card - ** enable bit. - */ - Ivec = inb(McaIrqEnable); - - rio_dprintk (RIO_DEBUG_INIT, "Ivec is %x\n", Ivec); - - switch ( Ivec & McaIrqMask ) - { - case McaIrq9: - rio_dprintk (RIO_DEBUG_INIT, "IRQ9\n"); - break; - case McaIrq3: - rio_dprintk (RIO_DEBUG_INIT, "IRQ3\n"); - break; - case McaIrq4: - rio_dprintk (RIO_DEBUG_INIT, "IRQ4\n"); - break; - case McaIrq7: - rio_dprintk (RIO_DEBUG_INIT, "IRQ7\n"); - break; - case McaIrq10: - rio_dprintk (RIO_DEBUG_INIT, "IRQ10\n"); - break; - case McaIrq11: - rio_dprintk (RIO_DEBUG_INIT, "IRQ11\n"); - break; - case McaIrq12: - rio_dprintk (RIO_DEBUG_INIT, "IRQ12\n"); - break; - case McaIrq15: - rio_dprintk (RIO_DEBUG_INIT, "IRQ15\n"); - break; - } - - /* - ** If the card enable bit isn't set, then set it! - */ - if ((Ivec & McaCardEnable) != McaCardEnable) { - rio_dprintk (RIO_DEBUG_INIT, "McaCardEnable not set - setting!\n"); - outb(McaIrqEnable,Ivec|McaCardEnable); - } else - rio_dprintk (RIO_DEBUG_INIT, "McaCardEnable already set\n"); - - /* - ** Convert the IRQ enable mask into something useful - */ - Ivec = RIOMcaToIvec[Ivec & McaIrqMask]; - - /* - ** Find the physical address - */ - rio_dprintk (RIO_DEBUG_INIT, "inb(McaMemory) is %x\n", inb(McaMemory)); - Paddr = McaAddress(inb(McaMemory)); - - rio_dprintk (RIO_DEBUG_INIT, "MCA card has Ivec %d Addr %x\n", Ivec, Paddr); - - if ( Paddr != 0 ) - { - - /* - ** Tell the memory mapper that we want to talk to it - */ - Handle = RIOMapin( Paddr, RIO_MCA_MEM_SIZE, &Caddr ); - - if ( Handle == -1 ) { - rio_dprintk (RIO_DEBUG_INIT, "Couldn't map %d bytes at %x\n", RIO_MCA_MEM_SIZE, Paddr; - continue; - } - - rio_dprintk (RIO_DEBUG_INIT, "Board mapped to vaddr 0x%x\n", Caddr); - - /* - ** And check that it is actually there! - */ - if ( RIOBoardTest( Paddr,Caddr,RIO_MCA,SlotNumber ) == RIO_SUCCESS ) - { - rio_dprintk (RIO_DEBUG_INIT, "Board has passed test\n"); - rio_dprintk (RIO_DEBUG_INIT, "Slot %d. Type %d. Paddr 0x%x. Caddr 0x%x. Mode 0x%x.\n", - SlotNumber, RIO_MCA, Paddr, Caddr, Mode); - - /* - ** Board has passed its scrub test. Fill in all the - ** transient stuff. - */ - p->RIOHosts[RIONumHosts].Slot = SlotNumber; - p->RIOHosts[RIONumHosts].Ivec = Ivec; - p->RIOHosts[RIONumHosts].Type = RIO_MCA; - p->RIOHosts[RIONumHosts].Copy = bcopy; - p->RIOHosts[RIONumHosts].PaddrP = Paddr; - p->RIOHosts[RIONumHosts].Caddr = Caddr; - p->RIOHosts[RIONumHosts].CardP = (struct DpRam *)Caddr; - p->RIOHosts[RIONumHosts].Mode = Mode; - WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt , 0xff); - p->RIOHosts[RIONumHosts].UniqueNum = - ((RBYTE(p->RIOHosts[RIONumHosts].Unique[0])&0xFF)<<0)| - ((RBYTE(p->RIOHosts[RIONumHosts].Unique[1])&0xFF)<<8)| - ((RBYTE(p->RIOHosts[RIONumHosts].Unique[2])&0xFF)<<16)| - ((RBYTE(p->RIOHosts[RIONumHosts].Unique[3])&0xFF)<<24); - RIONumHosts++; - ret++; - } - else - { - /* - ** It failed the test, so ignore it. - */ - rio_dprintk (RIO_DEBUG_INIT, "TEST FAILED\n"); - RIOMapout(Paddr, RIO_MCA_MEM_SIZE, Caddr ); - } - } - else - { - rio_dprintk (RIO_DEBUG_INIT, "Slot %d - Paddr zero!\n", SlotNumber); - } - } - else - { - rio_dprintk (RIO_DEBUG_INIT, "Slot %d NOT RIO\n", SlotNumber); - } - } - /* - ** Now we have checked all the slots, turn off the MCA slot selector - */ - outb(McaSlotSelect,0); - rio_dprintk (RIO_DEBUG_INIT, "Slot %d NOT RIO\n", SlotNumber); - return ret; -} - -int RIOEISAinit( int Mode ) -{ - static int EISADone = 0; - uint Paddr; - int PollIntMixMsgDone = 0; - caddr_t Caddr; - ushort Ident; - uchar EisaSlot; - uchar Ivec; - int ret = 0; - - /* - ** The only valid mode information for EISA hosts is fast or slow - ** links. - */ - Mode = (Mode & FAST_LINKS) ? EISA_TP_FAST_LINKS : EISA_TP_SLOW_LINKS; - - if ( EISADone ) - { - rio_dprintk (RIO_DEBUG_INIT, "RIOEISAinit() - already done, return.\n"); - return(0); - } - - EISADone++; - - rio_dprintk (RIO_DEBUG_INIT, "RIOEISAinit()\n"); - - - /* - ** First check all cards to see if ANY are set for polled mode operation. - ** If so, set ALL to polled. - */ - - for ( EisaSlot=1; EisaSlot<=RIO_MAX_EISA_SLOTS; EisaSlot++ ) - { - Ident = (INBZ(EisaSlot,EISA_PRODUCT_IDENT_HI)<<8) | - INBZ(EisaSlot,EISA_PRODUCT_IDENT_LO); - - if ( Ident == RIO_EISA_IDENT ) - { - rio_dprintk (RIO_DEBUG_INIT, "Found Specialix product\n"); - - if ( INBZ(EisaSlot,EISA_PRODUCT_NUMBER) != RIO_EISA_PRODUCT_CODE ) - { - rio_dprintk (RIO_DEBUG_INIT, "Not Specialix RIO - Product number %x\n", - INBZ(EisaSlot, EISA_PRODUCT_NUMBER)); - continue; /* next slot */ - } - /* - ** Its a Specialix RIO! - */ - rio_dprintk (RIO_DEBUG_INIT, "RIO Revision %d\n", - INBZ(EisaSlot, EISA_REVISION_NUMBER)); - - RIOMachineType |= (1<= RIO_HOSTS ) - { - Rprintf(RIOMesgTooManyCards); - return 0; - } - - /* - ** Ensure that the enable bit is set! - */ - OUTBZ( EisaSlot, EISA_ENABLE, RIO_EISA_ENABLE_BIT ); - - /* - ** EISA_INTERRUPT_VEC contains the interrupt vector. - */ - Ivec = INBZ(EisaSlot,EISA_INTERRUPT_VEC); - -#ifdef RIODEBUG - switch ( Ivec & EISA_INTERRUPT_MASK ) - { - case EISA_IRQ_3: - rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 3\n"); - break; - case EISA_IRQ_4: - rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 4\n"); - break; - case EISA_IRQ_5: - rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 5\n"); - break; - case EISA_IRQ_6: - rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 6\n"); - break; - case EISA_IRQ_7: - rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 7\n"); - break; - case EISA_IRQ_9: - rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 9\n"); - break; - case EISA_IRQ_10: - rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 10\n"); - break; - case EISA_IRQ_11: - rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 11\n"); - break; - case EISA_IRQ_12: - rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 12\n"); - break; - case EISA_IRQ_14: - rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 14\n"); - break; - case EISA_IRQ_15: - rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 15\n"); - break; - case EISA_POLLED: - rio_dprintk (RIO_DEBUG_INIT, "EISA POLLED\n"); - break; - default: - rio_dprintk (RIO_DEBUG_INIT, NULL,DBG_INIT|DBG_FAIL,"Shagged interrupt number!\n"); - Ivec &= EISA_CONTROL_MASK; - } -#endif - - if ( (Ivec & EISA_INTERRUPT_MASK) == - EISA_POLLED ) - { - RIOWillPoll = 1; - break; /* From EisaSlot loop */ - } - } - } - - /* - ** Do it all again now we know whether to change all cards to polled - ** mode or not - */ - - for ( EisaSlot=1; EisaSlot<=RIO_MAX_EISA_SLOTS; EisaSlot++ ) - { - Ident = (INBZ(EisaSlot,EISA_PRODUCT_IDENT_HI)<<8) | - INBZ(EisaSlot,EISA_PRODUCT_IDENT_LO); - - if ( Ident == RIO_EISA_IDENT ) - { - if ( INBZ(EisaSlot,EISA_PRODUCT_NUMBER) != RIO_EISA_PRODUCT_CODE ) - continue; /* next slot */ - - /* - ** Its a Specialix RIO! - */ - - /* - ** Ensure that the enable bit is set! - */ - OUTBZ( EisaSlot, EISA_ENABLE, RIO_EISA_ENABLE_BIT ); - - /* - ** EISA_INTERRUPT_VEC contains the interrupt vector. - */ - Ivec = INBZ(EisaSlot,EISA_INTERRUPT_VEC); - - if ( RIOWillPoll ) - { - /* - ** If we are going to operate in polled mode, but this - ** board is configured to be interrupt driven, display - ** the message explaining the situation to the punter, - ** assuming we haven't already done so. - */ - - if ( !PollIntMixMsgDone && - (Ivec & EISA_INTERRUPT_MASK) != EISA_POLLED ) - { - Rprintf(RIOMesgAllPolled); - PollIntMixMsgDone = 1; - } - - /* - ** Ungraciously ignore whatever the board reports as its - ** interrupt vector... - */ - - Ivec &= ~EISA_INTERRUPT_MASK; - - /* - ** ...and force it to dance to the poll tune. - */ - - Ivec |= EISA_POLLED; - } - - /* - ** Convert the IRQ enable mask into something useful (0-15) - */ - Ivec = RIOEisaToIvec(Ivec); - - rio_dprintk (RIO_DEBUG_INIT, "EISA host in slot %d has Ivec 0x%x\n", - EisaSlot, Ivec); - - /* - ** Find the physical address - */ - Paddr = (INBZ(EisaSlot,EISA_MEMORY_BASE_HI)<<24) | - (INBZ(EisaSlot,EISA_MEMORY_BASE_LO)<<16); - - rio_dprintk (RIO_DEBUG_INIT, "EISA card has Ivec %d Addr %x\n", Ivec, Paddr); - - if ( Paddr == 0 ) - { - rio_dprintk (RIO_DEBUG_INIT, - "Board in slot %d configured for address zero!\n", EisaSlot); - continue; - } - - /* - ** Tell the memory mapper that we want to talk to it - */ - rio_dprintk (RIO_DEBUG_INIT, "About to map EISA card \n"); - - if (RIOMapin( Paddr, RIO_EISA_MEM_SIZE, &Caddr) == -1) { - rio_dprintk (RIO_DEBUG_INIT, "Couldn't map %d bytes at %x\n", - RIO_EISA_MEM_SIZE,Paddr); - continue; - } - - rio_dprintk (RIO_DEBUG_INIT, "Board mapped to vaddr 0x%x\n", Caddr); - - /* - ** And check that it is actually there! - */ - if ( RIOBoardTest( Paddr,Caddr,RIO_EISA,EisaSlot) == RIO_SUCCESS ) - { - rio_dprintk (RIO_DEBUG_INIT, "Board has passed test\n"); - rio_dprintk (RIO_DEBUG_INIT, - "Slot %d. Ivec %d. Type %d. Paddr 0x%x. Caddr 0x%x. Mode 0x%x.\n", - EisaSlot,Ivec,RIO_EISA,Paddr,Caddr,Mode); - - /* - ** Board has passed its scrub test. Fill in all the - ** transient stuff. - */ - p->RIOHosts[RIONumHosts].Slot = EisaSlot; - p->RIOHosts[RIONumHosts].Ivec = Ivec; - p->RIOHosts[RIONumHosts].Type = RIO_EISA; - p->RIOHosts[RIONumHosts].Copy = bcopy; - p->RIOHosts[RIONumHosts].PaddrP = Paddr; - p->RIOHosts[RIONumHosts].Caddr = Caddr; - p->RIOHosts[RIONumHosts].CardP = (struct DpRam *)Caddr; - p->RIOHosts[RIONumHosts].Mode = Mode; - /* - ** because the EISA prom is mapped into IO space, we - ** need to copy the unqiue number into the memory area - ** that it would have occupied, so that the download - ** code can determine its ID and card type. - */ - WBYTE(p->RIOHosts[RIONumHosts].Unique[0],INBZ(EisaSlot,EISA_UNIQUE_NUM_0)); - WBYTE(p->RIOHosts[RIONumHosts].Unique[1],INBZ(EisaSlot,EISA_UNIQUE_NUM_1)); - WBYTE(p->RIOHosts[RIONumHosts].Unique[2],INBZ(EisaSlot,EISA_UNIQUE_NUM_2)); - WBYTE(p->RIOHosts[RIONumHosts].Unique[3],INBZ(EisaSlot,EISA_UNIQUE_NUM_3)); - p->RIOHosts[RIONumHosts].UniqueNum = - ((RBYTE(p->RIOHosts[RIONumHosts].Unique[0])&0xFF)<<0)| - ((RBYTE(p->RIOHosts[RIONumHosts].Unique[1])&0xFF)<<8)| - ((RBYTE(p->RIOHosts[RIONumHosts].Unique[2])&0xFF)<<16)| - ((RBYTE(p->RIOHosts[RIONumHosts].Unique[3])&0xFF)<<24); - INBZ(EisaSlot,EISA_INTERRUPT_RESET); - RIONumHosts++; - ret++; - } - else - { - /* - ** It failed the test, so ignore it. - */ - rio_dprintk (RIO_DEBUG_INIT, "TEST FAILED\n"); - - RIOMapout(Paddr, RIO_EISA_MEM_SIZE, Caddr ); - } - } - } - if (RIOMachineType & RIO_EISA) - return ret+1; - return ret; -} -#endif - - -#ifndef linux - -#define CONFIG_ADDRESS 0xcf8 -#define CONFIG_DATA 0xcfc -#define FORWARD_REG 0xcfa - - -static int -read_config(int bus_number, int device_num, int r_number) -{ - unsigned int cav; - unsigned int val; - -/* - Build config_address_value: - - 31 24 23 16 15 11 10 8 7 0 - ------------------------------------------------------ - |1| 0000000 | bus_number | device # | 000 | register | - ------------------------------------------------------ -*/ - - cav = r_number & 0xff; - cav |= ((device_num & 0x1f) << 11); - cav |= ((bus_number & 0xff) << 16); - cav |= 0x80000000; /* Enable bit */ - outpd(CONFIG_ADDRESS,cav); - val = inpd(CONFIG_DATA); - outpd(CONFIG_ADDRESS,0); - return val; -} - -static -write_config(bus_number,device_num,r_number,val) -{ - unsigned int cav; - -/* - Build config_address_value: - - 31 24 23 16 15 11 10 8 7 0 - ------------------------------------------------------ - |1| 0000000 | bus_number | device # | 000 | register | - ------------------------------------------------------ -*/ - - cav = r_number & 0xff; - cav |= ((device_num & 0x1f) << 11); - cav |= ((bus_number & 0xff) << 16); - cav |= 0x80000000; /* Enable bit */ - outpd(CONFIG_ADDRESS, cav); - outpd(CONFIG_DATA, val); - outpd(CONFIG_ADDRESS, 0); - return val; -} -#else -/* XXX Implement these... */ -static int -read_config(int bus_number, int device_num, int r_number) -{ - return 0; -} - -static int -write_config(int bus_number, int device_num, int r_number) -{ - return 0; -} - -#endif - -int -RIOPCIinit(p, Mode) -struct rio_info *p; -int Mode; -{ - #define MAX_PCI_SLOT 32 - #define RIO_PCI_JET_CARD 0x200011CB - - static int slot; /* count of machine's PCI slots searched so far */ - caddr_t Caddr; /* Virtual address of the current PCI host card. */ - unsigned char Ivec; /* interrupt vector for the current PCI host */ - unsigned long Paddr; /* Physical address for the current PCI host */ - int Handle; /* Handle to Virtual memory allocated for current PCI host */ - - - rio_dprintk (RIO_DEBUG_INIT, "Search for a RIO PCI card - start at slot %d\n", slot); - - /* - ** Initialise the search status - */ - p->RIOLastPCISearch = RIO_FAIL; - - while ( (slot < MAX_PCI_SLOT) & (p->RIOLastPCISearch != RIO_SUCCESS) ) - { - rio_dprintk (RIO_DEBUG_INIT, "Currently testing slot %d\n", slot); - - if (read_config(0,slot,0) == RIO_PCI_JET_CARD) { - p->RIOHosts[p->RIONumHosts].Ivec = 0; - Paddr = read_config(0,slot,0x18); - Paddr = Paddr - (Paddr & 0x1); /* Mask off the io bit */ - - if ( (Paddr == 0) || ((Paddr & 0xffff0000) == 0xffff0000) ) { - rio_dprintk (RIO_DEBUG_INIT, "Goofed up slot\n"); /* what! */ - slot++; - continue; - } - - p->RIOHosts[p->RIONumHosts].PaddrP = Paddr; - Ivec = (read_config(0,slot,0x3c) & 0xff); - - rio_dprintk (RIO_DEBUG_INIT, "PCI Host at 0x%x, Intr %d\n", (int)Paddr, Ivec); - - Handle = RIOMapin( Paddr, RIO_PCI_MEM_SIZE, &Caddr ); - if (Handle == -1) { - rio_dprintk (RIO_DEBUG_INIT, "Couldn't map %d bytes at 0x%x\n", RIO_PCI_MEM_SIZE, (int)Paddr); - slot++; - continue; - } - p->RIOHosts[p->RIONumHosts].Ivec = Ivec + 32; - p->intr_tid = iointset(p->RIOHosts[p->RIONumHosts].Ivec, - (int (*)())rio_intr, (char *)p->RIONumHosts); - if (RIOBoardTest( Paddr, Caddr, RIO_PCI, 0 ) == RIO_SUCCESS) { - rio_dprintk (RIO_DEBUG_INIT, ("Board has passed test\n"); - rio_dprintk (RIO_DEBUG_INIT, ("Paddr 0x%x. Caddr 0x%x. Mode 0x%x.\n", Paddr, Caddr, Mode); - - /* - ** Board has passed its scrub test. Fill in all the - ** transient stuff. - */ - p->RIOHosts[p->RIONumHosts].Slot = 0; - p->RIOHosts[p->RIONumHosts].Ivec = Ivec + 32; - p->RIOHosts[p->RIONumHosts].Type = RIO_PCI; - p->RIOHosts[p->RIONumHosts].Copy = rio_pcicopy; - p->RIOHosts[p->RIONumHosts].PaddrP = Paddr; - p->RIOHosts[p->RIONumHosts].Caddr = Caddr; - p->RIOHosts[p->RIONumHosts].CardP = (struct DpRam *)Caddr; - p->RIOHosts[p->RIONumHosts].Mode = Mode; - -#if 0 - WBYTE(p->RIOHosts[p->RIONumHosts].Control, - BOOT_FROM_RAM | EXTERNAL_BUS_OFF | - p->RIOHosts[p->RIONumHosts].Mode | - INTERRUPT_DISABLE ); - WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt,0xff); - WBYTE(p->RIOHosts[p->RIONumHosts].Control, - BOOT_FROM_RAM | EXTERNAL_BUS_OFF | - p->RIOHosts[p->RIONumHosts].Mode | - INTERRUPT_DISABLE ); - WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt,0xff); -#else - WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff); -#endif - p->RIOHosts[p->RIONumHosts].UniqueNum = - ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0])&0xFF)<<0)| - ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1])&0xFF)<<8)| - ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2])&0xFF)<<16)| - ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3])&0xFF)<<24); - - rio_dprintk (RIO_DEBUG_INIT, "Unique no 0x%x.\n", - p->RIOHosts[p->RIONumHosts].UniqueNum); - - p->RIOLastPCISearch = RIO_SUCCESS; - p->RIONumHosts++; - } - } - slot++; - } - - if ( slot >= MAX_PCI_SLOT ) { - rio_dprintk (RIO_DEBUG_INIT, "All %d PCI slots have tested for RIO cards !!!\n", - MAX_PCI_SLOT); - } - - - /* - ** I don't think we want to do this anymore - ** - - if (!p->RIOLastPCISearch == RIO_FAIL ) { - p->RIOFailed++; - } - - ** - */ -} - -#ifdef FUTURE_RELEASE -void riohalt( void ) -{ - int host; - for ( host=0; hostRIONumHosts; host++ ) - { - rio_dprintk (RIO_DEBUG_INIT, "Stop host %d\n", host); - (void)RIOBoardTest( p->RIOHosts[host].PaddrP, p->RIOHosts[host].Caddr, p->RIOHosts[host].Type,p->RIOHosts[host].Slot ); - } -} -#endif -#endif static uchar val[] = { #ifdef VERY_LONG_TEST @@ -1262,200 +387,6 @@ int size; return RIO_SUCCESS; } -/* -** try to ensure that every host is either in polled mode -** or is in interrupt mode. Only allow interrupt mode if -** all hosts can interrupt (why?) -** and force into polled mode if told to. Patch up the -** interrupt vector & salute The Queen when you've done. -*/ -#if 0 -static void -RIOAllocateInterrupts(p) -struct rio_info * p; -{ - int Host; - - /* - ** Easy case - if we have been told to poll, then we poll. - */ - if (p->mode & POLLED_MODE) { - RIOStopInterrupts(p, 0, 0); - return; - } - - /* - ** check - if any host has been set to polled mode, then all must be. - */ - for (Host=0; HostRIONumHosts; Host++) { - if ( (p->RIOHosts[Host].Type != RIO_AT) && - (p->RIOHosts[Host].Ivec == POLLED) ) { - RIOStopInterrupts(p, 1, Host ); - return; - } - } - for (Host=0; HostRIONumHosts; Host++) { - if (p->RIOHosts[Host].Type == RIO_AT) { - if ( (p->RIOHosts[Host].Ivec - 32) == 0) { - RIOStopInterrupts(p, 2, Host ); - return; - } - } - } -} - -/* -** something has decided that we can't be doing with these -** new-fangled interrupt thingies. Set everything up to just -** poll. -*/ -static void -RIOStopInterrupts(p, Reason, Host) -struct rio_info * p; -int Reason; -int Host; -{ -#ifdef FUTURE_RELEASE - switch (Reason) { - case 0: /* forced into polling by rio_polled */ - break; - case 1: /* SCU has set 'Host' into polled mode */ - break; - case 2: /* there aren't enough interrupt vectors for 'Host' */ - break; - } -#endif - - for (Host=0; HostRIONumHosts; Host++ ) { - struct Host *HostP = &p->RIOHosts[Host]; - - switch (HostP->Type) { - case RIO_AT: - /* - ** The AT host has it's interrupts disabled by clearing the - ** int_enable bit. - */ - HostP->Mode &= ~INTERRUPT_ENABLE; - HostP->Ivec = POLLED; - break; -#ifdef FUTURE_RELEASE - case RIO_EISA: - /* - ** The EISA host has it's interrupts disabled by setting the - ** Ivec to zero - */ - HostP->Ivec = POLLED; - break; -#endif - case RIO_PCI: - /* - ** The PCI host has it's interrupts disabled by clearing the - ** int_enable bit, like a regular host card. - */ - HostP->Mode &= ~RIO_PCI_INT_ENABLE; - HostP->Ivec = POLLED; - break; -#ifdef FUTURE_RELEASE - case RIO_MCA: - /* - ** There's always one, isn't there? - ** The MCA host card cannot have it's interrupts disabled. - */ - RIOPatchVec(HostP); - break; -#endif - } - } -} - -/* -** This function is called at init time to setup the data structures. -*/ -void -RIOAllocDataStructs(p) -struct rio_info * p; -{ - int port, - host, - tm; - - p->RIOPortp = (struct Port *)sysbrk(RIO_PORTS * sizeof(struct Port)); - if (!p->RIOPortp) { - rio_dprintk (RIO_DEBUG_INIT, "RIO-init: No memory for port structures\n"); - p->RIOFailed++; - return; - } - bzero( p->RIOPortp, sizeof(struct Port) * RIO_PORTS ); - rio_dprintk (RIO_DEBUG_INIT, "RIO-init: allocated and cleared memory for port structs\n"); - rio_dprintk (RIO_DEBUG_INIT, "First RIO port struct @0x%x, size=0x%x bytes\n", - (int)p->RIOPortp, sizeof(struct Port)); - - for( port=0; portRIOPortp[port].PortNum = port; - p->RIOPortp[port].TtyP = &p->channel[port]; - sreset (p->RIOPortp[port].InUse); /* Let the first guy uses it */ - p->RIOPortp[port].portSem = -1; /* Let the first guy takes it */ - p->RIOPortp[port].ParamSem = -1; /* Let the first guy takes it */ - p->RIOPortp[port].timeout_id = 0; /* Let the first guy takes it */ - } - - p->RIOHosts = (struct Host *)sysbrk(RIO_HOSTS * sizeof(struct Host)); - if (!p->RIOHosts) { - rio_dprintk (RIO_DEBUG_INIT, "RIO-init: No memory for host structures\n"); - p->RIOFailed++; - return; - } - bzero(p->RIOHosts, sizeof(struct Host)*RIO_HOSTS); - rio_dprintk (RIO_DEBUG_INIT, "RIO-init: allocated and cleared memory for host structs\n"); - rio_dprintk (RIO_DEBUG_INIT, "First RIO host struct @0x%x, size=0x%x bytes\n", - (int)p->RIOHosts, sizeof(struct Host)); - - for( host=0; hostRIOHosts[host].HostLock); - p->RIOHosts[host].timeout_id = 0; /* Let the first guy takes it */ - } - /* - ** check that the buffer size is valid, round down to the next power of - ** two if necessary; if the result is zero, then, hey, no double buffers. - */ - for ( tm = 1; tm && tm <= p->RIOConf.BufferSize; tm <<= 1 ) - ; - tm >>= 1; - p->RIOBufferSize = tm; - p->RIOBufferMask = tm ? tm - 1 : 0; -} - -/* -** this function gets called whenever the data structures need to be -** re-setup, for example, after a riohalt (why did I ever invent it?) -*/ -void -RIOSetupDataStructs(p) -struct rio_info * p; -{ - int host, entry, rup; - - for ( host=0; hostRIOHosts[host]; - for ( entry=0; entryTopology[entry].Unit = ROUTE_DISCONNECT; - HostP->Topology[entry].Link = NO_LINK; - } - bcopy("HOST X", HostP->Name, 7); - HostP->Name[5] = '1'+host; - for (rup=0; rup<(MAX_RUP + LINKS_PER_UNIT); rup++) { - if (rup < MAX_RUP) { - for (entry=0; entryMapping[rup].Topology[entry].Unit = ROUTE_DISCONNECT; - HostP->Mapping[rup].Topology[entry].Link = NO_LINK; - } - RIODefaultName(p, HostP, rup); - } - spin_lock_init(&HostP->UnixRups[rup].RupLock); - } - } -} -#endif int RIODefaultName(p, HostP, UnitId) @@ -1463,10 +394,6 @@ struct rio_info * p; struct Host * HostP; uint UnitId; { -#ifdef CHECK - CheckHost( Host ); - CheckUnitId( UnitId ); -#endif bcopy("UNKNOWN RTA X-XX",HostP->Mapping[UnitId].Name,17); HostP->Mapping[UnitId].Name[12]='1'+(HostP-p->RIOHosts); if ((UnitId+1) > 9) { @@ -1483,33 +410,6 @@ uint UnitId; #define RIO_RELEASE "Linux" #define RELEASE_ID "1.0" -#if 0 -static int -RIOReport(p) -struct rio_info * p; -{ - char * RIORelease = RIO_RELEASE; - char * RIORelID = RELEASE_ID; - int host; - - rio_dprintk (RIO_DEBUG_INIT, "RIO : Release: %s ID: %s\n", RIORelease, RIORelID); - - if ( p->RIONumHosts==0 ) { - rio_dprintk (RIO_DEBUG_INIT, "\nNo Hosts configured\n"); - return(0); - } - - for ( host=0; host < p->RIONumHosts; host++ ) { - struct Host *HostP = &p->RIOHosts[host]; - switch ( HostP->Type ) { - case RIO_AT: - rio_dprintk (RIO_DEBUG_INIT, "AT BUS : found the card at 0x%x\n", HostP->PaddrP); - } - } - return 0; -} -#endif - static struct rioVersion stVersion; struct rioVersion * @@ -1523,27 +423,6 @@ RIOVersid(void) return &stVersion; } -#if 0 -int -RIOMapin(paddr, size, vaddr) -paddr_t paddr; -int size; -caddr_t * vaddr; -{ - *vaddr = (caddr_t)permap( (long)paddr, size); - return ((int)*vaddr); -} - -void -RIOMapout(paddr, size, vaddr) -paddr_t paddr; -long size; -caddr_t vaddr; -{ -} -#endif - - void RIOHostReset(Type, DpRamP, Slot) uint Type; @@ -1570,31 +449,6 @@ uint Slot; WBYTE(DpRamP->DpResetTpu, 0xFF); udelay(3); break; -#ifdef FUTURE_RELEASE - case RIO_EISA: - /* - ** Bet this doesn't work! - */ - OUTBZ( Slot, EISA_CONTROL_PORT, - EISA_TP_RUN | EISA_TP_BUS_DISABLE | - EISA_TP_SLOW_LINKS | EISA_TP_BOOT_FROM_RAM ); - OUTBZ( Slot, EISA_CONTROL_PORT, - EISA_TP_RESET | EISA_TP_BUS_DISABLE | - EISA_TP_SLOW_LINKS | EISA_TP_BOOT_FROM_RAM ); - suspend( 3 ); - OUTBZ( Slot, EISA_CONTROL_PORT, - EISA_TP_RUN | EISA_TP_BUS_DISABLE | - EISA_TP_SLOW_LINKS | EISA_TP_BOOT_FROM_RAM ); - break; - case RIO_MCA: - WBYTE(DpRamP->DpControl , McaTpBootFromRam | McaTpBusDisable ); - WBYTE(DpRamP->DpResetTpu , 0xFF ); - suspend( 3 ); - WBYTE(DpRamP->DpControl , McaTpBootFromRam | McaTpBusDisable ); - WBYTE(DpRamP->DpResetTpu , 0xFF ); - suspend( 3 ); - break; -#endif case RIO_PCI: rio_dprintk (RIO_DEBUG_INIT, " (RIO_PCI)\n"); DpRamP->DpControl = RIO_PCI_BOOT_FROM_RAM; @@ -1604,12 +458,6 @@ uint Slot; /* for (i=0; i<6000; i++); */ /* suspend( 3 ); */ break; -#ifdef FUTURE_RELEASE - default: - Rprintf(RIOMesgNoSupport,Type,DpRamP,Slot); - return; -#endif - default: rio_dprintk (RIO_DEBUG_INIT, " (UNKNOWN)\n"); break; -- GitLab From f099bfb7089735ad1760b3c6938069af10a88cc0 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 17:18:05 +0000 Subject: [PATCH 437/465] [PATCH] Remove unused code from rioboot.h Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/rio/rioboot.c | 61 -------------------------------------- 1 file changed, 61 deletions(-) diff --git a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c index 34cbb13aad4..92df43552f1 100644 --- a/drivers/char/rio/rioboot.c +++ b/drivers/char/rio/rioboot.c @@ -665,13 +665,6 @@ struct PKT *PacketP; struct CmdBlk *CmdBlkP; uint sequence; -#ifdef CHECK - CheckHost(Host); - CheckRup(Rup); - CheckHostP(HostP); - CheckPacketP(PacketP); -#endif - /* ** If we haven't been told what to boot, we can't boot it. */ @@ -956,11 +949,6 @@ static int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, st MyType = "RTA"; MyName = HostP->Mapping[Rup].Name; } -#ifdef CHECK - CheckString(MyType); - CheckString(MyName); -#endif - MyLink = RBYTE(PktCmdP->LinkNum); /* @@ -1309,52 +1297,3 @@ struct Host *HostP; } } -#if 0 -/* - Function: This function is to disable the disk interrupt - Returns : Nothing -*/ -void -disable_interrupt(vector) -int vector; -{ - int ps; - int val; - - disable(ps); - if (vector > 40) { - val = 1 << (vector - 40); - __outb(S8259+1, __inb(S8259+1) | val); - } - else { - val = 1 << (vector - 32); - __outb(M8259+1, __inb(M8259+1) | val); - } - restore(ps); -} - -/* - Function: This function is to enable the disk interrupt - Returns : Nothing -*/ -void -enable_interrupt(vector) -int vector; -{ - int ps; - int val; - - disable(ps); - if (vector > 40) { - val = 1 << (vector - 40); - val = ~val; - __outb(S8259+1, __inb(S8259+1) & val); - } - else { - val = 1 << (vector - 32); - val = ~val; - __outb(M8259+1, __inb(M8259+1) & val); - } - restore(ps); -} -#endif -- GitLab From 8b03de1f667a5c15d1e4d50318a27a67669f8980 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 17:19:52 +0000 Subject: [PATCH 438/465] [PATCH] Remove unused code from rioroute.h Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/rio/rioroute.c | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/drivers/char/rio/rioroute.c b/drivers/char/rio/rioroute.c index 0f4cd33ba64..f98888f5265 100644 --- a/drivers/char/rio/rioroute.c +++ b/drivers/char/rio/rioroute.c @@ -112,15 +112,6 @@ int RIORouteRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP) int Lies; unsigned long flags; -#ifdef STACK - RIOStackCheck("RIORouteRup"); -#endif -#ifdef CHECK - CheckPacketP(PacketP); - CheckHostP(HostP); - CheckRup(Rup); - CheckHost(Host); -#endif /* ** Is this unit telling us it's current link topology? */ @@ -540,9 +531,6 @@ uint unit; for (port = 0; port < PORTS_PER_RTA; port++, PortN++) { ushort dest_port = port + 8; -#if 0 - uint PktInt; -#endif WORD *TxPktP; PKT *Pkt; @@ -623,10 +611,6 @@ uint UnitId; unsigned long flags; rio_spin_lock_irqsave(&HostP->HostLock, flags); -#ifdef CHECK - CheckHostP(HostP); - CheckUnitId(UnitId); -#endif if (RIOCheck(HostP, UnitId)) { rio_dprintk(RIO_DEBUG_ROUTE, "Unit %d is NOT isolated\n", UnitId); rio_spin_unlock_irqrestore(&HostP->HostLock, flags); @@ -651,10 +635,6 @@ uint UnitId; { uint link, unit; -#ifdef CHECK - CheckHostP(HostP); - CheckUnitId(UnitId); -#endif UnitId--; /* this trick relies on the Unit Id being UNSIGNED! */ if (UnitId >= MAX_RUP) /* dontcha just lurv unsigned maths! */ @@ -684,10 +664,6 @@ uint UnitId; { unsigned char link; -#ifdef CHECK - CheckHostP(HostP); - CheckUnitId(UnitId); -#endif /* rio_dprint(RIO_DEBUG_ROUTE, ("Check to see if unit %d has a route to the host\n",UnitId)); */ rio_dprintk(RIO_DEBUG_ROUTE, "RIOCheck : UnitID = %d\n", UnitId); -- GitLab From 283c9d546ed7506b03f0d9da4441145aa5f2f6f9 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 17:21:25 +0000 Subject: [PATCH 439/465] [PATCH] Remove unused CHECK code from riocmd.c Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/rio/riocmd.c | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c index b97dd9fdb6b..694bfb9d937 100644 --- a/drivers/char/rio/riocmd.c +++ b/drivers/char/rio/riocmd.c @@ -387,12 +387,6 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * func_enter(); -#ifdef CHECK - CheckHost(Host); - CheckHostP(HostP); - CheckPacketP(PacketP); -#endif - /* ** 16 port RTA note: ** Command rup packets coming from the RTA will have pkt->data[1] (which @@ -406,10 +400,6 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * SysPort = UnixRupP->BaseSysPort + (RBYTE(PktCmdP->PhbNum) % (ushort) PORTS_PER_RTA); rio_dprintk(RIO_DEBUG_CMD, "Command on rup %d, port %d\n", rup, SysPort); -#ifdef CHECK - CheckRup(rup); - CheckUnixRupP(UnixRupP); -#endif if (UnixRupP->BaseSysPort == NO_PORT) { rio_dprintk(RIO_DEBUG_CMD, "OBSCURE ERROR!\n"); rio_dprintk(RIO_DEBUG_CMD, "Diagnostics follow. Please WRITE THESE DOWN and report them to Specialix Technical Support\n"); @@ -429,9 +419,6 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * rio_dprintk(RIO_DEBUG_CMD, "COMMAND information: Host Port Number 0x%x, " "Command Code 0x%x\n", PktCmdP->PhbNum, PktCmdP->Command); return TRUE; } -#ifdef CHECK - CheckSysPort(SysPort); -#endif PortP = p->RIOPortp[SysPort]; rio_spin_lock_irqsave(&PortP->portSem, flags); switch (RBYTE(PktCmdP->Command)) { @@ -604,11 +591,6 @@ int RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP) struct UnixRup *UnixRupP; unsigned long flags; -#ifdef CHECK - CheckHostP(HostP); - CheckRup(Rup); - CheckCmdBlkP(CmdBlkP); -#endif if (Rup >= (ushort) (MAX_RUP + LINKS_PER_UNIT)) { rio_dprintk(RIO_DEBUG_CMD, "Illegal rup number %d in RIOQueueCmdBlk\n", Rup); RIOFreeCmdBlk(CmdBlkP); @@ -806,9 +788,6 @@ void RIOPollHostCommands(struct rio_info *p, struct Host *HostP) ** If it returns RIO_FAIL then don't ** send this command yet! */ -#ifdef CHECK - CheckCmdBlkP(CmdBlkP); -#endif if (!(CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP) (CmdBlkP->PreArg, CmdBlkP) : TRUE)) { rio_dprintk(RIO_DEBUG_CMD, "Not ready to start command 0x%x\n", (int) CmdBlkP); } else { @@ -816,9 +795,6 @@ void RIOPollHostCommands(struct rio_info *p, struct Host *HostP) /* ** Whammy! blat that pack! */ -#ifdef CHECK - CheckPacketP((PKT *) RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt)); -#endif HostP->Copy((caddr_t) & CmdBlkP->Packet, RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt), sizeof(PKT)); /* @@ -852,9 +828,6 @@ int RIOWFlushMark(int iPortP, struct CmdBlk *CmdBlkP) unsigned long flags; rio_spin_lock_irqsave(&PortP->portSem, flags); -#ifdef CHECK - CheckPortP(PortP); -#endif PortP->WflushFlag++; PortP->MagicFlags |= MAGIC_FLUSH; rio_spin_unlock_irqrestore(&PortP->portSem, flags); @@ -894,9 +867,6 @@ int RIOUnUse(int iPortP, struct CmdBlk *CmdBlkP) rio_spin_lock_irqsave(&PortP->portSem, flags); -#ifdef CHECK - CheckPortP(PortP); -#endif rio_dprintk(RIO_DEBUG_CMD, "Decrement in use count for port\n"); if (PortP->InUse) { -- GitLab From 542ea6c37c2a77f7523c0703c326b8a9af2892bc Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 17:24:47 +0000 Subject: [PATCH 440/465] [PATCH] Remove unused code from rio_linux.c Signed-off-by: Linus Torvalds --- drivers/char/rio/rio_linux.c | 60 ------------------------------------ 1 file changed, 60 deletions(-) diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c index 8825bd61b7d..c9af283a811 100644 --- a/drivers/char/rio/rio_linux.c +++ b/drivers/char/rio/rio_linux.c @@ -132,16 +132,6 @@ more than 512 ports.... */ */ #define IRQ_RATE_LIMIT 200 -#if 0 -/* Not implemented */ -/* - * The following defines are mostly for testing purposes. But if you need - * some nice reporting in your syslog, you can define them also. - */ -#define RIO_REPORT_FIFO -#define RIO_REPORT_OVERRUN -#endif - /* These constants are derived from SCO Source */ static struct Conf @@ -573,21 +563,6 @@ static void rio_shutdown_port(void *ptr) PortP = (struct Port *) ptr; PortP->gs.tty = NULL; -#if 0 - port->gs.flags &= ~GS_ACTIVE; - if (!port->gs.tty) { - rio_dprintk(RIO_DBUG_TTY, "No tty.\n"); - return; - } - if (!port->gs.tty->termios) { - rio_dprintk(RIO_DEBUG_TTY, "No termios.\n"); - return; - } - if (port->gs.tty->termios->c_cflag & HUPCL) { - rio_setsignals(port, 0, 0); - } -#endif - func_exit(); } @@ -663,11 +638,6 @@ static int rio_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd rc = 0; switch (cmd) { -#if 0 - case TIOCGSOFTCAR: - rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0), (unsigned int *) arg); - break; -#endif case TIOCSSOFTCAR: if ((rc = get_user(ival, (unsigned int *) arg)) == 0) { tty->termios->c_cflag = (tty->termios->c_cflag & ~CLOCAL) | (ival ? CLOCAL : 0); @@ -709,36 +679,6 @@ static int rio_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd if (access_ok(VERIFY_READ, (void *) arg, sizeof(struct serial_struct))) rc = gs_setserial(&PortP->gs, (struct serial_struct *) arg); break; -#if 0 - /* - * note: these IOCTLs no longer reach here. Use - * tiocmset/tiocmget driver methods instead. The - * #if 0 disablement predates this comment. - */ - case TIOCMGET: - rc = -EFAULT; - if (access_ok(VERIFY_WRITE, (void *) arg, sizeof(unsigned int))) { - rc = 0; - ival = rio_getsignals(port); - put_user(ival, (unsigned int *) arg); - } - break; - case TIOCMBIS: - if ((rc = get_user(ival, (unsigned int *) arg)) == 0) { - rio_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1), ((ival & TIOCM_RTS) ? 1 : -1)); - } - break; - case TIOCMBIC: - if ((rc = get_user(ival, (unsigned int *) arg)) == 0) { - rio_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1), ((ival & TIOCM_RTS) ? 0 : -1)); - } - break; - case TIOCMSET: - if ((rc = get_user(ival, (unsigned int *) arg)) == 0) { - rio_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0), ((ival & TIOCM_RTS) ? 1 : 0)); - } - break; -#endif default: rc = -ENOIOCTLCMD; break; -- GitLab From 1384cee55d326e806158cea4b983ef2a9d26e035 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 17:25:42 +0000 Subject: [PATCH 441/465] [PATCH] Remove rio_table.c unused code Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/rio/riotable.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/char/rio/riotable.c b/drivers/char/rio/riotable.c index 42c3dffcbbb..a86b216ab65 100644 --- a/drivers/char/rio/riotable.c +++ b/drivers/char/rio/riotable.c @@ -754,11 +754,6 @@ struct Map *HostMapP; ushort RtaType; unsigned long flags; -#ifdef CHECK - CheckHostP(HostP); - CheckHostMapP(HostMapP); -#endif - rio_dprintk(RIO_DEBUG_TABLE, "Mapping sysport %d to id %d\n", (int) HostMapP->SysPort, HostMapP->ID); /* @@ -784,9 +779,6 @@ struct Map *HostMapP; rio_dprintk(RIO_DEBUG_TABLE, "c1 p = %p, p->rioPortp = %p\n", p, p->RIOPortp); PortP = p->RIOPortp[SysPort]; -#if 0 - PortP->TtyP = &p->channel[SysPort]; -#endif rio_dprintk(RIO_DEBUG_TABLE, "Map port\n"); /* -- GitLab From f4caf1606d3bbe3a790997e3dc5bb2779c6b7daf Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Jan 2006 17:27:38 +0000 Subject: [PATCH 442/465] [PATCH] Remove unused code from rioctrl.c (Last for this batch of work) Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/rio/rioctrl.c | 111 +------------------------------------ 1 file changed, 1 insertion(+), 110 deletions(-) diff --git a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c index 0b7700d2f04..fcf18a06122 100644 --- a/drivers/char/rio/rioctrl.c +++ b/drivers/char/rio/rioctrl.c @@ -308,12 +308,7 @@ int su; } case RIO_DEBUG_MEM: -#ifdef DEBUG_MEM_SUPPORT - RIO_DEBUG_CTRL, if (su) - return rio_RIODebugMemory(RIO_DEBUG_CTRL, arg); - else -#endif - return -EPERM; + return -EPERM; case RIO_ALL_MODEM: rio_dprintk(RIO_DEBUG_CTRL, "RIO_ALL_MODEM\n"); @@ -591,12 +586,7 @@ int su; case RIO_GET_LOG: rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_LOG\n"); -#ifdef LOGGING - RIOGetLog(arg); - return 0; -#else return -EINVAL; -#endif case RIO_GET_MODTYPE: if (copyin((int) arg, (caddr_t) & port, sizeof(uint)) == COPYFAIL) { @@ -684,52 +674,6 @@ int su; rio_dprintk(RIO_DEBUG_CTRL, "entering loop (%d %d)!\n", PortSetup.From, PortSetup.To); for (loop = PortSetup.From; loop <= PortSetup.To; loop++) { rio_dprintk(RIO_DEBUG_CTRL, "in loop (%d)!\n", loop); -#if 0 - PortP = p->RIOPortp[loop]; - if (!PortP->TtyP) - PortP->TtyP = &p->channel[loop]; - - rio_spin_lock_irqsave(&PortP->portSem, flags); - if (PortSetup.IxAny) - PortP->Config |= RIO_IXANY; - else - PortP->Config &= ~RIO_IXANY; - if (PortSetup.IxOn) - PortP->Config |= RIO_IXON; - else - PortP->Config &= ~RIO_IXON; - - /* - ** If the port needs to wait for all a processes output - ** to drain before closing then this flag will be set. - */ - if (PortSetup.Drain) { - PortP->Config |= RIO_WAITDRAIN; - } else { - PortP->Config &= ~RIO_WAITDRAIN; - } - /* - ** Store settings if locking or unlocking port or if the - ** port is not locked, when setting the store option. - */ - if (PortP->Mapped && ((PortSetup.Lock && !PortP->Lock) || (!PortP->Lock && (PortSetup.Store && !PortP->Store)))) { - PortP->StoredTty.iflag = PortP->TtyP->tm.c_iflag; - PortP->StoredTty.oflag = PortP->TtyP->tm.c_oflag; - PortP->StoredTty.cflag = PortP->TtyP->tm.c_cflag; - PortP->StoredTty.lflag = PortP->TtyP->tm.c_lflag; - PortP->StoredTty.line = PortP->TtyP->tm.c_line; - bcopy(PortP->TtyP->tm.c_cc, PortP->StoredTty.cc, NCC + 5); - } - PortP->Lock = PortSetup.Lock; - PortP->Store = PortSetup.Store; - PortP->Xprint.XpCps = PortSetup.XpCps; - bcopy(PortSetup.XpOn, PortP->Xprint.XpOn, MAX_XP_CTRL_LEN); - bcopy(PortSetup.XpOff, PortP->Xprint.XpOff, MAX_XP_CTRL_LEN); - PortP->Xprint.XpOn[MAX_XP_CTRL_LEN - 1] = '\0'; - PortP->Xprint.XpOff[MAX_XP_CTRL_LEN - 1] = '\0'; - PortP->Xprint.XpLen = RIOStrlen(PortP->Xprint.XpOn) + RIOStrlen(PortP->Xprint.XpOff); - rio_spin_unlock_irqrestore(&PortP->portSem, flags); -#endif } rio_dprintk(RIO_DEBUG_CTRL, "after loop (%d)!\n", loop); rio_dprintk(RIO_DEBUG_CTRL, "Retval:%x\n", retval); @@ -801,12 +745,6 @@ int su; rio_dprintk(RIO_DEBUG_CTRL, "Port %d\n", PortTty.port); PortP = (p->RIOPortp[PortTty.port]); -#if 0 - PortTty.Tty.tm.c_iflag = PortP->TtyP->tm.c_iflag; - PortTty.Tty.tm.c_oflag = PortP->TtyP->tm.c_oflag; - PortTty.Tty.tm.c_cflag = PortP->TtyP->tm.c_cflag; - PortTty.Tty.tm.c_lflag = PortP->TtyP->tm.c_lflag; -#endif if (copyout((caddr_t) & PortTty, (int) arg, sizeof(struct PortTty)) == COPYFAIL) { p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; @@ -824,15 +762,6 @@ int su; return -ENXIO; } PortP = (p->RIOPortp[PortTty.port]); -#if 0 - rio_spin_lock_irqsave(&PortP->portSem, flags); - PortP->TtyP->tm.c_iflag = PortTty.Tty.tm.c_iflag; - PortP->TtyP->tm.c_oflag = PortTty.Tty.tm.c_oflag; - PortP->TtyP->tm.c_cflag = PortTty.Tty.tm.c_cflag; - PortP->TtyP->tm.c_lflag = PortTty.Tty.tm.c_lflag; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); -#endif - RIOParam(PortP, CONFIG, PortP->State & RIO_MODEM, OK_TO_SLEEP); return retval; @@ -909,23 +838,6 @@ int su; rio_spin_unlock_irqrestore(&PortP->portSem, flags); return retval; -#ifdef DEBUG_SUPPORTED - case RIO_READ_LEVELS: - { - int num; - rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_LEVELS\n"); - for (num = 0; RIODbInf[num].Flag; num++); - rio_dprintk(RIO_DEBUG_CTRL, "%d levels to copy\n", num); - if (copyout((caddr_t) RIODbInf, (int) arg, sizeof(struct DbInf) * (num + 1)) == COPYFAIL) { - rio_dprintk(RIO_DEBUG_CTRL, "ReadLevels Copy failed\n"); - p->RIOError.Error = COPYOUT_FAILED; - return -EFAULT; - } - rio_dprintk(RIO_DEBUG_CTRL, "%d levels to copied\n", num); - return retval; - } -#endif - case RIO_READ_CONFIG: rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_CONFIG\n"); if (copyout((caddr_t) & p->RIOConf, (int) arg, sizeof(struct Conf)) == COPYFAIL) { @@ -1084,30 +996,13 @@ int su; (void) RIOBoardTest(p->RIOHosts[Host].PaddrP, p->RIOHosts[Host].Caddr, p->RIOHosts[Host].Type, p->RIOHosts[Host].Slot); bzero((caddr_t) & p->RIOHosts[Host].Flags, ((int) &p->RIOHosts[Host].____end_marker____) - ((int) &p->RIOHosts[Host].Flags)); p->RIOHosts[Host].Flags = RC_WAITING; -#if 0 - RIOSetupDataStructs(p); -#endif } RIOFoadWakeup(p); p->RIONumBootPkts = 0; p->RIOBooting = 0; - -#ifdef RINGBUFFER_SUPPORT - for (loop = 0; loop < RIO_PORTS; loop++) - if (p->RIOPortp[loop]->TxRingBuffer) - sysfree((void *) p->RIOPortp[loop]->TxRingBuffer, RIOBufferSize); -#endif -#if 0 - bzero((caddr_t) & p->RIOPortp[0], RIO_PORTS * sizeof(struct Port)); -#else printk("HEEEEELP!\n"); -#endif for (loop = 0; loop < RIO_PORTS; loop++) { -#if 0 - p->RIOPortp[loop]->TtyP = &p->channel[loop]; -#endif - spin_lock_init(&p->RIOPortp[loop]->portSem); p->RIOPortp[loop]->InUse = NOT_INUSE; } @@ -1653,10 +1548,6 @@ uchar Cmd; ushort rup; int port; -#ifdef CHECK - CheckPortP(PortP); -#endif - if (PortP->State & RIO_DELETED) { rio_dprintk(RIO_DEBUG_CTRL, "Preemptive command to deleted RTA ignored\n"); return RIO_FAIL; -- GitLab From 2664b25051f7ab96b22b199aa2f5ef6a949a4296 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 16 Jan 2006 23:44:47 -0800 Subject: [PATCH 443/465] Linux v2.6.16-rc1 --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index c3a727126d2..252a659896f 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 -SUBLEVEL = 15 -EXTRAVERSION = +SUBLEVEL = 16 +EXTRAVERSION =-rc1 NAME=Sliding Snow Leopard # *DOCUMENTATION* -- GitLab From 9343e79a7bb2d3268d68997163608b87d58d8098 Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Tue, 17 Jan 2006 02:10:53 -0800 Subject: [PATCH 444/465] [IPV6]: Preserve procfs IPV6 address output format Procfs always output IPV6 addresses without the colon characters, and we cannot change that. Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller --- include/linux/kernel.h | 1 + net/ipv6/addrconf.c | 2 +- net/ipv6/anycast.c | 2 +- net/ipv6/ip6_flowlabel.c | 4 ++-- net/ipv6/mcast.c | 6 +++--- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 323924edb26..a5363324cf9 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -228,6 +228,7 @@ extern void dump_stack(void); ntohs((addr).s6_addr16[6]), \ ntohs((addr).s6_addr16[7]) #define NIP6_FMT "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x" +#define NIP6_SEQFMT "%04x%04x%04x%04x%04x%04x%04x%04x" #if defined(__LITTLE_ENDIAN) #define HIPQUAD(addr) \ diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index dfb4f145a13..d328d598614 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2644,7 +2644,7 @@ static int if6_seq_show(struct seq_file *seq, void *v) { struct inet6_ifaddr *ifp = (struct inet6_ifaddr *)v; seq_printf(seq, - NIP6_FMT " %02x %02x %02x %02x %8s\n", + NIP6_SEQFMT " %02x %02x %02x %02x %8s\n", NIP6(ifp->addr), ifp->idev->dev->ifindex, ifp->prefix_len, diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index 72bd08af2df..840a33d3329 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c @@ -532,7 +532,7 @@ static int ac6_seq_show(struct seq_file *seq, void *v) struct ac6_iter_state *state = ac6_seq_private(seq); seq_printf(seq, - "%-4d %-15s " NIP6_FMT " %5d\n", + "%-4d %-15s " NIP6_SEQFMT " %5d\n", state->dev->ifindex, state->dev->name, NIP6(im->aca_addr), im->aca_users); diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 4183c8dac7f..69cbe8a66d0 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c @@ -629,7 +629,7 @@ static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl) { while(fl) { seq_printf(seq, - "%05X %-1d %-6d %-6d %-6ld %-8ld " NIP6_FMT " %-4d\n", + "%05X %-1d %-6d %-6d %-6ld %-8ld " NIP6_SEQFMT " %-4d\n", (unsigned)ntohl(fl->label), fl->share, (unsigned)fl->owner, @@ -645,7 +645,7 @@ static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl) static int ip6fl_seq_show(struct seq_file *seq, void *v) { if (v == SEQ_START_TOKEN) - seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-39s %s\n", + seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-32s %s\n", "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt"); else ip6fl_fl_seq_show(seq, v); diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 0e03eabfb9d..6c05c7978be 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -2373,7 +2373,7 @@ static int igmp6_mc_seq_show(struct seq_file *seq, void *v) struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq); seq_printf(seq, - "%-4d %-15s " NIP6_FMT " %5d %08X %ld\n", + "%-4d %-15s " NIP6_SEQFMT " %5d %08X %ld\n", state->dev->ifindex, state->dev->name, NIP6(im->mca_addr), im->mca_users, im->mca_flags, @@ -2542,12 +2542,12 @@ static int igmp6_mcf_seq_show(struct seq_file *seq, void *v) if (v == SEQ_START_TOKEN) { seq_printf(seq, "%3s %6s " - "%39s %39s %6s %6s\n", "Idx", + "%32s %32s %6s %6s\n", "Idx", "Device", "Multicast Address", "Source Address", "INC", "EXC"); } else { seq_printf(seq, - "%3d %6.6s " NIP6_FMT " " NIP6_FMT " %6lu %6lu\n", + "%3d %6.6s " NIP6_SEQFMT " " NIP6_SEQFMT " %6lu %6lu\n", state->dev->ifindex, state->dev->name, NIP6(state->im->mca_addr), NIP6(psf->sf_addr), -- GitLab From dd914b4082cfbe28849898a0a98757827829c813 Mon Sep 17 00:00:00 2001 From: Amnon Aaronsohn Date: Tue, 17 Jan 2006 02:24:26 -0800 Subject: [PATCH 445/465] [PKT_SCHED] sch_prio: fix qdisc bands init Currently when PRIO is configured to use N bands, it lets the packets be directed to any of the bands 0..N-1. However, PRIO attaches a fifo qdisc only to the bands that appear in the priomap; the rest of the N bands remain with a noop qdisc attached. This patch changes PRIO's behavior so that it attaches a fifo qdisc to all of the N bands. Signed-off-by: Amnon Aaronsohn Signed-off-by: David S. Miller --- net/sched/sch_prio.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c index 5b3a3e48ed9..1641db33a99 100644 --- a/net/sched/sch_prio.c +++ b/net/sched/sch_prio.c @@ -228,14 +228,13 @@ static int prio_tune(struct Qdisc *sch, struct rtattr *opt) } sch_tree_unlock(sch); - for (i=0; i<=TC_PRIO_MAX; i++) { - int band = q->prio2band[i]; - if (q->queues[band] == &noop_qdisc) { + for (i=0; ibands; i++) { + if (q->queues[i] == &noop_qdisc) { struct Qdisc *child; child = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops); if (child) { sch_tree_lock(sch); - child = xchg(&q->queues[band], child); + child = xchg(&q->queues[i], child); if (child != &noop_qdisc) qdisc_destroy(child); -- GitLab From e35bedf369b17120dbd7d554bee45407a3825267 Mon Sep 17 00:00:00 2001 From: Kris Katterjohn Date: Tue, 17 Jan 2006 02:25:52 -0800 Subject: [PATCH 446/465] [NET]: Fix whitespace issues in net/core/filter.c This fixes some whitespace issues in net/core/filter.c Signed-off-by: Kris Katterjohn Signed-off-by: David S. Miller --- net/core/filter.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/net/core/filter.c b/net/core/filter.c index a52665f7522..9540946a48f 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -74,7 +74,6 @@ static inline void *load_pointer(struct sk_buff *skb, int k, * filtering, filter is the array of filter instructions, and * len is the number of filter blocks in the array. */ - unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen) { struct sock_filter *fentry; /* We walk down these */ @@ -175,7 +174,7 @@ unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int continue; case BPF_LD|BPF_W|BPF_ABS: k = fentry->k; - load_w: +load_w: ptr = load_pointer(skb, k, 4, &tmp); if (ptr != NULL) { A = ntohl(*(u32 *)ptr); @@ -184,7 +183,7 @@ unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int break; case BPF_LD|BPF_H|BPF_ABS: k = fentry->k; - load_h: +load_h: ptr = load_pointer(skb, k, 2, &tmp); if (ptr != NULL) { A = ntohs(*(u16 *)ptr); @@ -374,7 +373,7 @@ int sk_chk_filter(struct sock_filter *filter, int flen) case BPF_JMP|BPF_JSET|BPF_K: case BPF_JMP|BPF_JSET|BPF_X: /* for conditionals both must be safe */ - if (pc + ftest->jt + 1 >= flen || + if (pc + ftest->jt + 1 >= flen || pc + ftest->jf + 1 >= flen) return -EINVAL; break; @@ -384,7 +383,7 @@ int sk_chk_filter(struct sock_filter *filter, int flen) } } - return (BPF_CLASS(filter[flen - 1].code) == BPF_RET) ? 0 : -EINVAL; + return (BPF_CLASS(filter[flen - 1].code) == BPF_RET) ? 0 : -EINVAL; } /** @@ -404,8 +403,8 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) int err; /* Make sure new filter is there and in the right amounts. */ - if (fprog->filter == NULL) - return -EINVAL; + if (fprog->filter == NULL) + return -EINVAL; fp = sock_kmalloc(sk, fsize+sizeof(*fp), GFP_KERNEL); if (!fp) -- GitLab From ccc91324a1b44d345ab4f814eb2ff453c7e98f9e Mon Sep 17 00:00:00 2001 From: Benoit Boissinot Date: Tue, 17 Jan 2006 02:26:34 -0800 Subject: [PATCH 447/465] [NETFILTER] ip[6]t_policy: Fix compilation warnings ip[6]t_policy argument conversion slipped when merging with x_tables Signed-off-by: Benoit Boissinot Signed-off-by: Harald Welte Signed-off-by: David S. Miller --- net/ipv4/netfilter/ipt_policy.c | 7 +++++-- net/ipv6/netfilter/ip6t_policy.c | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/net/ipv4/netfilter/ipt_policy.c b/net/ipv4/netfilter/ipt_policy.c index 709debcc69c..18ca8258a1c 100644 --- a/net/ipv4/netfilter/ipt_policy.c +++ b/net/ipv4/netfilter/ipt_policy.c @@ -95,7 +95,10 @@ match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info) static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, - const void *matchinfo, int offset, int *hotdrop) + const void *matchinfo, + int offset, + unsigned int protoff, + int *hotdrop) { const struct ipt_policy_info *info = matchinfo; int ret; @@ -113,7 +116,7 @@ static int match(const struct sk_buff *skb, return ret; } -static int checkentry(const char *tablename, const struct ipt_ip *ip, +static int checkentry(const char *tablename, const void *ip_void, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { diff --git a/net/ipv6/netfilter/ip6t_policy.c b/net/ipv6/netfilter/ip6t_policy.c index 13fedad48c1..afe1cc4c18a 100644 --- a/net/ipv6/netfilter/ip6t_policy.c +++ b/net/ipv6/netfilter/ip6t_policy.c @@ -118,7 +118,7 @@ static int match(const struct sk_buff *skb, return ret; } -static int checkentry(const char *tablename, const struct ip6t_ip6 *ip, +static int checkentry(const char *tablename, const void *ip_void, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { -- GitLab From 6dd42af7904336c6f59a01f9fd3599ee650e78ed Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Tue, 17 Jan 2006 02:38:56 -0800 Subject: [PATCH 448/465] [NETFILTER] Makefile cleanup These are replaced with x_tables matches and no longer exist. Signed-off-by: Yasuyuki Kozakai Signed-off-by: Harald Welte Signed-off-by: David S. Miller --- net/ipv4/netfilter/Makefile | 1 - net/ipv6/netfilter/Makefile | 1 - 2 files changed, 2 deletions(-) diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index bcefe64b931..e5c5b3202f0 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile @@ -46,7 +46,6 @@ obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o # matches -obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index 663b4749820..db6073c9416 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile @@ -4,7 +4,6 @@ # Link order matters here. obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o -obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o -- GitLab From e0069caede8387c585060b7e2e87729e9efcebc6 Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Tue, 17 Jan 2006 02:39:19 -0800 Subject: [PATCH 449/465] [NETFILTER] ip6tables: remove unused definitions These definitions ware used for only internal use in kernel <= 2.6.13, which had not introduced the unified parser of IPv6 extension header yet. Signed-off-by: Yasuyuki Kozakai Signed-off-by: Harald Welte Signed-off-by: David S. Miller --- include/linux/netfilter_ipv6/ip6t_ah.h | 9 --------- include/linux/netfilter_ipv6/ip6t_esp.h | 9 --------- include/linux/netfilter_ipv6/ip6t_frag.h | 9 --------- include/linux/netfilter_ipv6/ip6t_opts.h | 9 --------- include/linux/netfilter_ipv6/ip6t_rt.h | 9 --------- 5 files changed, 45 deletions(-) diff --git a/include/linux/netfilter_ipv6/ip6t_ah.h b/include/linux/netfilter_ipv6/ip6t_ah.h index c4f0793a0a9..8531879eb46 100644 --- a/include/linux/netfilter_ipv6/ip6t_ah.h +++ b/include/linux/netfilter_ipv6/ip6t_ah.h @@ -18,13 +18,4 @@ struct ip6t_ah #define IP6T_AH_INV_LEN 0x02 /* Invert the sense of length. */ #define IP6T_AH_INV_MASK 0x03 /* All possible flags. */ -#define MASK_HOPOPTS 128 -#define MASK_DSTOPTS 64 -#define MASK_ROUTING 32 -#define MASK_FRAGMENT 16 -#define MASK_AH 8 -#define MASK_ESP 4 -#define MASK_NONE 2 -#define MASK_PROTO 1 - #endif /*_IP6T_AH_H*/ diff --git a/include/linux/netfilter_ipv6/ip6t_esp.h b/include/linux/netfilter_ipv6/ip6t_esp.h index 01142b98a23..a91b6abc807 100644 --- a/include/linux/netfilter_ipv6/ip6t_esp.h +++ b/include/linux/netfilter_ipv6/ip6t_esp.h @@ -7,15 +7,6 @@ struct ip6t_esp u_int8_t invflags; /* Inverse flags */ }; -#define MASK_HOPOPTS 128 -#define MASK_DSTOPTS 64 -#define MASK_ROUTING 32 -#define MASK_FRAGMENT 16 -#define MASK_AH 8 -#define MASK_ESP 4 -#define MASK_NONE 2 -#define MASK_PROTO 1 - /* Values for "invflags" field in struct ip6t_esp. */ #define IP6T_ESP_INV_SPI 0x01 /* Invert the sense of spi. */ #define IP6T_ESP_INV_MASK 0x01 /* All possible flags. */ diff --git a/include/linux/netfilter_ipv6/ip6t_frag.h b/include/linux/netfilter_ipv6/ip6t_frag.h index 449a57eca7d..66070a0d6df 100644 --- a/include/linux/netfilter_ipv6/ip6t_frag.h +++ b/include/linux/netfilter_ipv6/ip6t_frag.h @@ -21,13 +21,4 @@ struct ip6t_frag #define IP6T_FRAG_INV_LEN 0x02 /* Invert the sense of length. */ #define IP6T_FRAG_INV_MASK 0x03 /* All possible flags. */ -#define MASK_HOPOPTS 128 -#define MASK_DSTOPTS 64 -#define MASK_ROUTING 32 -#define MASK_FRAGMENT 16 -#define MASK_AH 8 -#define MASK_ESP 4 -#define MASK_NONE 2 -#define MASK_PROTO 1 - #endif /*_IP6T_FRAG_H*/ diff --git a/include/linux/netfilter_ipv6/ip6t_opts.h b/include/linux/netfilter_ipv6/ip6t_opts.h index e259b6275bd..a07e36380ae 100644 --- a/include/linux/netfilter_ipv6/ip6t_opts.h +++ b/include/linux/netfilter_ipv6/ip6t_opts.h @@ -20,13 +20,4 @@ struct ip6t_opts #define IP6T_OPTS_INV_LEN 0x01 /* Invert the sense of length. */ #define IP6T_OPTS_INV_MASK 0x01 /* All possible flags. */ -#define MASK_HOPOPTS 128 -#define MASK_DSTOPTS 64 -#define MASK_ROUTING 32 -#define MASK_FRAGMENT 16 -#define MASK_AH 8 -#define MASK_ESP 4 -#define MASK_NONE 2 -#define MASK_PROTO 1 - #endif /*_IP6T_OPTS_H*/ diff --git a/include/linux/netfilter_ipv6/ip6t_rt.h b/include/linux/netfilter_ipv6/ip6t_rt.h index f1070fbf275..52156023e8d 100644 --- a/include/linux/netfilter_ipv6/ip6t_rt.h +++ b/include/linux/netfilter_ipv6/ip6t_rt.h @@ -30,13 +30,4 @@ struct ip6t_rt #define IP6T_RT_INV_LEN 0x04 /* Invert the sense of length. */ #define IP6T_RT_INV_MASK 0x07 /* All possible flags. */ -#define MASK_HOPOPTS 128 -#define MASK_DSTOPTS 64 -#define MASK_ROUTING 32 -#define MASK_FRAGMENT 16 -#define MASK_AH 8 -#define MASK_ESP 4 -#define MASK_NONE 2 -#define MASK_PROTO 1 - #endif /*_IP6T_RT_H*/ -- GitLab From f0daaa654af68c1651add9d21188d81c19672551 Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Tue, 17 Jan 2006 02:39:39 -0800 Subject: [PATCH 450/465] [NETFILTER] ip6tables: whitespace and indent cosmetic cleanup Signed-off-by: Yasuyuki Kozakai Signed-off-by: Harald Welte Signed-off-by: David S. Miller --- net/ipv6/netfilter/ip6t_dst.c | 151 ++++++++++--------- net/ipv6/netfilter/ip6t_eui64.c | 68 ++++----- net/ipv6/netfilter/ip6t_frag.c | 157 ++++++++++--------- net/ipv6/netfilter/ip6t_hbh.c | 151 ++++++++++--------- net/ipv6/netfilter/ip6t_ipv6header.c | 79 +++++----- net/ipv6/netfilter/ip6t_owner.c | 28 ++-- net/ipv6/netfilter/ip6t_rt.c | 215 ++++++++++++++------------- 7 files changed, 427 insertions(+), 422 deletions(-) diff --git a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c index 80fe82669ce..b4c153a5350 100644 --- a/net/ipv6/netfilter/ip6t_dst.c +++ b/net/ipv6/netfilter/ip6t_dst.c @@ -36,19 +36,19 @@ MODULE_AUTHOR("Andras Kis-Szabo "); #endif /* - * (Type & 0xC0) >> 6 - * 0 -> ignorable - * 1 -> must drop the packet - * 2 -> send ICMP PARM PROB regardless and drop packet - * 3 -> Send ICMP if not a multicast address and drop packet + * (Type & 0xC0) >> 6 + * 0 -> ignorable + * 1 -> must drop the packet + * 2 -> send ICMP PARM PROB regardless and drop packet + * 3 -> Send ICMP if not a multicast address and drop packet * (Type & 0x20) >> 5 - * 0 -> invariant - * 1 -> can change the routing + * 0 -> invariant + * 1 -> can change the routing * (Type & 0x1F) Type - * 0 -> Pad1 (only 1 byte!) - * 1 -> PadN LENGTH info (total length = length + 2) - * C0 | 2 -> JUMBO 4 x x x x ( xxxx > 64k ) - * 5 -> RTALERT 2 x x + * 0 -> Pad1 (only 1 byte!) + * 1 -> PadN LENGTH info (total length = length + 2) + * C0 | 2 -> JUMBO 4 x x x x ( xxxx > 64k ) + * 5 -> RTALERT 2 x x */ static int @@ -60,16 +60,16 @@ match(const struct sk_buff *skb, unsigned int protoff, int *hotdrop) { - struct ipv6_opt_hdr _optsh, *oh; - const struct ip6t_opts *optinfo = matchinfo; - unsigned int temp; - unsigned int ptr; - unsigned int hdrlen = 0; - unsigned int ret = 0; - u8 _opttype, *tp = NULL; - u8 _optlen, *lp = NULL; - unsigned int optlen; - + struct ipv6_opt_hdr _optsh, *oh; + const struct ip6t_opts *optinfo = matchinfo; + unsigned int temp; + unsigned int ptr; + unsigned int hdrlen = 0; + unsigned int ret = 0; + u8 _opttype, *tp = NULL; + u8 _optlen, *lp = NULL; + unsigned int optlen; + #if HOPBYHOP if (ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP, NULL) < 0) #else @@ -77,42 +77,41 @@ match(const struct sk_buff *skb, #endif return 0; - oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); - if (oh == NULL){ - *hotdrop = 1; - return 0; - } - - hdrlen = ipv6_optlen(oh); - if (skb->len - ptr < hdrlen){ - /* Packet smaller than it's length field */ - return 0; - } - - DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen); - - DEBUGP("len %02X %04X %02X ", - optinfo->hdrlen, hdrlen, - (!(optinfo->flags & IP6T_OPTS_LEN) || - ((optinfo->hdrlen == hdrlen) ^ - !!(optinfo->invflags & IP6T_OPTS_INV_LEN)))); - - ret = (oh != NULL) - && - (!(optinfo->flags & IP6T_OPTS_LEN) || - ((optinfo->hdrlen == hdrlen) ^ - !!(optinfo->invflags & IP6T_OPTS_INV_LEN))); - - ptr += 2; - hdrlen -= 2; - if ( !(optinfo->flags & IP6T_OPTS_OPTS) ){ - return ret; + oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); + if (oh == NULL) { + *hotdrop = 1; + return 0; + } + + hdrlen = ipv6_optlen(oh); + if (skb->len - ptr < hdrlen) { + /* Packet smaller than it's length field */ + return 0; + } + + DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen); + + DEBUGP("len %02X %04X %02X ", + optinfo->hdrlen, hdrlen, + (!(optinfo->flags & IP6T_OPTS_LEN) || + ((optinfo->hdrlen == hdrlen) ^ + !!(optinfo->invflags & IP6T_OPTS_INV_LEN)))); + + ret = (oh != NULL) && + (!(optinfo->flags & IP6T_OPTS_LEN) || + ((optinfo->hdrlen == hdrlen) ^ + !!(optinfo->invflags & IP6T_OPTS_INV_LEN))); + + ptr += 2; + hdrlen -= 2; + if (!(optinfo->flags & IP6T_OPTS_OPTS)) { + return ret; } else if (optinfo->flags & IP6T_OPTS_NSTRICT) { DEBUGP("Not strict - not implemented"); } else { DEBUGP("Strict "); - DEBUGP("#%d ",optinfo->optsnr); - for(temp=0; tempoptsnr; temp++){ + DEBUGP("#%d ", optinfo->optsnr); + for (temp = 0; temp < optinfo->optsnr; temp++) { /* type field exists ? */ if (hdrlen < 1) break; @@ -122,10 +121,10 @@ match(const struct sk_buff *skb, break; /* Type check */ - if (*tp != (optinfo->opts[temp] & 0xFF00)>>8){ + if (*tp != (optinfo->opts[temp] & 0xFF00) >> 8) { DEBUGP("Tbad %02X %02X\n", *tp, - (optinfo->opts[temp] & 0xFF00)>>8); + (optinfo->opts[temp] & 0xFF00) >> 8); return 0; } else { DEBUGP("Tok "); @@ -169,7 +168,8 @@ match(const struct sk_buff *skb, } if (temp == optinfo->optsnr) return ret; - else return 0; + else + return 0; } return 0; @@ -178,25 +178,24 @@ match(const struct sk_buff *skb, /* Called when user tries to insert an entry of this type. */ static int checkentry(const char *tablename, - const void *info, - void *matchinfo, - unsigned int matchinfosize, - unsigned int hook_mask) + const void *info, + void *matchinfo, + unsigned int matchinfosize, + unsigned int hook_mask) { - const struct ip6t_opts *optsinfo = matchinfo; - - if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_opts))) { - DEBUGP("ip6t_opts: matchsize %u != %u\n", - matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_opts))); - return 0; - } - if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) { - DEBUGP("ip6t_opts: unknown flags %X\n", - optsinfo->invflags); - return 0; - } - - return 1; + const struct ip6t_opts *optsinfo = matchinfo; + + if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_opts))) { + DEBUGP("ip6t_opts: matchsize %u != %u\n", + matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_opts))); + return 0; + } + if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) { + DEBUGP("ip6t_opts: unknown flags %X\n", optsinfo->invflags); + return 0; + } + + return 1; } static struct ip6t_match opts_match = { @@ -212,12 +211,12 @@ static struct ip6t_match opts_match = { static int __init init(void) { - return ip6t_register_match(&opts_match); + return ip6t_register_match(&opts_match); } static void __exit cleanup(void) { - ip6t_unregister_match(&opts_match); + ip6t_unregister_match(&opts_match); } module_init(init); diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c index ddf5f571909..27396ac0b9e 100644 --- a/net/ipv6/netfilter/ip6t_eui64.c +++ b/net/ipv6/netfilter/ip6t_eui64.c @@ -27,45 +27,45 @@ match(const struct sk_buff *skb, unsigned int protoff, int *hotdrop) { + unsigned char eui64[8]; + int i = 0; - unsigned char eui64[8]; - int i=0; - - if ( !(skb->mac.raw >= skb->head - && (skb->mac.raw + ETH_HLEN) <= skb->data) - && offset != 0) { - *hotdrop = 1; - return 0; - } - - memset(eui64, 0, sizeof(eui64)); - - if (eth_hdr(skb)->h_proto == ntohs(ETH_P_IPV6)) { - if (skb->nh.ipv6h->version == 0x6) { - memcpy(eui64, eth_hdr(skb)->h_source, 3); - memcpy(eui64 + 5, eth_hdr(skb)->h_source + 3, 3); - eui64[3]=0xff; - eui64[4]=0xfe; - eui64[0] |= 0x02; - - i=0; - while ((skb->nh.ipv6h->saddr.s6_addr[8+i] == - eui64[i]) && (i<8)) i++; - - if ( i == 8 ) - return 1; - } - } - - return 0; + if (!(skb->mac.raw >= skb->head && + (skb->mac.raw + ETH_HLEN) <= skb->data) && + offset != 0) { + *hotdrop = 1; + return 0; + } + + memset(eui64, 0, sizeof(eui64)); + + if (eth_hdr(skb)->h_proto == ntohs(ETH_P_IPV6)) { + if (skb->nh.ipv6h->version == 0x6) { + memcpy(eui64, eth_hdr(skb)->h_source, 3); + memcpy(eui64 + 5, eth_hdr(skb)->h_source + 3, 3); + eui64[3] = 0xff; + eui64[4] = 0xfe; + eui64[0] |= 0x02; + + i = 0; + while ((skb->nh.ipv6h->saddr.s6_addr[8+i] == eui64[i]) + && (i < 8)) + i++; + + if (i == 8) + return 1; + } + } + + return 0; } static int ip6t_eui64_checkentry(const char *tablename, - const void *ip, - void *matchinfo, - unsigned int matchsize, - unsigned int hook_mask) + const void *ip, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) { if (hook_mask & ~((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_IN) | diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c index a9964b946ed..4c14125a0e2 100644 --- a/net/ipv6/netfilter/ip6t_frag.c +++ b/net/ipv6/netfilter/ip6t_frag.c @@ -31,12 +31,12 @@ MODULE_AUTHOR("Andras Kis-Szabo "); static inline int id_match(u_int32_t min, u_int32_t max, u_int32_t id, int invert) { - int r=0; - DEBUGP("frag id_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ', - min,id,max); - r=(id >= min && id <= max) ^ invert; - DEBUGP(" result %s\n",r? "PASS" : "FAILED"); - return r; + int r = 0; + DEBUGP("frag id_match:%c 0x%x <= 0x%x <= 0x%x", invert ? '!' : ' ', + min, id, max); + r = (id >= min && id <= max) ^ invert; + DEBUGP(" result %s\n", r ? "PASS" : "FAILED"); + return r; } static int @@ -48,92 +48,91 @@ match(const struct sk_buff *skb, unsigned int protoff, int *hotdrop) { - struct frag_hdr _frag, *fh; - const struct ip6t_frag *fraginfo = matchinfo; - unsigned int ptr; + struct frag_hdr _frag, *fh; + const struct ip6t_frag *fraginfo = matchinfo; + unsigned int ptr; if (ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL) < 0) return 0; fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag); - if (fh == NULL){ + if (fh == NULL) { *hotdrop = 1; return 0; } - DEBUGP("INFO %04X ", fh->frag_off); - DEBUGP("OFFSET %04X ", ntohs(fh->frag_off) & ~0x7); - DEBUGP("RES %02X %04X", fh->reserved, ntohs(fh->frag_off) & 0x6); - DEBUGP("MF %04X ", fh->frag_off & htons(IP6_MF)); - DEBUGP("ID %u %08X\n", ntohl(fh->identification), - ntohl(fh->identification)); - - DEBUGP("IPv6 FRAG id %02X ", - (id_match(fraginfo->ids[0], fraginfo->ids[1], - ntohl(fh->identification), - !!(fraginfo->invflags & IP6T_FRAG_INV_IDS)))); - DEBUGP("res %02X %02X%04X %02X ", - (fraginfo->flags & IP6T_FRAG_RES), fh->reserved, - ntohs(fh->frag_off) & 0x6, - !((fraginfo->flags & IP6T_FRAG_RES) - && (fh->reserved || (ntohs(fh->frag_off) & 0x06)))); - DEBUGP("first %02X %02X %02X ", - (fraginfo->flags & IP6T_FRAG_FST), - ntohs(fh->frag_off) & ~0x7, - !((fraginfo->flags & IP6T_FRAG_FST) - && (ntohs(fh->frag_off) & ~0x7))); - DEBUGP("mf %02X %02X %02X ", - (fraginfo->flags & IP6T_FRAG_MF), - ntohs(fh->frag_off) & IP6_MF, - !((fraginfo->flags & IP6T_FRAG_MF) - && !((ntohs(fh->frag_off) & IP6_MF)))); - DEBUGP("last %02X %02X %02X\n", - (fraginfo->flags & IP6T_FRAG_NMF), - ntohs(fh->frag_off) & IP6_MF, - !((fraginfo->flags & IP6T_FRAG_NMF) - && (ntohs(fh->frag_off) & IP6_MF))); - - return (fh != NULL) - && - (id_match(fraginfo->ids[0], fraginfo->ids[1], - ntohl(fh->identification), - !!(fraginfo->invflags & IP6T_FRAG_INV_IDS))) - && - !((fraginfo->flags & IP6T_FRAG_RES) - && (fh->reserved || (ntohs(fh->frag_off) & 0x6))) - && - !((fraginfo->flags & IP6T_FRAG_FST) - && (ntohs(fh->frag_off) & ~0x7)) - && - !((fraginfo->flags & IP6T_FRAG_MF) - && !(ntohs(fh->frag_off) & IP6_MF)) - && - !((fraginfo->flags & IP6T_FRAG_NMF) - && (ntohs(fh->frag_off) & IP6_MF)); + DEBUGP("INFO %04X ", fh->frag_off); + DEBUGP("OFFSET %04X ", ntohs(fh->frag_off) & ~0x7); + DEBUGP("RES %02X %04X", fh->reserved, ntohs(fh->frag_off) & 0x6); + DEBUGP("MF %04X ", fh->frag_off & htons(IP6_MF)); + DEBUGP("ID %u %08X\n", ntohl(fh->identification), + ntohl(fh->identification)); + + DEBUGP("IPv6 FRAG id %02X ", + (id_match(fraginfo->ids[0], fraginfo->ids[1], + ntohl(fh->identification), + !!(fraginfo->invflags & IP6T_FRAG_INV_IDS)))); + DEBUGP("res %02X %02X%04X %02X ", + (fraginfo->flags & IP6T_FRAG_RES), fh->reserved, + ntohs(fh->frag_off) & 0x6, + !((fraginfo->flags & IP6T_FRAG_RES) + && (fh->reserved || (ntohs(fh->frag_off) & 0x06)))); + DEBUGP("first %02X %02X %02X ", + (fraginfo->flags & IP6T_FRAG_FST), + ntohs(fh->frag_off) & ~0x7, + !((fraginfo->flags & IP6T_FRAG_FST) + && (ntohs(fh->frag_off) & ~0x7))); + DEBUGP("mf %02X %02X %02X ", + (fraginfo->flags & IP6T_FRAG_MF), + ntohs(fh->frag_off) & IP6_MF, + !((fraginfo->flags & IP6T_FRAG_MF) + && !((ntohs(fh->frag_off) & IP6_MF)))); + DEBUGP("last %02X %02X %02X\n", + (fraginfo->flags & IP6T_FRAG_NMF), + ntohs(fh->frag_off) & IP6_MF, + !((fraginfo->flags & IP6T_FRAG_NMF) + && (ntohs(fh->frag_off) & IP6_MF))); + + return (fh != NULL) + && + (id_match(fraginfo->ids[0], fraginfo->ids[1], + ntohl(fh->identification), + !!(fraginfo->invflags & IP6T_FRAG_INV_IDS))) + && + !((fraginfo->flags & IP6T_FRAG_RES) + && (fh->reserved || (ntohs(fh->frag_off) & 0x6))) + && + !((fraginfo->flags & IP6T_FRAG_FST) + && (ntohs(fh->frag_off) & ~0x7)) + && + !((fraginfo->flags & IP6T_FRAG_MF) + && !(ntohs(fh->frag_off) & IP6_MF)) + && + !((fraginfo->flags & IP6T_FRAG_NMF) + && (ntohs(fh->frag_off) & IP6_MF)); } /* Called when user tries to insert an entry of this type. */ static int checkentry(const char *tablename, - const void *ip, - void *matchinfo, - unsigned int matchinfosize, - unsigned int hook_mask) + const void *ip, + void *matchinfo, + unsigned int matchinfosize, + unsigned int hook_mask) { - const struct ip6t_frag *fraginfo = matchinfo; - - if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_frag))) { - DEBUGP("ip6t_frag: matchsize %u != %u\n", - matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_frag))); - return 0; - } - if (fraginfo->invflags & ~IP6T_FRAG_INV_MASK) { - DEBUGP("ip6t_frag: unknown flags %X\n", - fraginfo->invflags); - return 0; - } - - return 1; + const struct ip6t_frag *fraginfo = matchinfo; + + if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_frag))) { + DEBUGP("ip6t_frag: matchsize %u != %u\n", + matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_frag))); + return 0; + } + if (fraginfo->invflags & ~IP6T_FRAG_INV_MASK) { + DEBUGP("ip6t_frag: unknown flags %X\n", fraginfo->invflags); + return 0; + } + + return 1; } static struct ip6t_match frag_match = { @@ -145,12 +144,12 @@ static struct ip6t_match frag_match = { static int __init init(void) { - return ip6t_register_match(&frag_match); + return ip6t_register_match(&frag_match); } static void __exit cleanup(void) { - ip6t_unregister_match(&frag_match); + ip6t_unregister_match(&frag_match); } module_init(init); diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c index ed8ded18bbd..37a8474a7e0 100644 --- a/net/ipv6/netfilter/ip6t_hbh.c +++ b/net/ipv6/netfilter/ip6t_hbh.c @@ -36,19 +36,19 @@ MODULE_AUTHOR("Andras Kis-Szabo "); #endif /* - * (Type & 0xC0) >> 6 - * 0 -> ignorable - * 1 -> must drop the packet - * 2 -> send ICMP PARM PROB regardless and drop packet - * 3 -> Send ICMP if not a multicast address and drop packet + * (Type & 0xC0) >> 6 + * 0 -> ignorable + * 1 -> must drop the packet + * 2 -> send ICMP PARM PROB regardless and drop packet + * 3 -> Send ICMP if not a multicast address and drop packet * (Type & 0x20) >> 5 - * 0 -> invariant - * 1 -> can change the routing + * 0 -> invariant + * 1 -> can change the routing * (Type & 0x1F) Type - * 0 -> Pad1 (only 1 byte!) - * 1 -> PadN LENGTH info (total length = length + 2) - * C0 | 2 -> JUMBO 4 x x x x ( xxxx > 64k ) - * 5 -> RTALERT 2 x x + * 0 -> Pad1 (only 1 byte!) + * 1 -> PadN LENGTH info (total length = length + 2) + * C0 | 2 -> JUMBO 4 x x x x ( xxxx > 64k ) + * 5 -> RTALERT 2 x x */ static int @@ -60,16 +60,16 @@ match(const struct sk_buff *skb, unsigned int protoff, int *hotdrop) { - struct ipv6_opt_hdr _optsh, *oh; - const struct ip6t_opts *optinfo = matchinfo; - unsigned int temp; - unsigned int ptr; - unsigned int hdrlen = 0; - unsigned int ret = 0; - u8 _opttype, *tp = NULL; - u8 _optlen, *lp = NULL; - unsigned int optlen; - + struct ipv6_opt_hdr _optsh, *oh; + const struct ip6t_opts *optinfo = matchinfo; + unsigned int temp; + unsigned int ptr; + unsigned int hdrlen = 0; + unsigned int ret = 0; + u8 _opttype, *tp = NULL; + u8 _optlen, *lp = NULL; + unsigned int optlen; + #if HOPBYHOP if (ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP, NULL) < 0) #else @@ -77,42 +77,41 @@ match(const struct sk_buff *skb, #endif return 0; - oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); - if (oh == NULL){ - *hotdrop = 1; - return 0; - } - - hdrlen = ipv6_optlen(oh); - if (skb->len - ptr < hdrlen){ - /* Packet smaller than it's length field */ - return 0; - } - - DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen); - - DEBUGP("len %02X %04X %02X ", - optinfo->hdrlen, hdrlen, - (!(optinfo->flags & IP6T_OPTS_LEN) || - ((optinfo->hdrlen == hdrlen) ^ - !!(optinfo->invflags & IP6T_OPTS_INV_LEN)))); - - ret = (oh != NULL) - && - (!(optinfo->flags & IP6T_OPTS_LEN) || - ((optinfo->hdrlen == hdrlen) ^ - !!(optinfo->invflags & IP6T_OPTS_INV_LEN))); - - ptr += 2; - hdrlen -= 2; - if ( !(optinfo->flags & IP6T_OPTS_OPTS) ){ - return ret; + oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); + if (oh == NULL) { + *hotdrop = 1; + return 0; + } + + hdrlen = ipv6_optlen(oh); + if (skb->len - ptr < hdrlen) { + /* Packet smaller than it's length field */ + return 0; + } + + DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen); + + DEBUGP("len %02X %04X %02X ", + optinfo->hdrlen, hdrlen, + (!(optinfo->flags & IP6T_OPTS_LEN) || + ((optinfo->hdrlen == hdrlen) ^ + !!(optinfo->invflags & IP6T_OPTS_INV_LEN)))); + + ret = (oh != NULL) && + (!(optinfo->flags & IP6T_OPTS_LEN) || + ((optinfo->hdrlen == hdrlen) ^ + !!(optinfo->invflags & IP6T_OPTS_INV_LEN))); + + ptr += 2; + hdrlen -= 2; + if (!(optinfo->flags & IP6T_OPTS_OPTS)) { + return ret; } else if (optinfo->flags & IP6T_OPTS_NSTRICT) { DEBUGP("Not strict - not implemented"); } else { DEBUGP("Strict "); - DEBUGP("#%d ",optinfo->optsnr); - for(temp=0; tempoptsnr; temp++){ + DEBUGP("#%d ", optinfo->optsnr); + for (temp = 0; temp < optinfo->optsnr; temp++) { /* type field exists ? */ if (hdrlen < 1) break; @@ -122,10 +121,10 @@ match(const struct sk_buff *skb, break; /* Type check */ - if (*tp != (optinfo->opts[temp] & 0xFF00)>>8){ + if (*tp != (optinfo->opts[temp] & 0xFF00) >> 8) { DEBUGP("Tbad %02X %02X\n", *tp, - (optinfo->opts[temp] & 0xFF00)>>8); + (optinfo->opts[temp] & 0xFF00) >> 8); return 0; } else { DEBUGP("Tok "); @@ -169,7 +168,8 @@ match(const struct sk_buff *skb, } if (temp == optinfo->optsnr) return ret; - else return 0; + else + return 0; } return 0; @@ -178,25 +178,24 @@ match(const struct sk_buff *skb, /* Called when user tries to insert an entry of this type. */ static int checkentry(const char *tablename, - const void *entry, - void *matchinfo, - unsigned int matchinfosize, - unsigned int hook_mask) + const void *entry, + void *matchinfo, + unsigned int matchinfosize, + unsigned int hook_mask) { - const struct ip6t_opts *optsinfo = matchinfo; - - if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_opts))) { - DEBUGP("ip6t_opts: matchsize %u != %u\n", - matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_opts))); - return 0; - } - if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) { - DEBUGP("ip6t_opts: unknown flags %X\n", - optsinfo->invflags); - return 0; - } - - return 1; + const struct ip6t_opts *optsinfo = matchinfo; + + if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_opts))) { + DEBUGP("ip6t_opts: matchsize %u != %u\n", + matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_opts))); + return 0; + } + if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) { + DEBUGP("ip6t_opts: unknown flags %X\n", optsinfo->invflags); + return 0; + } + + return 1; } static struct ip6t_match opts_match = { @@ -212,12 +211,12 @@ static struct ip6t_match opts_match = { static int __init init(void) { - return ip6t_register_match(&opts_match); + return ip6t_register_match(&opts_match); } static void __exit cleanup(void) { - ip6t_unregister_match(&opts_match); + ip6t_unregister_match(&opts_match); } module_init(init); diff --git a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c index fda1ceaf5a2..83ad6b272f7 100644 --- a/net/ipv6/netfilter/ip6t_ipv6header.c +++ b/net/ipv6/netfilter/ip6t_ipv6header.c @@ -50,20 +50,20 @@ ipv6header_match(const struct sk_buff *skb, len = skb->len - ptr; temp = 0; - while (ip6t_ext_hdr(nexthdr)) { + while (ip6t_ext_hdr(nexthdr)) { struct ipv6_opt_hdr _hdr, *hp; - int hdrlen; + int hdrlen; /* Is there enough space for the next ext header? */ - if (len < (int)sizeof(struct ipv6_opt_hdr)) - return 0; + if (len < (int)sizeof(struct ipv6_opt_hdr)) + return 0; /* No more exthdr -> evaluate */ - if (nexthdr == NEXTHDR_NONE) { + if (nexthdr == NEXTHDR_NONE) { temp |= MASK_NONE; break; } /* ESP -> evaluate */ - if (nexthdr == NEXTHDR_ESP) { + if (nexthdr == NEXTHDR_ESP) { temp |= MASK_ESP; break; } @@ -72,43 +72,43 @@ ipv6header_match(const struct sk_buff *skb, BUG_ON(hp == NULL); /* Calculate the header length */ - if (nexthdr == NEXTHDR_FRAGMENT) { - hdrlen = 8; - } else if (nexthdr == NEXTHDR_AUTH) - hdrlen = (hp->hdrlen+2)<<2; - else - hdrlen = ipv6_optlen(hp); + if (nexthdr == NEXTHDR_FRAGMENT) { + hdrlen = 8; + } else if (nexthdr == NEXTHDR_AUTH) + hdrlen = (hp->hdrlen + 2) << 2; + else + hdrlen = ipv6_optlen(hp); /* set the flag */ - switch (nexthdr){ - case NEXTHDR_HOP: - temp |= MASK_HOPOPTS; - break; - case NEXTHDR_ROUTING: - temp |= MASK_ROUTING; - break; - case NEXTHDR_FRAGMENT: - temp |= MASK_FRAGMENT; - break; - case NEXTHDR_AUTH: - temp |= MASK_AH; - break; - case NEXTHDR_DEST: - temp |= MASK_DSTOPTS; - break; - default: - return 0; - break; + switch (nexthdr) { + case NEXTHDR_HOP: + temp |= MASK_HOPOPTS; + break; + case NEXTHDR_ROUTING: + temp |= MASK_ROUTING; + break; + case NEXTHDR_FRAGMENT: + temp |= MASK_FRAGMENT; + break; + case NEXTHDR_AUTH: + temp |= MASK_AH; + break; + case NEXTHDR_DEST: + temp |= MASK_DSTOPTS; + break; + default: + return 0; + break; } - nexthdr = hp->nexthdr; - len -= hdrlen; - ptr += hdrlen; + nexthdr = hp->nexthdr; + len -= hdrlen; + ptr += hdrlen; if (ptr > skb->len) break; - } + } - if ( (nexthdr != NEXTHDR_NONE ) && (nexthdr != NEXTHDR_ESP) ) + if ((nexthdr != NEXTHDR_NONE) && (nexthdr != NEXTHDR_ESP)) temp |= MASK_PROTO; if (info->modeflag) @@ -137,8 +137,8 @@ ipv6header_checkentry(const char *tablename, return 0; /* invflags is 0 or 0xff in hard mode */ - if ((!info->modeflag) && info->invflags != 0x00 - && info->invflags != 0xFF) + if ((!info->modeflag) && info->invflags != 0x00 && + info->invflags != 0xFF) return 0; return 1; @@ -152,7 +152,7 @@ static struct ip6t_match ip6t_ipv6header_match = { .me = THIS_MODULE, }; -static int __init ipv6header_init(void) +static int __init ipv6header_init(void) { return ip6t_register_match(&ip6t_ipv6header_match); } @@ -164,4 +164,3 @@ static void __exit ipv6header_exit(void) module_init(ipv6header_init); module_exit(ipv6header_exit); - diff --git a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c index 5409b375b51..8c8a4c7ec93 100644 --- a/net/ipv6/netfilter/ip6t_owner.c +++ b/net/ipv6/netfilter/ip6t_owner.c @@ -36,14 +36,14 @@ match(const struct sk_buff *skb, if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file) return 0; - if(info->match & IP6T_OWNER_UID) { - if((skb->sk->sk_socket->file->f_uid != info->uid) ^ + if (info->match & IP6T_OWNER_UID) { + if ((skb->sk->sk_socket->file->f_uid != info->uid) ^ !!(info->invert & IP6T_OWNER_UID)) return 0; } - if(info->match & IP6T_OWNER_GID) { - if((skb->sk->sk_socket->file->f_gid != info->gid) ^ + if (info->match & IP6T_OWNER_GID) { + if ((skb->sk->sk_socket->file->f_gid != info->gid) ^ !!(info->invert & IP6T_OWNER_GID)) return 0; } @@ -53,23 +53,23 @@ match(const struct sk_buff *skb, static int checkentry(const char *tablename, - const void *ip, - void *matchinfo, - unsigned int matchsize, - unsigned int hook_mask) + const void *ip, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) { const struct ip6t_owner_info *info = matchinfo; - if (hook_mask - & ~((1 << NF_IP6_LOCAL_OUT) | (1 << NF_IP6_POST_ROUTING))) { - printk("ip6t_owner: only valid for LOCAL_OUT or POST_ROUTING.\n"); - return 0; - } + if (hook_mask + & ~((1 << NF_IP6_LOCAL_OUT) | (1 << NF_IP6_POST_ROUTING))) { + printk("ip6t_owner: only valid for LOCAL_OUT or POST_ROUTING.\n"); + return 0; + } if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_owner_info))) return 0; - if (info->match & (IP6T_OWNER_PID|IP6T_OWNER_SID)) { + if (info->match & (IP6T_OWNER_PID | IP6T_OWNER_SID)) { printk("ipt_owner: pid and sid matching " "not supported anymore\n"); return 0; diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c index 8465b437585..8f82476dc89 100644 --- a/net/ipv6/netfilter/ip6t_rt.c +++ b/net/ipv6/netfilter/ip6t_rt.c @@ -33,12 +33,12 @@ MODULE_AUTHOR("Andras Kis-Szabo "); static inline int segsleft_match(u_int32_t min, u_int32_t max, u_int32_t id, int invert) { - int r=0; - DEBUGP("rt segsleft_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ', - min,id,max); - r=(id >= min && id <= max) ^ invert; - DEBUGP(" result %s\n",r? "PASS" : "FAILED"); - return r; + int r = 0; + DEBUGP("rt segsleft_match:%c 0x%x <= 0x%x <= 0x%x", + invert ? '!' : ' ', min, id, max); + r = (id >= min && id <= max) ^ invert; + DEBUGP(" result %s\n", r ? "PASS" : "FAILED"); + return r; } static int @@ -50,87 +50,93 @@ match(const struct sk_buff *skb, unsigned int protoff, int *hotdrop) { - struct ipv6_rt_hdr _route, *rh; - const struct ip6t_rt *rtinfo = matchinfo; - unsigned int temp; - unsigned int ptr; - unsigned int hdrlen = 0; - unsigned int ret = 0; - struct in6_addr *ap, _addr; + struct ipv6_rt_hdr _route, *rh; + const struct ip6t_rt *rtinfo = matchinfo; + unsigned int temp; + unsigned int ptr; + unsigned int hdrlen = 0; + unsigned int ret = 0; + struct in6_addr *ap, _addr; if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL) < 0) return 0; - rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route); - if (rh == NULL){ - *hotdrop = 1; - return 0; - } - - hdrlen = ipv6_optlen(rh); - if (skb->len - ptr < hdrlen){ - /* Pcket smaller than its length field */ - return 0; - } - - DEBUGP("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen); - DEBUGP("TYPE %04X ", rh->type); - DEBUGP("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left); - - DEBUGP("IPv6 RT segsleft %02X ", - (segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1], - rh->segments_left, - !!(rtinfo->invflags & IP6T_RT_INV_SGS)))); - DEBUGP("type %02X %02X %02X ", - rtinfo->rt_type, rh->type, - (!(rtinfo->flags & IP6T_RT_TYP) || - ((rtinfo->rt_type == rh->type) ^ - !!(rtinfo->invflags & IP6T_RT_INV_TYP)))); - DEBUGP("len %02X %04X %02X ", - rtinfo->hdrlen, hdrlen, - (!(rtinfo->flags & IP6T_RT_LEN) || - ((rtinfo->hdrlen == hdrlen) ^ - !!(rtinfo->invflags & IP6T_RT_INV_LEN)))); - DEBUGP("res %02X %02X %02X ", - (rtinfo->flags & IP6T_RT_RES), ((struct rt0_hdr *)rh)->reserved, - !((rtinfo->flags & IP6T_RT_RES) && (((struct rt0_hdr *)rh)->reserved))); - - ret = (rh != NULL) - && - (segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1], - rh->segments_left, - !!(rtinfo->invflags & IP6T_RT_INV_SGS))) - && - (!(rtinfo->flags & IP6T_RT_LEN) || - ((rtinfo->hdrlen == hdrlen) ^ - !!(rtinfo->invflags & IP6T_RT_INV_LEN))) - && - (!(rtinfo->flags & IP6T_RT_TYP) || - ((rtinfo->rt_type == rh->type) ^ - !!(rtinfo->invflags & IP6T_RT_INV_TYP))); + rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route); + if (rh == NULL) { + *hotdrop = 1; + return 0; + } + + hdrlen = ipv6_optlen(rh); + if (skb->len - ptr < hdrlen) { + /* Pcket smaller than its length field */ + return 0; + } + + DEBUGP("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen); + DEBUGP("TYPE %04X ", rh->type); + DEBUGP("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left); + + DEBUGP("IPv6 RT segsleft %02X ", + (segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1], + rh->segments_left, + !!(rtinfo->invflags & IP6T_RT_INV_SGS)))); + DEBUGP("type %02X %02X %02X ", + rtinfo->rt_type, rh->type, + (!(rtinfo->flags & IP6T_RT_TYP) || + ((rtinfo->rt_type == rh->type) ^ + !!(rtinfo->invflags & IP6T_RT_INV_TYP)))); + DEBUGP("len %02X %04X %02X ", + rtinfo->hdrlen, hdrlen, + (!(rtinfo->flags & IP6T_RT_LEN) || + ((rtinfo->hdrlen == hdrlen) ^ + !!(rtinfo->invflags & IP6T_RT_INV_LEN)))); + DEBUGP("res %02X %02X %02X ", + (rtinfo->flags & IP6T_RT_RES), + ((struct rt0_hdr *)rh)->reserved, + !((rtinfo->flags & IP6T_RT_RES) && + (((struct rt0_hdr *)rh)->reserved))); + + ret = (rh != NULL) + && + (segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1], + rh->segments_left, + !!(rtinfo->invflags & IP6T_RT_INV_SGS))) + && + (!(rtinfo->flags & IP6T_RT_LEN) || + ((rtinfo->hdrlen == hdrlen) ^ + !!(rtinfo->invflags & IP6T_RT_INV_LEN))) + && + (!(rtinfo->flags & IP6T_RT_TYP) || + ((rtinfo->rt_type == rh->type) ^ + !!(rtinfo->invflags & IP6T_RT_INV_TYP))); if (ret && (rtinfo->flags & IP6T_RT_RES)) { u_int32_t *rp, _reserved; rp = skb_header_pointer(skb, - ptr + offsetof(struct rt0_hdr, reserved), - sizeof(_reserved), &_reserved); + ptr + offsetof(struct rt0_hdr, + reserved), + sizeof(_reserved), + &_reserved); ret = (*rp == 0); } - DEBUGP("#%d ",rtinfo->addrnr); - if ( !(rtinfo->flags & IP6T_RT_FST) ){ - return ret; + DEBUGP("#%d ", rtinfo->addrnr); + if (!(rtinfo->flags & IP6T_RT_FST)) { + return ret; } else if (rtinfo->flags & IP6T_RT_FST_NSTRICT) { DEBUGP("Not strict "); - if ( rtinfo->addrnr > (unsigned int)((hdrlen-8)/16) ){ + if (rtinfo->addrnr > (unsigned int)((hdrlen - 8) / 16)) { DEBUGP("There isn't enough space\n"); return 0; } else { unsigned int i = 0; - DEBUGP("#%d ",rtinfo->addrnr); - for(temp=0; temp<(unsigned int)((hdrlen-8)/16); temp++){ + DEBUGP("#%d ", rtinfo->addrnr); + for (temp = 0; + temp < (unsigned int)((hdrlen - 8) / 16); + temp++) { ap = skb_header_pointer(skb, ptr + sizeof(struct rt0_hdr) @@ -141,24 +147,26 @@ match(const struct sk_buff *skb, BUG_ON(ap == NULL); if (ipv6_addr_equal(ap, &rtinfo->addrs[i])) { - DEBUGP("i=%d temp=%d;\n",i,temp); + DEBUGP("i=%d temp=%d;\n", i, temp); i++; } - if (i==rtinfo->addrnr) break; + if (i == rtinfo->addrnr) + break; } DEBUGP("i=%d #%d\n", i, rtinfo->addrnr); if (i == rtinfo->addrnr) return ret; - else return 0; + else + return 0; } } else { DEBUGP("Strict "); - if ( rtinfo->addrnr > (unsigned int)((hdrlen-8)/16) ){ + if (rtinfo->addrnr > (unsigned int)((hdrlen - 8) / 16)) { DEBUGP("There isn't enough space\n"); return 0; } else { - DEBUGP("#%d ",rtinfo->addrnr); - for(temp=0; tempaddrnr; temp++){ + DEBUGP("#%d ", rtinfo->addrnr); + for (temp = 0; temp < rtinfo->addrnr; temp++) { ap = skb_header_pointer(skb, ptr + sizeof(struct rt0_hdr) @@ -171,9 +179,11 @@ match(const struct sk_buff *skb, break; } DEBUGP("temp=%d #%d\n", temp, rtinfo->addrnr); - if ((temp == rtinfo->addrnr) && (temp == (unsigned int)((hdrlen-8)/16))) + if ((temp == rtinfo->addrnr) && + (temp == (unsigned int)((hdrlen - 8) / 16))) return ret; - else return 0; + else + return 0; } } @@ -183,32 +193,31 @@ match(const struct sk_buff *skb, /* Called when user tries to insert an entry of this type. */ static int checkentry(const char *tablename, - const void *entry, - void *matchinfo, - unsigned int matchinfosize, - unsigned int hook_mask) + const void *entry, + void *matchinfo, + unsigned int matchinfosize, + unsigned int hook_mask) { - const struct ip6t_rt *rtinfo = matchinfo; - - if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_rt))) { - DEBUGP("ip6t_rt: matchsize %u != %u\n", - matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_rt))); - return 0; - } - if (rtinfo->invflags & ~IP6T_RT_INV_MASK) { - DEBUGP("ip6t_rt: unknown flags %X\n", - rtinfo->invflags); - return 0; - } - if ( (rtinfo->flags & (IP6T_RT_RES|IP6T_RT_FST_MASK)) && - (!(rtinfo->flags & IP6T_RT_TYP) || - (rtinfo->rt_type != 0) || - (rtinfo->invflags & IP6T_RT_INV_TYP)) ) { - DEBUGP("`--rt-type 0' required before `--rt-0-*'"); - return 0; - } - - return 1; + const struct ip6t_rt *rtinfo = matchinfo; + + if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_rt))) { + DEBUGP("ip6t_rt: matchsize %u != %u\n", + matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_rt))); + return 0; + } + if (rtinfo->invflags & ~IP6T_RT_INV_MASK) { + DEBUGP("ip6t_rt: unknown flags %X\n", rtinfo->invflags); + return 0; + } + if ((rtinfo->flags & (IP6T_RT_RES | IP6T_RT_FST_MASK)) && + (!(rtinfo->flags & IP6T_RT_TYP) || + (rtinfo->rt_type != 0) || + (rtinfo->invflags & IP6T_RT_INV_TYP))) { + DEBUGP("`--rt-type 0' required before `--rt-0-*'"); + return 0; + } + + return 1; } static struct ip6t_match rt_match = { @@ -220,12 +229,12 @@ static struct ip6t_match rt_match = { static int __init init(void) { - return ip6t_register_match(&rt_match); + return ip6t_register_match(&rt_match); } static void __exit cleanup(void) { - ip6t_unregister_match(&rt_match); + ip6t_unregister_match(&rt_match); } module_init(init); -- GitLab From ec41c7dfd525468decb9da9281dbc9ed82d98c98 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Tue, 17 Jan 2006 02:40:55 -0800 Subject: [PATCH 451/465] [TG3]: Refine nvram locking Add nvram lock count so that calls to tg3_nvram_lock()/unlock() can be nested. Add error checking to all callers of tg3_nvram_lock() where appropriate. To prevent nvram lock failures after halting the firmware, it is also necessary to release firmware's nvram lock in tg3_halt_cpu(). Update version to 3.48. Based on David Miller's initial patch. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 82 +++++++++++++++++++++++++++++++---------------- drivers/net/tg3.h | 1 + 2 files changed, 55 insertions(+), 28 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index eb86b059809..f2d1dafde08 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -69,8 +69,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.47" -#define DRV_MODULE_RELDATE "Dec 28, 2005" +#define DRV_MODULE_VERSION "3.48" +#define DRV_MODULE_RELDATE "Jan 16, 2006" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -1325,10 +1325,12 @@ static int tg3_set_power_state(struct tg3 *tp, int state) val &= ~((1 << 16) | (1 << 4) | (1 << 2) | (1 << 1) | 1); tw32(0x7d00, val); if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { - tg3_nvram_lock(tp); + int err; + + err = tg3_nvram_lock(tp); tg3_halt_cpu(tp, RX_CPU_BASE); - tw32_f(NVRAM_SWARB, SWARB_REQ_CLR0); - tg3_nvram_unlock(tp); + if (!err) + tg3_nvram_unlock(tp); } } @@ -4193,14 +4195,19 @@ static int tg3_nvram_lock(struct tg3 *tp) if (tp->tg3_flags & TG3_FLAG_NVRAM) { int i; - tw32(NVRAM_SWARB, SWARB_REQ_SET1); - for (i = 0; i < 8000; i++) { - if (tr32(NVRAM_SWARB) & SWARB_GNT1) - break; - udelay(20); + if (tp->nvram_lock_cnt == 0) { + tw32(NVRAM_SWARB, SWARB_REQ_SET1); + for (i = 0; i < 8000; i++) { + if (tr32(NVRAM_SWARB) & SWARB_GNT1) + break; + udelay(20); + } + if (i == 8000) { + tw32(NVRAM_SWARB, SWARB_REQ_CLR1); + return -ENODEV; + } } - if (i == 8000) - return -ENODEV; + tp->nvram_lock_cnt++; } return 0; } @@ -4208,8 +4215,12 @@ static int tg3_nvram_lock(struct tg3 *tp) /* tp->lock is held. */ static void tg3_nvram_unlock(struct tg3 *tp) { - if (tp->tg3_flags & TG3_FLAG_NVRAM) - tw32_f(NVRAM_SWARB, SWARB_REQ_CLR1); + if (tp->tg3_flags & TG3_FLAG_NVRAM) { + if (tp->nvram_lock_cnt > 0) + tp->nvram_lock_cnt--; + if (tp->nvram_lock_cnt == 0) + tw32_f(NVRAM_SWARB, SWARB_REQ_CLR1); + } } /* tp->lock is held. */ @@ -4320,8 +4331,13 @@ static int tg3_chip_reset(struct tg3 *tp) void (*write_op)(struct tg3 *, u32, u32); int i; - if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) + if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) { tg3_nvram_lock(tp); + /* No matching tg3_nvram_unlock() after this because + * chip reset below will undo the nvram lock. + */ + tp->nvram_lock_cnt = 0; + } /* * We must avoid the readl() that normally takes place. @@ -4717,6 +4733,10 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset) (offset == RX_CPU_BASE ? "RX" : "TX")); return -ENODEV; } + + /* Clear firmware's nvram arbitration. */ + if (tp->tg3_flags & TG3_FLAG_NVRAM) + tw32(NVRAM_SWARB, SWARB_REQ_CLR0); return 0; } @@ -4736,7 +4756,7 @@ struct fw_info { static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_base, int cpu_scratch_size, struct fw_info *info) { - int err, i; + int err, lock_err, i; void (*write_op)(struct tg3 *, u32, u32); if (cpu_base == TX_CPU_BASE && @@ -4755,9 +4775,10 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_b /* It is possible that bootcode is still loading at this point. * Get the nvram lock first before halting the cpu. */ - tg3_nvram_lock(tp); + lock_err = tg3_nvram_lock(tp); err = tg3_halt_cpu(tp, cpu_base); - tg3_nvram_unlock(tp); + if (!lock_err) + tg3_nvram_unlock(tp); if (err) goto out; @@ -8182,7 +8203,7 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, data[1] = 1; } if (etest->flags & ETH_TEST_FL_OFFLINE) { - int irq_sync = 0; + int err, irq_sync = 0; if (netif_running(dev)) { tg3_netif_stop(tp); @@ -8192,11 +8213,12 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, tg3_full_lock(tp, irq_sync); tg3_halt(tp, RESET_KIND_SUSPEND, 1); - tg3_nvram_lock(tp); + err = tg3_nvram_lock(tp); tg3_halt_cpu(tp, RX_CPU_BASE); if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) tg3_halt_cpu(tp, TX_CPU_BASE); - tg3_nvram_unlock(tp); + if (!err) + tg3_nvram_unlock(tp); if (tg3_test_registers(tp) != 0) { etest->flags |= ETH_TEST_FL_FAILED; @@ -8588,7 +8610,11 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) { tp->tg3_flags |= TG3_FLAG_NVRAM; - tg3_nvram_lock(tp); + if (tg3_nvram_lock(tp)) { + printk(KERN_WARNING PFX "%s: Cannot get nvarm lock, " + "tg3_nvram_init failed.\n", tp->dev->name); + return; + } tg3_enable_nvram_access(tp); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752) @@ -8686,7 +8712,9 @@ static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val) if (offset > NVRAM_ADDR_MSK) return -EINVAL; - tg3_nvram_lock(tp); + ret = tg3_nvram_lock(tp); + if (ret) + return ret; tg3_enable_nvram_access(tp); @@ -8785,10 +8813,6 @@ static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len, offset = offset + (pagesize - page_off); - /* Nvram lock released by tg3_nvram_read() above, - * so need to get it again. - */ - tg3_nvram_lock(tp); tg3_enable_nvram_access(tp); /* @@ -8925,7 +8949,9 @@ static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf) else { u32 grc_mode; - tg3_nvram_lock(tp); + ret = tg3_nvram_lock(tp); + if (ret) + return ret; tg3_enable_nvram_access(tp); if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) && diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 890e1635996..e8243305f0e 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2275,6 +2275,7 @@ struct tg3 { dma_addr_t stats_mapping; struct work_struct reset_task; + int nvram_lock_cnt; u32 nvram_size; u32 nvram_pagesize; u32 nvram_jedecnum; -- GitLab From f09484ff87f677056ce631aa3d8e486861501b51 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 17 Jan 2006 02:42:02 -0800 Subject: [PATCH 452/465] [NETFILTER]: ip_conntrack_proto_gre.c needs linux/interrupt.h Signed-off-by: David S. Miller --- net/ipv4/netfilter/ip_conntrack_proto_gre.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv4/netfilter/ip_conntrack_proto_gre.c b/net/ipv4/netfilter/ip_conntrack_proto_gre.c index c777abf16cb..56794797d55 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_gre.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_gre.c @@ -32,6 +32,7 @@ #include #include #include +#include static DEFINE_RWLOCK(ip_ct_gre_lock); #define ASSERT_READ_LOCK(x) -- GitLab From 8243126c5e29030bf1a3fb75187a513966dcba62 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 17 Jan 2006 02:54:21 -0800 Subject: [PATCH 453/465] [NET]: Make second arg to skb_reserved() signed. Some subsystems, such as PPP, can send negative values here. It just happened to work correctly on 32-bit with an unsigned value, but on 64-bit this explodes. Figured out by Paul Mackerras based upon several PPP crash reports. Signed-off-by: David S. Miller --- include/linux/skbuff.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index e5fd66c5650..ad7cc22bd42 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -926,7 +926,7 @@ static inline int skb_tailroom(const struct sk_buff *skb) * Increase the headroom of an empty &sk_buff by reducing the tail * room. This is only allowed for an empty buffer. */ -static inline void skb_reserve(struct sk_buff *skb, unsigned int len) +static inline void skb_reserve(struct sk_buff *skb, int len) { skb->data += len; skb->tail += len; -- GitLab From 2f970d83576cf4938fd75551c465050f6a16c33c Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 17 Jan 2006 02:54:36 -0800 Subject: [PATCH 454/465] [IPV4]: rt_cache_stat can be statically defined Using __get_cpu_var(obj) is slightly faster than per_cpu_ptr(obj, raw_smp_processor_id()). 1) Smaller code and memory use For static and small objects, DEFINE_PER_CPU(type, object) is preferred over a alloc_percpu() : Better and smaller code to access them, and no extra memory (storing the pointer, and the percpu array of pointers) x86_64 code before patch mov 1237577(%rip),%rax # ffffffff803e5990 not %rax # part of per_cpu machinery mov %gs:0x3c,%edx # get cpu number movslq %edx,%rdx # extend 32 bits cpu number to 64 bits mov (%rax,%rdx,8),%rax # get the pointer for this cpu incl 0x38(%rax) x86_64 code after patch mov $per_cpu__rt_cache_stat,%rdx mov %gs:0x48,%rax # get percpu data offset incl 0x38(%rax,%rdx,1) 2) False sharing avoidance for SMP : For a small NR_CPUS, the array of per cpu pointers allocated in alloc_percpu() can be <= 32 bytes. This let slab code gives a part of a cache line. If the other part of this 64 bytes (or 128 bytes) cache line is used by a mostly written object, we can have false sharing and expensive per_cpu_ptr() operations. Size of rt_cache_stat is 64 bytes, so this patch is not a danger of a too big increase of bss (in UP mode) or static per_cpu data for SMP (PERCPU_ENOUGH_ROOM is currently 32768 bytes) Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/route.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index f701a136a6a..f2e82afc15b 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -240,9 +240,8 @@ static unsigned rt_hash_mask; static int rt_hash_log; static unsigned int rt_hash_rnd; -static struct rt_cache_stat *rt_cache_stat; -#define RT_CACHE_STAT_INC(field) \ - (per_cpu_ptr(rt_cache_stat, raw_smp_processor_id())->field++) +static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat); +#define RT_CACHE_STAT_INC(field) (__get_cpu_var(rt_cache_stat).field++) static int rt_intern_hash(unsigned hash, struct rtable *rth, struct rtable **res); @@ -401,7 +400,7 @@ static void *rt_cpu_seq_start(struct seq_file *seq, loff_t *pos) if (!cpu_possible(cpu)) continue; *pos = cpu+1; - return per_cpu_ptr(rt_cache_stat, cpu); + return &per_cpu(rt_cache_stat, cpu); } return NULL; } @@ -414,7 +413,7 @@ static void *rt_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos) if (!cpu_possible(cpu)) continue; *pos = cpu+1; - return per_cpu_ptr(rt_cache_stat, cpu); + return &per_cpu(rt_cache_stat, cpu); } return NULL; @@ -3160,10 +3159,6 @@ int __init ip_rt_init(void) ipv4_dst_ops.gc_thresh = (rt_hash_mask + 1); ip_rt_max_size = (rt_hash_mask + 1) * 16; - rt_cache_stat = alloc_percpu(struct rt_cache_stat); - if (!rt_cache_stat) - return -ENOMEM; - devinet_init(); ip_fib_init(); @@ -3191,7 +3186,6 @@ int __init ip_rt_init(void) if (!proc_net_fops_create("rt_cache", S_IRUGO, &rt_cache_seq_fops) || !(rtstat_pde = create_proc_entry("rt_cache", S_IRUGO, proc_net_stat))) { - free_percpu(rt_cache_stat); return -ENOMEM; } rtstat_pde->proc_fops = &rt_cpu_seq_fops; -- GitLab From ae82af54d73becd66804d942cf39b049e625fa89 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Tue, 17 Jan 2006 13:01:06 -0800 Subject: [PATCH 455/465] [PKT_SCHED]: Handle SCTP/DCCP in sfq_hash Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/sched/sch_sfq.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 8734bb7280e..86d8da0cbd0 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -144,6 +144,8 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP || + iph->protocol == IPPROTO_SCTP || + iph->protocol == IPPROTO_DCCP || iph->protocol == IPPROTO_ESP)) h2 ^= *(((u32*)iph) + iph->ihl); break; @@ -155,6 +157,8 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) h2 = iph->saddr.s6_addr32[3]^iph->nexthdr; if (iph->nexthdr == IPPROTO_TCP || iph->nexthdr == IPPROTO_UDP || + iph->nexthdr == IPPROTO_SCTP || + iph->nexthdr == IPPROTO_DCCP || iph->nexthdr == IPPROTO_ESP) h2 ^= *(u32*)&iph[1]; break; -- GitLab From ab67a4d511188680beb8a0d82a90f55dbeb53d5c Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Tue, 17 Jan 2006 13:01:31 -0800 Subject: [PATCH 456/465] [EBTABLES]: Handle SCTP/DCCP in ebt_{ip,log} Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/bridge/netfilter/ebt_ip.c | 4 +++- net/bridge/netfilter/ebt_log.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/net/bridge/netfilter/ebt_ip.c b/net/bridge/netfilter/ebt_ip.c index f158fe67dd6..dc5d0b2427c 100644 --- a/net/bridge/netfilter/ebt_ip.c +++ b/net/bridge/netfilter/ebt_ip.c @@ -92,7 +92,9 @@ static int ebt_ip_check(const char *tablename, unsigned int hookmask, if (info->invflags & EBT_IP_PROTO) return -EINVAL; if (info->protocol != IPPROTO_TCP && - info->protocol != IPPROTO_UDP) + info->protocol != IPPROTO_UDP && + info->protocol != IPPROTO_SCTP && + info->protocol != IPPROTO_DCCP) return -EINVAL; } if (info->bitmask & EBT_IP_DPORT && info->dport[0] > info->dport[1]) diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c index a29c1232c42..0128fbbe232 100644 --- a/net/bridge/netfilter/ebt_log.c +++ b/net/bridge/netfilter/ebt_log.c @@ -95,7 +95,9 @@ ebt_log_packet(unsigned int pf, unsigned int hooknum, "tos=0x%02X, IP proto=%d", NIPQUAD(ih->saddr), NIPQUAD(ih->daddr), ih->tos, ih->protocol); if (ih->protocol == IPPROTO_TCP || - ih->protocol == IPPROTO_UDP) { + ih->protocol == IPPROTO_UDP || + ih->protocol == IPPROTO_SCTP || + ih->protocol == IPPROTO_DCCP) { struct tcpudphdr _ports, *pptr; pptr = skb_header_pointer(skb, ih->ihl*4, -- GitLab From a8fc3d8decfd5601fb14a2163952f81fa6b971bb Mon Sep 17 00:00:00 2001 From: Kris Katterjohn Date: Tue, 17 Jan 2006 13:03:54 -0800 Subject: [PATCH 457/465] [NET]: "signed long" -> "long" Signed-off-by: Kris Katterjohn Signed-off-by: David S. Miller --- net/dccp/ackvec.c | 2 +- net/rxrpc/krxtimod.c | 2 +- net/rxrpc/proc.c | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c index ce9cb77c5c2..2c77dafbd09 100644 --- a/net/dccp/ackvec.c +++ b/net/dccp/ackvec.c @@ -144,7 +144,7 @@ static inline int dccp_ackvec_set_buf_head_state(struct dccp_ackvec *av, const unsigned char state) { unsigned int gap; - signed long new_head; + long new_head; if (av->dccpav_vec_len + packets > av->dccpav_buf_len) return -ENOBUFS; diff --git a/net/rxrpc/krxtimod.c b/net/rxrpc/krxtimod.c index 3ac81cdd121..3e7466900bd 100644 --- a/net/rxrpc/krxtimod.c +++ b/net/rxrpc/krxtimod.c @@ -81,7 +81,7 @@ static int krxtimod(void *arg) for (;;) { unsigned long jif; - signed long timeout; + long timeout; /* deal with the server being asked to die */ if (krxtimod_die) { diff --git a/net/rxrpc/proc.c b/net/rxrpc/proc.c index 3b5ecd8e240..29975d99d86 100644 --- a/net/rxrpc/proc.c +++ b/net/rxrpc/proc.c @@ -361,7 +361,7 @@ static void rxrpc_proc_peers_stop(struct seq_file *p, void *v) static int rxrpc_proc_peers_show(struct seq_file *m, void *v) { struct rxrpc_peer *peer = list_entry(v, struct rxrpc_peer, proc_link); - signed long timeout; + long timeout; /* display header on line 1 */ if (v == SEQ_START_TOKEN) { @@ -373,8 +373,8 @@ static int rxrpc_proc_peers_show(struct seq_file *m, void *v) /* display one peer per line on subsequent lines */ timeout = 0; if (!list_empty(&peer->timeout.link)) - timeout = (signed long) peer->timeout.timo_jif - - (signed long) jiffies; + timeout = (long) peer->timeout.timo_jif - + (long) jiffies; seq_printf(m, "%5hu %08x %5d %5d %8ld %5Zu %7lu\n", peer->trans->port, @@ -468,7 +468,7 @@ static void rxrpc_proc_conns_stop(struct seq_file *p, void *v) static int rxrpc_proc_conns_show(struct seq_file *m, void *v) { struct rxrpc_connection *conn; - signed long timeout; + long timeout; conn = list_entry(v, struct rxrpc_connection, proc_link); @@ -484,8 +484,8 @@ static int rxrpc_proc_conns_show(struct seq_file *m, void *v) /* display one conn per line on subsequent lines */ timeout = 0; if (!list_empty(&conn->timeout.link)) - timeout = (signed long) conn->timeout.timo_jif - - (signed long) jiffies; + timeout = (long) conn->timeout.timo_jif - + (long) jiffies; seq_printf(m, "%5hu %08x %5hu %04hx %08x %-3.3s %08x %08x %5Zu %8ld\n", -- GitLab From f404e9a67ffdc0bb0302a5ad1f7eaf58e5a59109 Mon Sep 17 00:00:00 2001 From: Kris Katterjohn Date: Tue, 17 Jan 2006 13:04:57 -0800 Subject: [PATCH 458/465] [PKTGEN]: Replacing with (compare|is_zero)_ether_addr() and ETH_ALEN This replaces some tests with is_zero_ether_addr(), memcmp(one, two, 6) with compare_ether_addr(one, two), and 6 with ETH_ALEN where appropriate. Signed-off-by: Kris Katterjohn Signed-off-by: David S. Miller --- net/core/pktgen.c | 34 +++++++++++----------------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 39063122fbb..3827f881f42 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -139,6 +139,7 @@ #include #include #include +#include #include #include #include @@ -281,8 +282,8 @@ struct pktgen_dev { __u32 src_mac_count; /* How many MACs to iterate through */ __u32 dst_mac_count; /* How many MACs to iterate through */ - unsigned char dst_mac[6]; - unsigned char src_mac[6]; + unsigned char dst_mac[ETH_ALEN]; + unsigned char src_mac[ETH_ALEN]; __u32 cur_dst_mac_offset; __u32 cur_src_mac_offset; @@ -594,16 +595,9 @@ static int pktgen_if_show(struct seq_file *seq, void *v) seq_puts(seq, " src_mac: "); - if ((pkt_dev->src_mac[0] == 0) && - (pkt_dev->src_mac[1] == 0) && - (pkt_dev->src_mac[2] == 0) && - (pkt_dev->src_mac[3] == 0) && - (pkt_dev->src_mac[4] == 0) && - (pkt_dev->src_mac[5] == 0)) - + if (is_zero_ether_addr(pkt_dev->src_mac)) for (i = 0; i < 6; i++) seq_printf(seq, "%02X%s", pkt_dev->odev->dev_addr[i], i == 5 ? " " : ":"); - else for (i = 0; i < 6; i++) seq_printf(seq, "%02X%s", pkt_dev->src_mac[i], i == 5 ? " " : ":"); @@ -1189,9 +1183,9 @@ static ssize_t pktgen_if_write(struct file *file, const char __user *user_buffer } if (!strcmp(name, "dst_mac")) { char *v = valstr; - unsigned char old_dmac[6]; + unsigned char old_dmac[ETH_ALEN]; unsigned char *m = pkt_dev->dst_mac; - memcpy(old_dmac, pkt_dev->dst_mac, 6); + memcpy(old_dmac, pkt_dev->dst_mac, ETH_ALEN); len = strn_len(&user_buffer[i], sizeof(valstr) - 1); if (len < 0) { return len; } @@ -1220,8 +1214,8 @@ static ssize_t pktgen_if_write(struct file *file, const char __user *user_buffer } /* Set up Dest MAC */ - if (memcmp(old_dmac, pkt_dev->dst_mac, 6) != 0) - memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, 6); + if (compare_ether_addr(old_dmac, pkt_dev->dst_mac)) + memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, ETH_ALEN); sprintf(pg_result, "OK: dstmac"); return count; @@ -1560,17 +1554,11 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev) /* Default to the interface's mac if not explicitly set. */ - if ((pkt_dev->src_mac[0] == 0) && - (pkt_dev->src_mac[1] == 0) && - (pkt_dev->src_mac[2] == 0) && - (pkt_dev->src_mac[3] == 0) && - (pkt_dev->src_mac[4] == 0) && - (pkt_dev->src_mac[5] == 0)) { + if (is_zero_ether_addr(pkt_dev->src_mac)) + memcpy(&(pkt_dev->hh[6]), pkt_dev->odev->dev_addr, ETH_ALEN); - memcpy(&(pkt_dev->hh[6]), pkt_dev->odev->dev_addr, 6); - } /* Set up Dest MAC */ - memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, 6); + memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, ETH_ALEN); /* Set up pkt size */ pkt_dev->cur_pkt_size = pkt_dev->min_pkt_size; -- GitLab From 64af4c13622511257daba762b32d9d20f2d0c4b5 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 17 Jan 2006 15:14:49 -0800 Subject: [PATCH 459/465] [CASSINI]: Fix printk warning. drivers/net/cassini.c:1930: warning: long unsigned int format, different type arg (arg 4) Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/net/cassini.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 1f7ca453bb4..dde631f8f68 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -1925,8 +1925,8 @@ static void cas_tx(struct net_device *dev, struct cas *cp, u64 compwb = le64_to_cpu(cp->init_block->tx_compwb); #endif if (netif_msg_intr(cp)) - printk(KERN_DEBUG "%s: tx interrupt, status: 0x%x, %lx\n", - cp->dev->name, status, compwb); + printk(KERN_DEBUG "%s: tx interrupt, status: 0x%x, %llx\n", + cp->dev->name, status, (unsigned long long)compwb); /* process all the rings */ for (ring = 0; ring < N_TX_RINGS; ring++) { #ifdef USE_TX_COMPWB -- GitLab From 3860288ee8298bf2784e9a0c37d26d3a82941e35 Mon Sep 17 00:00:00 2001 From: Kris Katterjohn Date: Tue, 17 Jan 2006 15:15:38 -0800 Subject: [PATCH 460/465] [NET]: Use is_zero_ether_addr() in net/core/netpoll.c This replaces a memcmp() with is_zero_ether_addr(). Signed-off-by: Kris Katterjohn Signed-off-by: David S. Miller --- net/core/netpoll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 281a632fa6a..ea51f8d02eb 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -703,7 +703,7 @@ int netpoll_setup(struct netpoll *np) } } - if (!memcmp(np->local_mac, "\0\0\0\0\0\0", 6) && ndev->dev_addr) + if (is_zero_ether_addr(np->local_mac) && ndev->dev_addr) memcpy(np->local_mac, ndev->dev_addr, 6); if (!np->local_ip) { -- GitLab From 9eb3394bf2037120881a8846bc67064f49325366 Mon Sep 17 00:00:00 2001 From: Richard Mortimer Date: Tue, 17 Jan 2006 15:21:01 -0800 Subject: [PATCH 461/465] [SPARC64]: Eliminate race condition reading Hummingbird STICK register Ensure a consistent value is read from the STICK register by ensuring that both high and low are read without high changing due to a roll over of the low register. Various Debian/SPARC users (myself include) have noticed problems with Hummingbird based systems. The symptoms are that the system time is seen to jump forward 3 days, 6 hours, 11 minutes give or take a few seconds. In many cases the system then hangs some time afterwards. I've spotted a race condition in the code to read the STICK register. I could not work out why 3d, 6h, 11m is important but guess that it is due to the 2^32 jump of STICK (forwards on one read and then the next read will seem to be backwards) during a timer interrupt. I'm guessing that a change of -2^32 will get converted to a large unsigned increment after the arithmetic manipulation between STICK, nanoseconds, jiffies etc. I did a test where I modified __hbird_read_stick to artificially inject rollover faults forcefully every few seconds. With this I saw the clock jump over 6 times in 12 hours compared to once every month or so. Signed-off-by: Richard Mortimer Signed-off-by: David S. Miller --- arch/sparc64/kernel/time.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 459c8fbe02b..a22930d62ad 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -280,9 +280,9 @@ static struct sparc64_tick_ops stick_operations __read_mostly = { * Since STICK is constantly updating, we have to access it carefully. * * The sequence we use to read is: - * 1) read low - * 2) read high - * 3) read low again, if it rolled over increment high by 1 + * 1) read high + * 2) read low + * 3) read high again, if it rolled re-read both low and high again. * * Writing STICK safely is also tricky: * 1) write low to zero @@ -295,18 +295,18 @@ static struct sparc64_tick_ops stick_operations __read_mostly = { static unsigned long __hbird_read_stick(void) { unsigned long ret, tmp1, tmp2, tmp3; - unsigned long addr = HBIRD_STICK_ADDR; + unsigned long addr = HBIRD_STICK_ADDR+8; - __asm__ __volatile__("ldxa [%1] %5, %2\n\t" - "add %1, 0x8, %1\n\t" - "ldxa [%1] %5, %3\n\t" + __asm__ __volatile__("ldxa [%1] %5, %2\n" + "1:\n\t" "sub %1, 0x8, %1\n\t" + "ldxa [%1] %5, %3\n\t" + "add %1, 0x8, %1\n\t" "ldxa [%1] %5, %4\n\t" "cmp %4, %2\n\t" - "blu,a,pn %%xcc, 1f\n\t" - " add %3, 1, %3\n" - "1:\n\t" - "sllx %3, 32, %3\n\t" + "bne,a,pn %%xcc, 1b\n\t" + " mov %4, %2\n\t" + "sllx %4, 32, %4\n\t" "or %3, %4, %0\n\t" : "=&r" (ret), "=&r" (addr), "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3) -- GitLab From 1ae613883468eab2fb8a077aad9fdedfbfa73d1b Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Tue, 17 Jan 2006 15:36:05 -0800 Subject: [PATCH 462/465] [SPARC]: change if() BUG(); to BUG_ON in iommu.c this patch changes if() BUG(); constructs in iommu.c to BUG_ON(); so it gets save to define BUG() and BUG_ON() to nullstatements. Signed-off-by: Eric Sesterhenn Signed-off-by: David S. Miller --- arch/sparc/mm/iommu.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c index 489bf68d5f0..77840c80478 100644 --- a/arch/sparc/mm/iommu.c +++ b/arch/sparc/mm/iommu.c @@ -295,8 +295,7 @@ static void iommu_release_one(u32 busa, int npages, struct sbus_bus *sbus) int ioptex; int i; - if (busa < iommu->start) - BUG(); + BUG_ON(busa < iommu->start); ioptex = (busa - iommu->start) >> PAGE_SHIFT; for (i = 0; i < npages; i++) { iopte_val(iommu->page_table[ioptex + i]) = 0; @@ -340,9 +339,9 @@ static int iommu_map_dma_area(dma_addr_t *pba, unsigned long va, iopte_t *first; int ioptex; - if ((va & ~PAGE_MASK) != 0) BUG(); - if ((addr & ~PAGE_MASK) != 0) BUG(); - if ((len & ~PAGE_MASK) != 0) BUG(); + BUG_ON((va & ~PAGE_MASK) != 0); + BUG_ON((addr & ~PAGE_MASK) != 0); + BUG_ON((len & ~PAGE_MASK) != 0); /* page color = physical address */ ioptex = bit_map_string_get(&iommu->usemap, len >> PAGE_SHIFT, @@ -405,8 +404,8 @@ static void iommu_unmap_dma_area(unsigned long busa, int len) unsigned long end; int ioptex = (busa - iommu->start) >> PAGE_SHIFT; - if ((busa & ~PAGE_MASK) != 0) BUG(); - if ((len & ~PAGE_MASK) != 0) BUG(); + BUG_ON((busa & ~PAGE_MASK) != 0); + BUG_ON((len & ~PAGE_MASK) != 0); iopte += ioptex; end = busa + len; -- GitLab From c7006638a50cbf16bb420fa91e5af2dd22d28621 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 17 Jan 2006 15:53:11 -0800 Subject: [PATCH 463/465] [SPARC]: Fix sbusfb build. sbusfb_compat_ioctl() needs to return int, not long, as that is what the fb_ops->fb_compat_ioctl method prototype wants. Need to git rid of the "struct file *file" first argument to fbiogetputcmap() and fbiogscursor() to match calls done in sbusfb_compat_ioctl(). Signed-off-by: David S. Miller --- drivers/video/sbuslib.c | 9 +++------ drivers/video/sbuslib.h | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/video/sbuslib.c b/drivers/video/sbuslib.c index 55e6e2d60d3..a4d7cc51ce0 100644 --- a/drivers/video/sbuslib.c +++ b/drivers/video/sbuslib.c @@ -199,8 +199,7 @@ struct fbcmap32 { #define FBIOPUTCMAP32 _IOW('F', 3, struct fbcmap32) #define FBIOGETCMAP32 _IOW('F', 4, struct fbcmap32) -static int fbiogetputcmap(struct file *file, struct fb_info *info, - unsigned int cmd, unsigned long arg) +static int fbiogetputcmap(struct fb_info *info, unsigned int cmd, unsigned long arg) { struct fbcmap32 __user *argp = (void __user *)arg; struct fbcmap __user *p = compat_alloc_user_space(sizeof(*p)); @@ -236,8 +235,7 @@ struct fbcursor32 { #define FBIOSCURSOR32 _IOW('F', 24, struct fbcursor32) #define FBIOGCURSOR32 _IOW('F', 25, struct fbcursor32) -static int fbiogscursor(struct file *file, struct fb_info *info, - unsigned long arg) +static int fbiogscursor(struct fb_info *info, unsigned long arg) { struct fbcursor __user *p = compat_alloc_user_space(sizeof(*p)); struct fbcursor32 __user *argp = (void __user *)arg; @@ -263,8 +261,7 @@ static int fbiogscursor(struct file *file, struct fb_info *info, return info->fbops->fb_ioctl(info, FBIOSCURSOR, (unsigned long)p); } -long sbusfb_compat_ioctl(struct fb_info *info, unsigned int cmd, - unsigned long arg) +int sbusfb_compat_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { switch (cmd) { case FBIOGTYPE: diff --git a/drivers/video/sbuslib.h b/drivers/video/sbuslib.h index f753939013e..492828c3fe8 100644 --- a/drivers/video/sbuslib.h +++ b/drivers/video/sbuslib.h @@ -20,7 +20,7 @@ extern int sbusfb_mmap_helper(struct sbus_mmap_map *map, int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg, struct fb_info *info, int type, int fb_depth, unsigned long fb_size); -long sbusfb_compat_ioctl(struct fb_info *info, unsigned int cmd, +int sbusfb_compat_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg); #endif /* _SBUSLIB_H */ -- GitLab From 4f3f2f6f3e7ce68c533e7786114f05181772ff6f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 17 Jan 2006 15:55:58 -0800 Subject: [PATCH 464/465] [SOUND]: sparc/cs4231: Fix some typos which wrecked the build. Signed-off-by: David S. Miller --- sound/sparc/cs4231.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index e9086e95a31..fd654399878 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -69,13 +69,14 @@ struct sbus_dma_info { }; #endif +struct snd_cs4231; struct cs4231_dma_control { void (*prepare)(struct cs4231_dma_control *dma_cont, int dir); void (*enable)(struct cs4231_dma_control *dma_cont, int on); int (*request)(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len); unsigned int (*address)(struct cs4231_dma_control *dma_cont); void (*reset)(struct snd_cs4231 *chip); - void (*preallocate)(struct snd_cs4231 *chip, struct snd_snd_pcm *pcm); + void (*preallocate)(struct snd_cs4231 *chip, struct snd_pcm *pcm); #ifdef EBUS_SUPPORT struct ebus_dma_info ebus_info; #endif -- GitLab From c6b3feaf5774508ab5a955a81e45ffefa3b12eaa Mon Sep 17 00:00:00 2001 From: Bryan O'Sullivan Date: Tue, 17 Jan 2006 17:00:05 -0800 Subject: [PATCH 465/465] [PATCH] Fix sparse parse error in lppaca.h sparse can't parse a struct definition in include/asm-powerpc/lppaca.h, even though gcc can accept it. The form looks like this: struct __attribute__((whatever)) foo { }; An equivalent that both gcc and sparse can handle is struct foo { } __attribute__((whatever)); This is the only definition of this type in the tree, and fixing it is easier than fixing sparse. Signed-off-by: Bryan O'Sullivan [ Side note: fixing sparse wouldn't be hard, but the "attribute at the end" version is the canonical one, and the one that makes sense. So let's just fix the kernel instead. Luc Van Oostenryck already sent out a sparse patch to the sparse mailing list in case anybody cares. -- Linus ] Signed-off-by: Linus Torvalds --- include/asm-powerpc/lppaca.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/asm-powerpc/lppaca.h b/include/asm-powerpc/lppaca.h index cd9f11f1ef1..4dc514aabfe 100644 --- a/include/asm-powerpc/lppaca.h +++ b/include/asm-powerpc/lppaca.h @@ -31,7 +31,7 @@ /* The Hypervisor barfs if the lppaca crosses a page boundary. A 1k * alignment is sufficient to prevent this */ -struct __attribute__((__aligned__(0x400))) lppaca { +struct lppaca { //============================================================================= // CACHE_LINE_1 0x0000 - 0x007F Contains read-only data // NOTE: The xDynXyz fields are fields that will be dynamically changed by @@ -129,7 +129,7 @@ struct __attribute__((__aligned__(0x400))) lppaca { // CACHE_LINE_4-5 0x0100 - 0x01FF Contains PMC interrupt data //============================================================================= u8 pmc_save_area[256]; // PMC interrupt Area x00-xFF -}; +} __attribute__((__aligned__(0x400))); extern struct lppaca lppaca[]; -- GitLab