From 51e9f2ff83df6b1c81c5c44f4486c68ed87aa20e Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Fri, 27 Jan 2006 16:50:27 -0500 Subject: [libata sata_sil] implement 'slow_down' module parameter On occasion, a user will submit a patch that enables the "mod15write" quirk for their device. Enabling this quirk has the effect of clamping all ATA commands to no more than 15 sectors. The intended use of this quirk is to stop the controller from generating FIS's of unusual size ("but Wesley, what about the FOUS's?"), which in turn works around problems in a of hard drives. One side effect of this quirk is greatly decreased performance. Users often enable the mod15write quirk to fix various system, power, chip, and/or driver problems. For a few rare problematic cases, enabling this has cured lockups or data corruption. Rather than add bogus listings to the mod15write quirk list (I get a patch every month doing such), we add a 'slow_down' module parameter. This allows users to employ a performance sledgehammer in the hopes of curing a problem. It defaults to off (0), of course. --- drivers/scsi/sata_sil.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index b017f85e6d6a..17f74d3c10e7 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -231,6 +231,10 @@ MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, sil_pci_tbl); MODULE_VERSION(DRV_VERSION); +static int slow_down = 0; +module_param(slow_down, int, 0444); +MODULE_PARM_DESC(slow_down, "Sledgehammer used to work around random problems, by limiting commands to 15 sectors (0=off, 1=on)"); + static unsigned char sil_get_device_cache_line(struct pci_dev *pdev) { @@ -354,8 +358,10 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev) } /* limit requests to 15 sectors */ - if ((ap->flags & SIL_FLAG_MOD15WRITE) && (quirks & SIL_QUIRK_MOD15WRITE)) { - printk(KERN_INFO "ata%u(%u): applying Seagate errata fix\n", + if (slow_down || + ((ap->flags & SIL_FLAG_MOD15WRITE) && + (quirks & SIL_QUIRK_MOD15WRITE))) { + printk(KERN_INFO "ata%u(%u): applying Seagate errata fix (mod15write workaround)\n", ap->id, dev->devno); ap->host->max_sectors = 15; ap->host->hostt->max_sectors = 15; -- cgit v1.2.3 From e4472cb3706ceea42797ae1dc79d624026986694 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 31 Jan 2006 15:53:55 -0800 Subject: [CPUFREQ] cpufreq_notify_transition cleanup. Introduce caching of cpufreq_cpu_data[freqs->cpu], which allows us to make the function a lot more readable, and as a nice side-effect, it now fits in < 80 column displays again. Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq.c | 47 ++++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 7a511479ae29..6bbe5825765a 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -229,44 +229,53 @@ static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) { /** - * cpufreq_notify_transition - call notifier chain and adjust_jiffies on frequency transition + * cpufreq_notify_transition - call notifier chain and adjust_jiffies + * on frequency transition. * - * This function calls the transition notifiers and the "adjust_jiffies" function. It is called - * twice on all CPU frequency changes that have external effects. + * This function calls the transition notifiers and the "adjust_jiffies" + * function. It is called twice on all CPU frequency changes that have + * external effects. */ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) { + struct cpufreq_policy *policy; + BUG_ON(irqs_disabled()); freqs->flags = cpufreq_driver->flags; - dprintk("notification %u of frequency transition to %u kHz\n", state, freqs->new); + dprintk("notification %u of frequency transition to %u kHz\n", + state, freqs->new); down_read(&cpufreq_notifier_rwsem); + + policy = cpufreq_cpu_data[freqs->cpu]; switch (state) { + case CPUFREQ_PRECHANGE: - /* detect if the driver reported a value as "old frequency" which - * is not equal to what the cpufreq core thinks is "old frequency". + /* detect if the driver reported a value as "old frequency" + * which is not equal to what the cpufreq core thinks is + * "old frequency". */ if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { - if ((likely(cpufreq_cpu_data[freqs->cpu])) && - (likely(cpufreq_cpu_data[freqs->cpu]->cpu == freqs->cpu)) && - (likely(cpufreq_cpu_data[freqs->cpu]->cur)) && - (unlikely(freqs->old != cpufreq_cpu_data[freqs->cpu]->cur))) - { - dprintk(KERN_WARNING "Warning: CPU frequency is %u, " - "cpufreq assumed %u kHz.\n", freqs->old, cpufreq_cpu_data[freqs->cpu]->cur); - freqs->old = cpufreq_cpu_data[freqs->cpu]->cur; + if ((policy) && (policy->cpu == freqs->cpu) && + (policy->cur) && (policy->cur != freqs->old)) { + dprintk(KERN_WARNING "Warning: CPU frequency is" + " %u, cpufreq assumed %u kHz.\n", + freqs->old, policy->cur); + freqs->old = policy->cur; } } - notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs); + notifier_call_chain(&cpufreq_transition_notifier_list, + CPUFREQ_PRECHANGE, freqs); adjust_jiffies(CPUFREQ_PRECHANGE, freqs); break; + case CPUFREQ_POSTCHANGE: adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); - notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs); - if ((likely(cpufreq_cpu_data[freqs->cpu])) && - (likely(cpufreq_cpu_data[freqs->cpu]->cpu == freqs->cpu))) - cpufreq_cpu_data[freqs->cpu]->cur = freqs->new; + notifier_call_chain(&cpufreq_transition_notifier_list, + CPUFREQ_POSTCHANGE, freqs); + if (likely(policy) && likely(policy->cpu == freqs->cpu)) + policy->cur = freqs->new; break; } up_read(&cpufreq_notifier_rwsem); -- cgit v1.2.3 From ddef9bb367b19383df627e388cb4c01c86ddba6c Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 2 Feb 2006 16:17:06 -0500 Subject: [libata sata_mv] do not enable PCI MSI by default Several bug reports have come in, noting that disabling CONFIG_PCI_MSI has fixed their problems with this driver. This may be generic system issues, but there is also the probability of unimplemented hardware errata workarounds. Until this ream of bug reports is sorted out, we can get them going in non-MSI interrupt mode. As such, this change adds an 'msi' module option, which defaults to off. --- drivers/scsi/sata_mv.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index cd54244058b5..6fddf17a3b70 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -509,6 +509,12 @@ static const struct mv_hw_ops mv6xxx_ops = { .reset_bus = mv_reset_pci_bus, }; +/* + * module options + */ +static int msi; /* Use PCI msi; either zero (off, default) or non-zero */ + + /* * Functions */ @@ -2191,7 +2197,7 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) } /* Enable interrupts */ - if (pci_enable_msi(pdev) == 0) { + if (msi && pci_enable_msi(pdev) == 0) { hpriv->hp_flags |= MV_HP_FLAG_MSI; } else { pci_intx(pdev, 1); @@ -2246,5 +2252,8 @@ MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, mv_pci_tbl); MODULE_VERSION(DRV_VERSION); +module_param(msi, int, 0444); +MODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)"); + module_init(mv_init); module_exit(mv_exit); -- cgit v1.2.3 From a85f7bd310dbc9010309bfe70b6b02432a11ef59 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Wed, 1 Feb 2006 11:36:04 +0100 Subject: [CPUFREQ] Check whether driver init did not initialize current freq Check whether driver init did not initialize current freq Signed-off-by: Thomas Renninger Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 6bbe5825765a..35eafbcf5ad5 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1442,8 +1442,13 @@ int cpufreq_update_policy(unsigned int cpu) -> ask driver for current freq and notify governors about a change */ if (cpufreq_driver->get) { policy.cur = cpufreq_driver->get(cpu); - if (data->cur != policy.cur) - cpufreq_out_of_sync(cpu, data->cur, policy.cur); + if (!data->cur) { + dprintk("Driver did not initialize current freq"); + data->cur = policy.cur; + } else { + if (data->cur != policy.cur) + cpufreq_out_of_sync(cpu, data->cur, policy.cur); + } } ret = __cpufreq_set_policy(data, &policy); -- cgit v1.2.3 From 7d5e350fab47f1273bc8b52d5f133ed6e4baeb7f Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 2 Feb 2006 17:03:42 -0500 Subject: [CPUFREQ] Whitespace/CodingStyle cleanups Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq.c | 54 ++++++++++++++++++----------------------------- 1 file changed, 21 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 35eafbcf5ad5..9582de1c9cad 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -35,8 +35,8 @@ * level driver of CPUFreq support, and its spinlock. This lock * also protects the cpufreq_cpu_data array. */ -static struct cpufreq_driver *cpufreq_driver; -static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS]; +static struct cpufreq_driver *cpufreq_driver; +static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS]; static DEFINE_SPINLOCK(cpufreq_driver_lock); /* internal prototypes */ @@ -50,15 +50,15 @@ static void handle_update(void *data); * changes to devices when the CPU clock speed changes. * The mutex locks both lists. */ -static struct notifier_block *cpufreq_policy_notifier_list; -static struct notifier_block *cpufreq_transition_notifier_list; -static DECLARE_RWSEM (cpufreq_notifier_rwsem); +static struct notifier_block *cpufreq_policy_notifier_list; +static struct notifier_block *cpufreq_transition_notifier_list; +static DECLARE_RWSEM (cpufreq_notifier_rwsem); static LIST_HEAD(cpufreq_governor_list); -static DEFINE_MUTEX (cpufreq_governor_mutex); +static DEFINE_MUTEX (cpufreq_governor_mutex); -struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu) +struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu) { struct cpufreq_policy *data; unsigned long flags; @@ -85,20 +85,19 @@ struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu) if (!kobject_get(&data->kobj)) goto err_out_put_module; - spin_unlock_irqrestore(&cpufreq_driver_lock, flags); - return data; - err_out_put_module: +err_out_put_module: module_put(cpufreq_driver->owner); - err_out_unlock: +err_out_unlock: spin_unlock_irqrestore(&cpufreq_driver_lock, flags); - err_out: +err_out: return NULL; } EXPORT_SYMBOL_GPL(cpufreq_cpu_get); + void cpufreq_cpu_put(struct cpufreq_policy *data) { kobject_put(&data->kobj); @@ -317,7 +316,7 @@ static int cpufreq_parse_governor (char *str_governor, unsigned int *policy, return 0; } } - out: +out: mutex_unlock(&cpufreq_governor_mutex); } return -EINVAL; @@ -424,7 +423,6 @@ static ssize_t store_scaling_governor (struct cpufreq_policy * policy, return -EINVAL; ret = cpufreq_set_policy(&new_policy); - return ret ? ret : count; } @@ -455,7 +453,7 @@ static ssize_t show_scaling_available_governors (struct cpufreq_policy * policy, goto out; i += scnprintf(&buf[i], CPUFREQ_NAME_LEN, "%s ", t->name); } - out: +out: i += sprintf(&buf[i], "\n"); return i; } @@ -798,7 +796,6 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) kfree(data); cpufreq_debug_enable_ratelimit(); - return 0; } @@ -879,8 +876,7 @@ unsigned int cpufreq_get(unsigned int cpu) ret = cpufreq_driver->get(cpu); - if (ret && policy->cur && !(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) - { + if (ret && policy->cur && !(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { /* verify no discrepancy between actual and saved value exists */ if (unlikely(ret != policy->cur)) { cpufreq_out_of_sync(cpu, policy->cur, ret); @@ -890,7 +886,7 @@ unsigned int cpufreq_get(unsigned int cpu) mutex_unlock(&policy->lock); - out: +out: cpufreq_cpu_put(policy); return (ret); @@ -971,7 +967,7 @@ static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg) cpu_policy->cur = cur_freq; } - out: +out: cpufreq_cpu_put(cpu_policy); return 0; } @@ -1178,7 +1174,6 @@ int cpufreq_driver_target(struct cpufreq_policy *policy, mutex_unlock(&policy->lock); cpufreq_cpu_put(policy); - return ret; } EXPORT_SYMBOL_GPL(cpufreq_driver_target); @@ -1217,7 +1212,6 @@ int cpufreq_governor(unsigned int cpu, unsigned int event) mutex_unlock(&policy->lock); cpufreq_cpu_put(policy); - return ret; } EXPORT_SYMBOL_GPL(cpufreq_governor); @@ -1241,7 +1235,6 @@ int cpufreq_register_governor(struct cpufreq_governor *governor) list_add(&governor->governor_list, &cpufreq_governor_list); mutex_unlock(&cpufreq_governor_mutex); - return 0; } EXPORT_SYMBOL_GPL(cpufreq_register_governor); @@ -1286,7 +1279,6 @@ int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu) mutex_unlock(&cpu_policy->lock); cpufreq_cpu_put(cpu_policy); - return 0; } EXPORT_SYMBOL(cpufreq_get_policy); @@ -1300,9 +1292,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli dprintk("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu, policy->min, policy->max); - memcpy(&policy->cpuinfo, - &data->cpuinfo, - sizeof(struct cpufreq_cpuinfo)); + memcpy(&policy->cpuinfo, &data->cpuinfo, sizeof(struct cpufreq_cpuinfo)); /* verify the cpu speed can be set within this limit */ ret = cpufreq_driver->verify(policy); @@ -1333,8 +1323,8 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli up_read(&cpufreq_notifier_rwsem); - data->min = policy->min; - data->max = policy->max; + data->min = policy->min; + data->max = policy->max; dprintk("new min and max freqs are %u - %u kHz\n", data->min, data->max); @@ -1371,7 +1361,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli __cpufreq_governor(data, CPUFREQ_GOV_LIMITS); } - error_out: +error_out: cpufreq_debug_enable_ratelimit(); return ret; } @@ -1430,9 +1420,7 @@ int cpufreq_update_policy(unsigned int cpu) mutex_lock(&data->lock); dprintk("updating policy for CPU %u\n", cpu); - memcpy(&policy, - data, - sizeof(struct cpufreq_policy)); + memcpy(&policy, data, sizeof(struct cpufreq_policy)); policy.min = data->user_policy.min; policy.max = data->user_policy.max; policy.policy = data->user_policy.policy; -- cgit v1.2.3 From 8cf3f04f45694db0699f608c0e3fb550c607cc88 Mon Sep 17 00:00:00 2001 From: Ralph Campbell Date: Fri, 3 Feb 2006 14:28:48 -0800 Subject: IB/mad: Handle DR SMPs with a LID routed part Fix handling of directed route SMPs with a beginning or ending LID routed part. Signed-off-by: Ralph Campbell Signed-off-by: Hal Rosenstock Signed-off-by: Roland Dreier --- drivers/infiniband/core/mad.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index d393b504bf26..c82f47a66e48 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -665,7 +665,15 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv, struct ib_wc mad_wc; struct ib_send_wr *send_wr = &mad_send_wr->send_wr; - if (!smi_handle_dr_smp_send(smp, device->node_type, port_num)) { + /* + * Directed route handling starts if the initial LID routed part of + * a request or the ending LID routed part of a response is empty. + * If we are at the start of the LID routed part, don't update the + * hop_ptr or hop_cnt. See section 14.2.2, Vol 1 IB spec. + */ + if ((ib_get_smp_direction(smp) ? smp->dr_dlid : smp->dr_slid) == + IB_LID_PERMISSIVE && + !smi_handle_dr_smp_send(smp, device->node_type, port_num)) { ret = -EINVAL; printk(KERN_ERR PFX "Invalid directed route\n"); goto out; -- cgit v1.2.3 From 04414013bbda644b65537e73f1dacb2821b36811 Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Tue, 31 Jan 2006 16:04:51 -0800 Subject: [SCSI] qla2xxx: Add port-speed FC transport attribute. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 22 ++++++++++++++++++++++ drivers/scsi/qla2xxx/qla_def.h | 4 ++++ drivers/scsi/qla2xxx/qla_isr.c | 4 ++-- drivers/scsi/qla2xxx/qla_os.c | 1 + 4 files changed, 29 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index b17ee62dd1a9..e03140fec179 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -425,6 +425,26 @@ qla2x00_get_host_port_id(struct Scsi_Host *shost) ha->d_id.b.area << 8 | ha->d_id.b.al_pa; } +static void +qla2x00_get_host_speed(struct Scsi_Host *shost) +{ + scsi_qla_host_t *ha = to_qla_host(shost); + uint32_t speed = 0; + + switch (ha->link_data_rate) { + case LDR_1GB: + speed = 1; + break; + case LDR_2GB: + speed = 2; + break; + case LDR_4GB: + speed = 4; + break; + } + fc_host_speed(shost) = speed; +} + static void qla2x00_get_starget_node_name(struct scsi_target *starget) { @@ -520,6 +540,8 @@ struct fc_function_template qla2xxx_transport_functions = { .get_host_port_id = qla2x00_get_host_port_id, .show_host_port_id = 1, + .get_host_speed = qla2x00_get_host_speed, + .show_host_speed = 1, .dd_fcrport_size = sizeof(struct fc_port *), .show_rport_supported_classes = 1, diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index bad066e5772a..26af5319c219 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2331,6 +2331,10 @@ typedef struct scsi_qla_host { uint16_t min_external_loopid; /* First external loop Id */ uint16_t link_data_rate; /* F/W operating speed */ +#define LDR_1GB 0 +#define LDR_2GB 1 +#define LDR_4GB 3 +#define LDR_UNKNOWN 0xFFFF uint8_t current_topology; uint8_t prev_topology; diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 71a46fcee8cc..42aa7a7c1a73 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -402,9 +402,9 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) break; case MBA_LOOP_UP: /* Loop Up Event */ - ha->link_data_rate = 0; if (IS_QLA2100(ha) || IS_QLA2200(ha)) { link_speed = link_speeds[0]; + ha->link_data_rate = LDR_1GB; } else { link_speed = link_speeds[LS_UNKNOWN]; if (mb[1] < 5) @@ -436,7 +436,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) } ha->flags.management_server_logged_in = 0; - ha->link_data_rate = 0; + ha->link_data_rate = LDR_UNKNOWN; if (ql2xfdmienable) set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 5866a7c706a8..6e133edb2016 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1312,6 +1312,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) ha->ports = MAX_BUSES; ha->init_cb_size = sizeof(init_cb_t); ha->mgmt_svr_loop_id = MANAGEMENT_SERVER; + ha->link_data_rate = LDR_UNKNOWN; /* Assign ISP specific operations. */ ha->isp_ops.pci_config = qla2100_pci_config; -- cgit v1.2.3 From 8d067623adf119081b7a2683cdc6ee90eb8a70b2 Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Tue, 31 Jan 2006 16:04:56 -0800 Subject: [SCSI] qla2xxx: Add host port-type FC transport attribute. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index e03140fec179..55016328bd78 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -445,6 +445,29 @@ qla2x00_get_host_speed(struct Scsi_Host *shost) fc_host_speed(shost) = speed; } +static void +qla2x00_get_host_port_type(struct Scsi_Host *shost) +{ + scsi_qla_host_t *ha = to_qla_host(shost); + uint32_t port_type = FC_PORTTYPE_UNKNOWN; + + switch (ha->current_topology) { + case ISP_CFG_NL: + port_type = FC_PORTTYPE_LPORT; + break; + case ISP_CFG_FL: + port_type = FC_PORTTYPE_NLPORT; + break; + case ISP_CFG_N: + port_type = FC_PORTTYPE_PTP; + break; + case ISP_CFG_F: + port_type = FC_PORTTYPE_NPORT; + break; + } + fc_host_port_type(shost) = port_type; +} + static void qla2x00_get_starget_node_name(struct scsi_target *starget) { @@ -542,6 +565,8 @@ struct fc_function_template qla2xxx_transport_functions = { .show_host_port_id = 1, .get_host_speed = qla2x00_get_host_speed, .show_host_speed = 1, + .get_host_port_type = qla2x00_get_host_port_type, + .show_host_port_type = 1, .dd_fcrport_size = sizeof(struct fc_port *), .show_rport_supported_classes = 1, -- cgit v1.2.3 From 392e2f651c8a83484116a407a9f121e534c22b5a Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Tue, 31 Jan 2006 16:05:02 -0800 Subject: [SCSI] qla2xxx: Add host-statistics FC transport attributes. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 37 +++++++++++++- drivers/scsi/qla2xxx/qla_def.h | 2 + drivers/scsi/qla2xxx/qla_gbl.h | 7 +++ drivers/scsi/qla2xxx/qla_init.c | 1 - drivers/scsi/qla2xxx/qla_mbx.c | 105 ++++++++++++++++++++++++++++++++++++++-- drivers/scsi/qla2xxx/qla_rscn.c | 2 - 6 files changed, 147 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 55016328bd78..5a8d5c4c69ba 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -7,7 +7,6 @@ #include "qla_def.h" #include -#include /* SYSFS attributes --------------------------------------------------------- */ @@ -555,6 +554,41 @@ qla2x00_issue_lip(struct Scsi_Host *shost) return 0; } +static struct fc_host_statistics * +qla2x00_get_fc_host_stats(struct Scsi_Host *shost) +{ + scsi_qla_host_t *ha = to_qla_host(shost); + int rval; + uint16_t mb_stat[1]; + link_stat_t stat_buf; + struct fc_host_statistics *pfc_host_stat; + + pfc_host_stat = &ha->fc_host_stat; + memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics)); + + if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + rval = qla24xx_get_isp_stats(ha, (uint32_t *)&stat_buf, + sizeof(stat_buf) / 4, mb_stat); + } else { + rval = qla2x00_get_link_status(ha, ha->loop_id, &stat_buf, + mb_stat); + } + if (rval != 0) { + qla_printk(KERN_WARNING, ha, + "Unable to retrieve host statistics (%d).\n", mb_stat[0]); + return pfc_host_stat; + } + + pfc_host_stat->link_failure_count = stat_buf.link_fail_cnt; + pfc_host_stat->loss_of_sync_count = stat_buf.loss_sync_cnt; + pfc_host_stat->loss_of_signal_count = stat_buf.loss_sig_cnt; + pfc_host_stat->prim_seq_protocol_err_count = stat_buf.prim_seq_err_cnt; + pfc_host_stat->invalid_tx_word_count = stat_buf.inval_xmit_word_cnt; + pfc_host_stat->invalid_crc_count = stat_buf.inval_crc_cnt; + + return pfc_host_stat; +} + struct fc_function_template qla2xxx_transport_functions = { .show_host_node_name = 1, @@ -583,6 +617,7 @@ struct fc_function_template qla2xxx_transport_functions = { .show_rport_dev_loss_tmo = 1, .issue_fc_host_lip = qla2x00_issue_lip, + .get_fc_host_stats = qla2x00_get_fc_host_stats, }; void diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 26af5319c219..414580800dc0 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -29,6 +29,7 @@ #include #include #include +#include #if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) #if defined(CONFIG_SCSI_QLA21XX) || defined(CONFIG_SCSI_QLA21XX_MODULE) @@ -2496,6 +2497,7 @@ typedef struct scsi_qla_host { uint16_t zio_mode; uint16_t zio_timer; + struct fc_host_statistics fc_host_stat; } scsi_qla_host_t; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 35266bd5d538..f2f5454a05e9 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -185,6 +185,13 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *, uint16_t *, uint16_t *, uint16_t *, extern int qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map); +extern int +qla2x00_get_link_status(scsi_qla_host_t *, uint16_t, link_stat_t *, + uint16_t *); + +extern int +qla24xx_get_isp_stats(scsi_qla_host_t *, uint32_t *, uint32_t, uint16_t *); + extern int qla24xx_abort_command(scsi_qla_host_t *, srb_t *); extern int qla24xx_abort_target(fc_port_t *); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index e67bb0997818..634ee174bff2 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -8,7 +8,6 @@ #include #include -#include #include "qla_devtbl.h" diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 3099b379de9d..49ce197876b4 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -7,7 +7,6 @@ #include "qla_def.h" #include -#include static void qla2x00_mbx_sem_timeout(unsigned long data) @@ -2017,8 +2016,109 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map) return rval; } +#endif + +/* + * qla2x00_get_link_status + * + * Input: + * ha = adapter block pointer. + * loop_id = device loop ID. + * ret_buf = pointer to link status return buffer. + * + * Returns: + * 0 = success. + * BIT_0 = mem alloc error. + * BIT_1 = mailbox error. + */ +int +qla2x00_get_link_status(scsi_qla_host_t *ha, uint16_t loop_id, + link_stat_t *ret_buf, uint16_t *status) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + link_stat_t *stat_buf; + dma_addr_t stat_buf_dma; + + DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);) + + stat_buf = dma_pool_alloc(ha->s_dma_pool, GFP_ATOMIC, &stat_buf_dma); + if (stat_buf == NULL) { + DEBUG2_3_11(printk("%s(%ld): Failed to allocate memory.\n", + __func__, ha->host_no)); + return BIT_0; + } + memset(stat_buf, 0, sizeof(link_stat_t)); + + mcp->mb[0] = MBC_GET_LINK_STATUS; + mcp->mb[2] = MSW(stat_buf_dma); + mcp->mb[3] = LSW(stat_buf_dma); + mcp->mb[6] = MSW(MSD(stat_buf_dma)); + mcp->mb[7] = LSW(MSD(stat_buf_dma)); + mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; + mcp->in_mb = MBX_0; + if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { + mcp->mb[1] = loop_id; + mcp->mb[4] = 0; + mcp->mb[10] = 0; + mcp->out_mb |= MBX_10|MBX_4|MBX_1; + mcp->in_mb |= MBX_1; + } else if (HAS_EXTENDED_IDS(ha)) { + mcp->mb[1] = loop_id; + mcp->mb[10] = 0; + mcp->out_mb |= MBX_10|MBX_1; + } else { + mcp->mb[1] = loop_id << 8; + mcp->out_mb |= MBX_1; + } + mcp->tov = 30; + mcp->flags = IOCTL_CMD; + rval = qla2x00_mailbox_command(ha, mcp); + + if (rval == QLA_SUCCESS) { + if (mcp->mb[0] != MBS_COMMAND_COMPLETE) { + DEBUG2_3_11(printk("%s(%ld): cmd failed. mbx0=%x.\n", + __func__, ha->host_no, mcp->mb[0]);) + status[0] = mcp->mb[0]; + rval = BIT_1; + } else { + /* copy over data -- firmware data is LE. */ + ret_buf->link_fail_cnt = + le32_to_cpu(stat_buf->link_fail_cnt); + ret_buf->loss_sync_cnt = + le32_to_cpu(stat_buf->loss_sync_cnt); + ret_buf->loss_sig_cnt = + le32_to_cpu(stat_buf->loss_sig_cnt); + ret_buf->prim_seq_err_cnt = + le32_to_cpu(stat_buf->prim_seq_err_cnt); + ret_buf->inval_xmit_word_cnt = + le32_to_cpu(stat_buf->inval_xmit_word_cnt); + ret_buf->inval_crc_cnt = + le32_to_cpu(stat_buf->inval_crc_cnt); + + DEBUG11(printk("%s(%ld): stat dump: fail_cnt=%d " + "loss_sync=%d loss_sig=%d seq_err=%d " + "inval_xmt_word=%d inval_crc=%d.\n", __func__, + ha->host_no, stat_buf->link_fail_cnt, + stat_buf->loss_sync_cnt, stat_buf->loss_sig_cnt, + stat_buf->prim_seq_err_cnt, + stat_buf->inval_xmit_word_cnt, + stat_buf->inval_crc_cnt);) + } + } else { + /* Failed. */ + DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__, + ha->host_no, rval);) + rval = BIT_1; + } + + dma_pool_free(ha->s_dma_pool, stat_buf, stat_buf_dma); -uint8_t + return rval; +} + +int qla24xx_get_isp_stats(scsi_qla_host_t *ha, uint32_t *dwbuf, uint32_t dwords, uint16_t *status) { @@ -2080,7 +2180,6 @@ qla24xx_get_isp_stats(scsi_qla_host_t *ha, uint32_t *dwbuf, uint32_t dwords, return rval; } -#endif int qla24xx_abort_command(scsi_qla_host_t *ha, srb_t *sp) diff --git a/drivers/scsi/qla2xxx/qla_rscn.c b/drivers/scsi/qla2xxx/qla_rscn.c index 2c3342108dd8..b70bebe18c01 100644 --- a/drivers/scsi/qla2xxx/qla_rscn.c +++ b/drivers/scsi/qla2xxx/qla_rscn.c @@ -6,8 +6,6 @@ */ #include "qla_def.h" -#include - /** * IO descriptor handle definitions. * -- cgit v1.2.3 From f6df144cca19cc60dda6dcce65d236b70cc46494 Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Tue, 31 Jan 2006 16:05:07 -0800 Subject: [SCSI] qla2xxx: Add beacon support via class-device attribute. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 50 +++++++ drivers/scsi/qla2xxx/qla_def.h | 21 ++- drivers/scsi/qla2xxx/qla_gbl.h | 9 +- drivers/scsi/qla2xxx/qla_os.c | 16 +++ drivers/scsi/qla2xxx/qla_sup.c | 294 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 387 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 5a8d5c4c69ba..049e5cf1af7f 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -196,6 +196,9 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha) sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_fw_dump_attr); sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr); + + if (ha->beacon_blink_led == 1) + ha->isp_ops.beacon_off(ha); } /* Scsi_Host attributes. */ @@ -383,6 +386,50 @@ qla2x00_zio_timer_store(struct class_device *cdev, const char *buf, return strlen(buf); } +static ssize_t +qla2x00_beacon_show(struct class_device *cdev, char *buf) +{ + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + int len = 0; + + if (ha->beacon_blink_led) + len += snprintf(buf + len, PAGE_SIZE-len, "Enabled\n"); + else + len += snprintf(buf + len, PAGE_SIZE-len, "Disabled\n"); + return len; +} + +static ssize_t +qla2x00_beacon_store(struct class_device *cdev, const char *buf, + size_t count) +{ + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + int val = 0; + int rval; + + if (IS_QLA2100(ha) || IS_QLA2200(ha)) + return -EPERM; + + if (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) { + qla_printk(KERN_WARNING, ha, + "Abort ISP active -- ignoring beacon request.\n"); + return -EBUSY; + } + + if (sscanf(buf, "%d", &val) != 1) + return -EINVAL; + + if (val) + rval = ha->isp_ops.beacon_on(ha); + else + rval = ha->isp_ops.beacon_off(ha); + + if (rval != QLA_SUCCESS) + count = 0; + + return count; +} + static CLASS_DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL); static CLASS_DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL); @@ -397,6 +444,8 @@ static CLASS_DEVICE_ATTR(zio, S_IRUGO | S_IWUSR, qla2x00_zio_show, qla2x00_zio_store); static CLASS_DEVICE_ATTR(zio_timer, S_IRUGO | S_IWUSR, qla2x00_zio_timer_show, qla2x00_zio_timer_store); +static CLASS_DEVICE_ATTR(beacon, S_IRUGO | S_IWUSR, qla2x00_beacon_show, + qla2x00_beacon_store); struct class_device_attribute *qla2x00_host_attrs[] = { &class_device_attr_driver_version, @@ -410,6 +459,7 @@ struct class_device_attribute *qla2x00_host_attrs[] = { &class_device_attr_state, &class_device_attr_zio, &class_device_attr_zio_timer, + &class_device_attr_beacon, NULL, }; diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 414580800dc0..7cb8b5a5e659 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -181,6 +181,13 @@ #define WRT_REG_WORD(addr, data) writew(data,addr) #define WRT_REG_DWORD(addr, data) writel(data,addr) +/* + * The ISP2312 v2 chip cannot access the FLASH/GPIO registers via MMIO in an + * 133Mhz slot. + */ +#define RD_REG_WORD_PIO(addr) (inw((unsigned long)addr)) +#define WRT_REG_WORD_PIO(addr, data) (outw(data,(unsigned long)addr)) + /* * Fibre Channel device definitions. */ @@ -433,6 +440,9 @@ struct device_reg_2xxx { #define GPIO_LED_GREEN_ON_AMBER_OFF 0x0040 #define GPIO_LED_GREEN_OFF_AMBER_ON 0x0080 #define GPIO_LED_GREEN_ON_AMBER_ON 0x00C0 +#define GPIO_LED_ALL_OFF 0x0000 +#define GPIO_LED_RED_ON_OTHER_OFF 0x0001 /* isp2322 */ +#define GPIO_LED_RGA_ON 0x00C1 /* isp2322: red green amber */ union { struct { @@ -2200,6 +2210,10 @@ struct isp_operations { void (*fw_dump) (struct scsi_qla_host *, int); void (*ascii_fw_dump) (struct scsi_qla_host *); + + int (*beacon_on) (struct scsi_qla_host *); + int (*beacon_off) (struct scsi_qla_host *); + void (*beacon_blink) (struct scsi_qla_host *); }; /* @@ -2493,7 +2507,12 @@ typedef struct scsi_qla_host { /* Needed for BEACON */ uint16_t beacon_blink_led; - uint16_t beacon_green_on; + uint8_t beacon_color_state; +#define QLA_LED_GRN_ON 0x01 +#define QLA_LED_YLW_ON 0x02 +#define QLA_LED_ABR_ON 0x04 +#define QLA_LED_ALL_ON 0x07 /* yellow, green, amber. */ + /* ISP2322: red, green, amber. */ uint16_t zio_mode; uint16_t zio_timer; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index f2f5454a05e9..eb35198bc8cf 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -75,8 +75,6 @@ extern void qla2x00_cmd_timeout(srb_t *); extern void qla2x00_mark_device_lost(scsi_qla_host_t *, fc_port_t *, int, int); extern void qla2x00_mark_all_devices_lost(scsi_qla_host_t *, int); -extern void qla2x00_blink_led(scsi_qla_host_t *); - extern int qla2x00_down_timeout(struct semaphore *, unsigned long); extern struct fw_blob *qla2x00_request_firmware(scsi_qla_host_t *); @@ -235,6 +233,13 @@ extern int qla2x00_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t, extern int qla24xx_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t, uint32_t); +extern int qla2x00_beacon_on(struct scsi_qla_host *); +extern int qla2x00_beacon_off(struct scsi_qla_host *); +extern void qla2x00_beacon_blink(struct scsi_qla_host *); +extern int qla24xx_beacon_on(struct scsi_qla_host *); +extern int qla24xx_beacon_off(struct scsi_qla_host *); +extern void qla24xx_beacon_blink(struct scsi_qla_host *); + /* * Global Function Prototypes in qla_dbg.c source file. */ diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 6e133edb2016..57179dabcccf 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1365,6 +1365,9 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) ha->isp_ops.intr_handler = qla2300_intr_handler; ha->isp_ops.fw_dump = qla2300_fw_dump; ha->isp_ops.ascii_fw_dump = qla2300_ascii_fw_dump; + ha->isp_ops.beacon_on = qla2x00_beacon_on; + ha->isp_ops.beacon_off = qla2x00_beacon_off; + ha->isp_ops.beacon_blink = qla2x00_beacon_blink; ha->gid_list_info_size = 6; } else if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { host->max_id = MAX_TARGETS_2200; @@ -1401,6 +1404,9 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) ha->isp_ops.write_nvram = qla24xx_write_nvram_data; ha->isp_ops.fw_dump = qla24xx_fw_dump; ha->isp_ops.ascii_fw_dump = qla24xx_ascii_fw_dump; + ha->isp_ops.beacon_on = qla24xx_beacon_on; + ha->isp_ops.beacon_off = qla24xx_beacon_off; + ha->isp_ops.beacon_blink = qla24xx_beacon_blink; ha->gid_list_info_size = 8; } host->can_queue = ha->request_q_length + 128; @@ -2315,6 +2321,9 @@ qla2x00_do_dpc(void *data) if (!ha->interrupts_on) ha->isp_ops.enable_intrs(ha); + if (test_and_clear_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags)) + ha->isp_ops.beacon_blink(ha); + ha->dpc_active = 0; } /* End of while(1) */ @@ -2492,6 +2501,12 @@ qla2x00_timer(scsi_qla_host_t *ha) atomic_read(&ha->loop_down_timer))); } + /* Check if beacon LED needs to be blinked */ + if (ha->beacon_blink_led == 1) { + set_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags); + start_dpc++; + } + /* Schedule the DPC routine if needed */ if ((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) || test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || @@ -2500,6 +2515,7 @@ qla2x00_timer(scsi_qla_host_t *ha) start_dpc || test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) || test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) || + test_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags) || test_bit(RELOGIN_NEEDED, &ha->dpc_flags)) && ha->dpc_wait && !ha->dpc_active) { diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index f4d755a643e4..3105bb93cc19 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -695,3 +695,297 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, return ret; } + + +static inline void +qla2x00_flip_colors(scsi_qla_host_t *ha, uint16_t *pflags) +{ + if (IS_QLA2322(ha)) { + /* Flip all colors. */ + if (ha->beacon_color_state == QLA_LED_ALL_ON) { + /* Turn off. */ + ha->beacon_color_state = 0; + *pflags = GPIO_LED_ALL_OFF; + } else { + /* Turn on. */ + ha->beacon_color_state = QLA_LED_ALL_ON; + *pflags = GPIO_LED_RGA_ON; + } + } else { + /* Flip green led only. */ + if (ha->beacon_color_state == QLA_LED_GRN_ON) { + /* Turn off. */ + ha->beacon_color_state = 0; + *pflags = GPIO_LED_GREEN_OFF_AMBER_OFF; + } else { + /* Turn on. */ + ha->beacon_color_state = QLA_LED_GRN_ON; + *pflags = GPIO_LED_GREEN_ON_AMBER_OFF; + } + } +} + +void +qla2x00_beacon_blink(struct scsi_qla_host *ha) +{ + uint16_t gpio_enable; + uint16_t gpio_data; + uint16_t led_color = 0; + unsigned long flags; + struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; + + if (ha->pio_address) + reg = (struct device_reg_2xxx __iomem *)ha->pio_address; + + spin_lock_irqsave(&ha->hardware_lock, flags); + + /* Save the Original GPIOE. */ + if (ha->pio_address) { + gpio_enable = RD_REG_WORD_PIO(®->gpioe); + gpio_data = RD_REG_WORD_PIO(®->gpiod); + } else { + gpio_enable = RD_REG_WORD(®->gpioe); + gpio_data = RD_REG_WORD(®->gpiod); + } + + /* Set the modified gpio_enable values */ + gpio_enable |= GPIO_LED_MASK; + + if (ha->pio_address) { + WRT_REG_WORD_PIO(®->gpioe, gpio_enable); + } else { + WRT_REG_WORD(®->gpioe, gpio_enable); + RD_REG_WORD(®->gpioe); + } + + qla2x00_flip_colors(ha, &led_color); + + /* Clear out any previously set LED color. */ + gpio_data &= ~GPIO_LED_MASK; + + /* Set the new input LED color to GPIOD. */ + gpio_data |= led_color; + + /* Set the modified gpio_data values */ + if (ha->pio_address) { + WRT_REG_WORD_PIO(®->gpiod, gpio_data); + } else { + WRT_REG_WORD(®->gpiod, gpio_data); + RD_REG_WORD(®->gpiod); + } + + spin_unlock_irqrestore(&ha->hardware_lock, flags); +} + +int +qla2x00_beacon_on(struct scsi_qla_host *ha) +{ + uint16_t gpio_enable; + uint16_t gpio_data; + unsigned long flags; + struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; + + ha->fw_options[1] &= ~FO1_SET_EMPHASIS_SWING; + ha->fw_options[1] |= FO1_DISABLE_GPIO6_7; + + if (qla2x00_set_fw_options(ha, ha->fw_options) != QLA_SUCCESS) { + qla_printk(KERN_WARNING, ha, + "Unable to update fw options (beacon on).\n"); + return QLA_FUNCTION_FAILED; + } + + if (ha->pio_address) + reg = (struct device_reg_2xxx __iomem *)ha->pio_address; + + /* Turn off LEDs. */ + spin_lock_irqsave(&ha->hardware_lock, flags); + if (ha->pio_address) { + gpio_enable = RD_REG_WORD_PIO(®->gpioe); + gpio_data = RD_REG_WORD_PIO(®->gpiod); + } else { + gpio_enable = RD_REG_WORD(®->gpioe); + gpio_data = RD_REG_WORD(®->gpiod); + } + gpio_enable |= GPIO_LED_MASK; + + /* Set the modified gpio_enable values. */ + if (ha->pio_address) { + WRT_REG_WORD_PIO(®->gpioe, gpio_enable); + } else { + WRT_REG_WORD(®->gpioe, gpio_enable); + RD_REG_WORD(®->gpioe); + } + + /* Clear out previously set LED colour. */ + gpio_data &= ~GPIO_LED_MASK; + if (ha->pio_address) { + WRT_REG_WORD_PIO(®->gpiod, gpio_data); + } else { + WRT_REG_WORD(®->gpiod, gpio_data); + RD_REG_WORD(®->gpiod); + } + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + /* + * Let the per HBA timer kick off the blinking process based on + * the following flags. No need to do anything else now. + */ + ha->beacon_blink_led = 1; + ha->beacon_color_state = 0; + + return QLA_SUCCESS; +} + +int +qla2x00_beacon_off(struct scsi_qla_host *ha) +{ + int rval = QLA_SUCCESS; + + ha->beacon_blink_led = 0; + + /* Set the on flag so when it gets flipped it will be off. */ + if (IS_QLA2322(ha)) + ha->beacon_color_state = QLA_LED_ALL_ON; + else + ha->beacon_color_state = QLA_LED_GRN_ON; + + ha->isp_ops.beacon_blink(ha); /* This turns green LED off */ + + ha->fw_options[1] &= ~FO1_SET_EMPHASIS_SWING; + ha->fw_options[1] &= ~FO1_DISABLE_GPIO6_7; + + rval = qla2x00_set_fw_options(ha, ha->fw_options); + if (rval != QLA_SUCCESS) + qla_printk(KERN_WARNING, ha, + "Unable to update fw options (beacon off).\n"); + return rval; +} + + +static inline void +qla24xx_flip_colors(scsi_qla_host_t *ha, uint16_t *pflags) +{ + /* Flip all colors. */ + if (ha->beacon_color_state == QLA_LED_ALL_ON) { + /* Turn off. */ + ha->beacon_color_state = 0; + *pflags = 0; + } else { + /* Turn on. */ + ha->beacon_color_state = QLA_LED_ALL_ON; + *pflags = GPDX_LED_YELLOW_ON | GPDX_LED_AMBER_ON; + } +} + +void +qla24xx_beacon_blink(struct scsi_qla_host *ha) +{ + uint16_t led_color = 0; + uint32_t gpio_data; + unsigned long flags; + struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + + /* Save the Original GPIOD. */ + spin_lock_irqsave(&ha->hardware_lock, flags); + gpio_data = RD_REG_DWORD(®->gpiod); + + /* Enable the gpio_data reg for update. */ + gpio_data |= GPDX_LED_UPDATE_MASK; + + WRT_REG_DWORD(®->gpiod, gpio_data); + gpio_data = RD_REG_DWORD(®->gpiod); + + /* Set the color bits. */ + qla24xx_flip_colors(ha, &led_color); + + /* Clear out any previously set LED color. */ + gpio_data &= ~GPDX_LED_COLOR_MASK; + + /* Set the new input LED color to GPIOD. */ + gpio_data |= led_color; + + /* Set the modified gpio_data values. */ + WRT_REG_DWORD(®->gpiod, gpio_data); + gpio_data = RD_REG_DWORD(®->gpiod); + spin_unlock_irqrestore(&ha->hardware_lock, flags); +} + +int +qla24xx_beacon_on(struct scsi_qla_host *ha) +{ + uint32_t gpio_data; + unsigned long flags; + struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + + if (ha->beacon_blink_led == 0) { + /* Enable firmware for update */ + ha->fw_options[1] |= ADD_FO1_DISABLE_GPIO_LED_CTRL; + + if (qla2x00_set_fw_options(ha, ha->fw_options) != QLA_SUCCESS) + return QLA_FUNCTION_FAILED; + + if (qla2x00_get_fw_options(ha, ha->fw_options) != + QLA_SUCCESS) { + qla_printk(KERN_WARNING, ha, + "Unable to update fw options (beacon on).\n"); + return QLA_FUNCTION_FAILED; + } + + spin_lock_irqsave(&ha->hardware_lock, flags); + gpio_data = RD_REG_DWORD(®->gpiod); + + /* Enable the gpio_data reg for update. */ + gpio_data |= GPDX_LED_UPDATE_MASK; + WRT_REG_DWORD(®->gpiod, gpio_data); + RD_REG_DWORD(®->gpiod); + + spin_unlock_irqrestore(&ha->hardware_lock, flags); + } + + /* So all colors blink together. */ + ha->beacon_color_state = 0; + + /* Let the per HBA timer kick off the blinking process. */ + ha->beacon_blink_led = 1; + + return QLA_SUCCESS; +} + +int +qla24xx_beacon_off(struct scsi_qla_host *ha) +{ + uint32_t gpio_data; + unsigned long flags; + struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + + ha->beacon_blink_led = 0; + ha->beacon_color_state = QLA_LED_ALL_ON; + + ha->isp_ops.beacon_blink(ha); /* Will flip to all off. */ + + /* Give control back to firmware. */ + spin_lock_irqsave(&ha->hardware_lock, flags); + gpio_data = RD_REG_DWORD(®->gpiod); + + /* Disable the gpio_data reg for update. */ + gpio_data &= ~GPDX_LED_UPDATE_MASK; + WRT_REG_DWORD(®->gpiod, gpio_data); + RD_REG_DWORD(®->gpiod); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + ha->fw_options[1] &= ~ADD_FO1_DISABLE_GPIO_LED_CTRL; + + if (qla2x00_set_fw_options(ha, ha->fw_options) != QLA_SUCCESS) { + qla_printk(KERN_WARNING, ha, + "Unable to update fw options (beacon off).\n"); + return QLA_FUNCTION_FAILED; + } + + if (qla2x00_get_fw_options(ha, ha->fw_options) != QLA_SUCCESS) { + qla_printk(KERN_WARNING, ha, + "Unable to get fw options (beacon off).\n"); + return QLA_FUNCTION_FAILED; + } + + return QLA_SUCCESS; +} -- cgit v1.2.3 From 1b3f63659bd353ae460c35f5793a9fd46cc95014 Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Tue, 31 Jan 2006 16:05:12 -0800 Subject: [SCSI] qla2xxx: Return correct data-len during NVRAM retrieval. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 049e5cf1af7f..73d10b35091e 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -113,7 +113,7 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off, struct device, kobj))); unsigned long flags; - if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size) + if (!capable(CAP_SYS_ADMIN) || off != 0) return 0; /* Read NVRAM. */ @@ -122,7 +122,7 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off, ha->nvram_size); spin_unlock_irqrestore(&ha->hardware_lock, flags); - return (count); + return ha->nvram_size; } static ssize_t @@ -174,7 +174,7 @@ static struct bin_attribute sysfs_nvram_attr = { .mode = S_IRUSR | S_IWUSR, .owner = THIS_MODULE, }, - .size = 0, + .size = 512, .read = qla2x00_sysfs_read_nvram, .write = qla2x00_sysfs_write_nvram, }; @@ -185,7 +185,6 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha) struct Scsi_Host *host = ha->host; sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_fw_dump_attr); - sysfs_nvram_attr.size = ha->nvram_size; sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr); } -- cgit v1.2.3 From 854165f4245c4a3b4a8cc363ba2050033151e196 Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Tue, 31 Jan 2006 16:05:17 -0800 Subject: [SCSI] qla2xxx: Add support to retrieve/update HBA option-rom. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 135 ++++++++ drivers/scsi/qla2xxx/qla_def.h | 17 +- drivers/scsi/qla2xxx/qla_gbl.h | 11 + drivers/scsi/qla2xxx/qla_os.c | 15 +- drivers/scsi/qla2xxx/qla_sup.c | 669 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 845 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 73d10b35091e..92b3e13e9061 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -179,6 +179,135 @@ static struct bin_attribute sysfs_nvram_attr = { .write = qla2x00_sysfs_write_nvram, }; +static ssize_t +qla2x00_sysfs_read_optrom(struct kobject *kobj, char *buf, loff_t off, + size_t count) +{ + struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, + struct device, kobj))); + + if (ha->optrom_state != QLA_SREADING) + return 0; + if (off > ha->optrom_size) + return 0; + if (off + count > ha->optrom_size) + count = ha->optrom_size - off; + + memcpy(buf, &ha->optrom_buffer[off], count); + + return count; +} + +static ssize_t +qla2x00_sysfs_write_optrom(struct kobject *kobj, char *buf, loff_t off, + size_t count) +{ + struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, + struct device, kobj))); + + if (ha->optrom_state != QLA_SWRITING) + return -EINVAL; + if (off > ha->optrom_size) + return -ERANGE; + if (off + count > ha->optrom_size) + count = ha->optrom_size - off; + + memcpy(&ha->optrom_buffer[off], buf, count); + + return count; +} + +static struct bin_attribute sysfs_optrom_attr = { + .attr = { + .name = "optrom", + .mode = S_IRUSR | S_IWUSR, + .owner = THIS_MODULE, + }, + .size = OPTROM_SIZE_24XX, + .read = qla2x00_sysfs_read_optrom, + .write = qla2x00_sysfs_write_optrom, +}; + +static ssize_t +qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, char *buf, loff_t off, + size_t count) +{ + struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, + struct device, kobj))); + int val; + + if (off) + return 0; + + if (sscanf(buf, "%d", &val) != 1) + return -EINVAL; + + switch (val) { + case 0: + if (ha->optrom_state != QLA_SREADING && + ha->optrom_state != QLA_SWRITING) + break; + + ha->optrom_state = QLA_SWAITING; + vfree(ha->optrom_buffer); + ha->optrom_buffer = NULL; + break; + case 1: + if (ha->optrom_state != QLA_SWAITING) + break; + + ha->optrom_state = QLA_SREADING; + ha->optrom_buffer = (uint8_t *)vmalloc(ha->optrom_size); + if (ha->optrom_buffer == NULL) { + qla_printk(KERN_WARNING, ha, + "Unable to allocate memory for optrom retrieval " + "(%x).\n", ha->optrom_size); + + ha->optrom_state = QLA_SWAITING; + return count; + } + + memset(ha->optrom_buffer, 0, ha->optrom_size); + ha->isp_ops.read_optrom(ha, ha->optrom_buffer, 0, + ha->optrom_size); + break; + case 2: + if (ha->optrom_state != QLA_SWAITING) + break; + + ha->optrom_state = QLA_SWRITING; + ha->optrom_buffer = (uint8_t *)vmalloc(ha->optrom_size); + if (ha->optrom_buffer == NULL) { + qla_printk(KERN_WARNING, ha, + "Unable to allocate memory for optrom update " + "(%x).\n", ha->optrom_size); + + ha->optrom_state = QLA_SWAITING; + return count; + } + memset(ha->optrom_buffer, 0, ha->optrom_size); + break; + case 3: + if (ha->optrom_state != QLA_SWRITING) + break; + + ha->isp_ops.write_optrom(ha, ha->optrom_buffer, 0, + ha->optrom_size); + break; + } + return count; +} + +static struct bin_attribute sysfs_optrom_ctl_attr = { + .attr = { + .name = "optrom_ctl", + .mode = S_IWUSR, + .owner = THIS_MODULE, + }, + .size = 0, + .write = qla2x00_sysfs_write_optrom_ctl, +}; + void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha) { @@ -186,6 +315,9 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha) sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_fw_dump_attr); sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr); + sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr); + sysfs_create_bin_file(&host->shost_gendev.kobj, + &sysfs_optrom_ctl_attr); } void @@ -195,6 +327,9 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha) sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_fw_dump_attr); sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr); + sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr); + sysfs_remove_bin_file(&host->shost_gendev.kobj, + &sysfs_optrom_ctl_attr); if (ha->beacon_blink_led == 1) ha->isp_ops.beacon_off(ha); diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 7cb8b5a5e659..b31a03bbd14f 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2214,6 +2214,11 @@ struct isp_operations { int (*beacon_on) (struct scsi_qla_host *); int (*beacon_off) (struct scsi_qla_host *); void (*beacon_blink) (struct scsi_qla_host *); + + uint8_t * (*read_optrom) (struct scsi_qla_host *, uint8_t *, + uint32_t, uint32_t); + int (*write_optrom) (struct scsi_qla_host *, uint8_t *, uint32_t, + uint32_t); }; /* @@ -2505,6 +2510,14 @@ typedef struct scsi_qla_host { uint8_t *port_name; uint32_t isp_abort_cnt; + /* Option ROM information. */ + char *optrom_buffer; + uint32_t optrom_size; + int optrom_state; +#define QLA_SWAITING 0 +#define QLA_SREADING 1 +#define QLA_SWRITING 2 + /* Needed for BEACON */ uint16_t beacon_blink_led; uint8_t beacon_color_state; @@ -2582,7 +2595,9 @@ struct _qla2x00stats { /* * Flash support definitions */ -#define FLASH_IMAGE_SIZE 131072 +#define OPTROM_SIZE_2300 0x20000 +#define OPTROM_SIZE_2322 0x100000 +#define OPTROM_SIZE_24XX 0x100000 #include "qla_gbl.h" #include "qla_dbg.h" diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index eb35198bc8cf..ffdc2680f049 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -79,6 +79,8 @@ extern int qla2x00_down_timeout(struct semaphore *, unsigned long); extern struct fw_blob *qla2x00_request_firmware(scsi_qla_host_t *); +extern int qla2x00_wait_for_hba_online(scsi_qla_host_t *); + /* * Global Function Prototypes in qla_iocb.c source file. */ @@ -240,6 +242,15 @@ extern int qla24xx_beacon_on(struct scsi_qla_host *); extern int qla24xx_beacon_off(struct scsi_qla_host *); extern void qla24xx_beacon_blink(struct scsi_qla_host *); +extern uint8_t *qla2x00_read_optrom_data(struct scsi_qla_host *, uint8_t *, + uint32_t, uint32_t); +extern int qla2x00_write_optrom_data(struct scsi_qla_host *, uint8_t *, + uint32_t, uint32_t); +extern uint8_t *qla24xx_read_optrom_data(struct scsi_qla_host *, uint8_t *, + uint32_t, uint32_t); +extern int qla24xx_write_optrom_data(struct scsi_qla_host *, uint8_t *, + uint32_t, uint32_t); + /* * Global Function Prototypes in qla_dbg.c source file. */ diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 57179dabcccf..495ccbc7f8cb 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -513,7 +513,7 @@ qla2x00_eh_wait_on_command(scsi_qla_host_t *ha, struct scsi_cmnd *cmd) * Success (Adapter is online) : 0 * Failed (Adapter is offline/disabled) : 1 */ -static int +int qla2x00_wait_for_hba_online(scsi_qla_host_t *ha) { int return_status; @@ -1271,6 +1271,9 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) fc_port_t *fcport; struct scsi_host_template *sht; +if (PCI_FUNC(pdev->devfn)) + goto probe_out; + if (pci_enable_device(pdev)) goto probe_out; @@ -1313,6 +1316,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) ha->init_cb_size = sizeof(init_cb_t); ha->mgmt_svr_loop_id = MANAGEMENT_SERVER; ha->link_data_rate = LDR_UNKNOWN; + ha->optrom_size = OPTROM_SIZE_2300; /* Assign ISP specific operations. */ ha->isp_ops.pci_config = qla2100_pci_config; @@ -1340,6 +1344,8 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) ha->isp_ops.write_nvram = qla2x00_write_nvram_data; ha->isp_ops.fw_dump = qla2100_fw_dump; ha->isp_ops.ascii_fw_dump = qla2100_ascii_fw_dump; + ha->isp_ops.read_optrom = qla2x00_read_optrom_data; + ha->isp_ops.write_optrom = qla2x00_write_optrom_data; if (IS_QLA2100(ha)) { host->max_id = MAX_TARGETS_2100; ha->mbx_count = MAILBOX_REGISTER_COUNT_2100; @@ -1369,6 +1375,8 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) ha->isp_ops.beacon_off = qla2x00_beacon_off; ha->isp_ops.beacon_blink = qla2x00_beacon_blink; ha->gid_list_info_size = 6; + if (IS_QLA2322(ha) || IS_QLA6322(ha)) + ha->optrom_size = OPTROM_SIZE_2322; } else if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { host->max_id = MAX_TARGETS_2200; ha->mbx_count = MAILBOX_REGISTER_COUNT; @@ -1404,10 +1412,13 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) ha->isp_ops.write_nvram = qla24xx_write_nvram_data; ha->isp_ops.fw_dump = qla24xx_fw_dump; ha->isp_ops.ascii_fw_dump = qla24xx_ascii_fw_dump; + ha->isp_ops.read_optrom = qla24xx_read_optrom_data; + ha->isp_ops.write_optrom = qla24xx_write_optrom_data; ha->isp_ops.beacon_on = qla24xx_beacon_on; ha->isp_ops.beacon_off = qla24xx_beacon_off; ha->isp_ops.beacon_blink = qla24xx_beacon_blink; ha->gid_list_info_size = 8; + ha->optrom_size = OPTROM_SIZE_24XX; } host->can_queue = ha->request_q_length + 128; @@ -2073,6 +2084,8 @@ qla2x00_mem_free(scsi_qla_host_t *ha) ha->fw_dumped = 0; ha->fw_dump_reading = 0; ha->fw_dump_buffer = NULL; + + vfree(ha->optrom_buffer); } /* diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 3105bb93cc19..3866a5760f15 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -989,3 +989,672 @@ qla24xx_beacon_off(struct scsi_qla_host *ha) return QLA_SUCCESS; } + + +/* + * Flash support routines + */ + +/** + * qla2x00_flash_enable() - Setup flash for reading and writing. + * @ha: HA context + */ +static void +qla2x00_flash_enable(scsi_qla_host_t *ha) +{ + uint16_t data; + struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; + + data = RD_REG_WORD(®->ctrl_status); + data |= CSR_FLASH_ENABLE; + WRT_REG_WORD(®->ctrl_status, data); + RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ +} + +/** + * qla2x00_flash_disable() - Disable flash and allow RISC to run. + * @ha: HA context + */ +static void +qla2x00_flash_disable(scsi_qla_host_t *ha) +{ + uint16_t data; + struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; + + data = RD_REG_WORD(®->ctrl_status); + data &= ~(CSR_FLASH_ENABLE); + WRT_REG_WORD(®->ctrl_status, data); + RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ +} + +/** + * qla2x00_read_flash_byte() - Reads a byte from flash + * @ha: HA context + * @addr: Address in flash to read + * + * A word is read from the chip, but, only the lower byte is valid. + * + * Returns the byte read from flash @addr. + */ +static uint8_t +qla2x00_read_flash_byte(scsi_qla_host_t *ha, uint32_t addr) +{ + uint16_t data; + uint16_t bank_select; + struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; + + bank_select = RD_REG_WORD(®->ctrl_status); + + if (IS_QLA2322(ha) || IS_QLA6322(ha)) { + /* Specify 64K address range: */ + /* clear out Module Select and Flash Address bits [19:16]. */ + bank_select &= ~0xf8; + bank_select |= addr >> 12 & 0xf0; + bank_select |= CSR_FLASH_64K_BANK; + WRT_REG_WORD(®->ctrl_status, bank_select); + RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ + + WRT_REG_WORD(®->flash_address, (uint16_t)addr); + data = RD_REG_WORD(®->flash_data); + + return (uint8_t)data; + } + + /* Setup bit 16 of flash address. */ + if ((addr & BIT_16) && ((bank_select & CSR_FLASH_64K_BANK) == 0)) { + bank_select |= CSR_FLASH_64K_BANK; + WRT_REG_WORD(®->ctrl_status, bank_select); + RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ + } else if (((addr & BIT_16) == 0) && + (bank_select & CSR_FLASH_64K_BANK)) { + bank_select &= ~(CSR_FLASH_64K_BANK); + WRT_REG_WORD(®->ctrl_status, bank_select); + RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ + } + + /* Always perform IO mapped accesses to the FLASH registers. */ + if (ha->pio_address) { + uint16_t data2; + + reg = (struct device_reg_2xxx __iomem *)ha->pio_address; + WRT_REG_WORD_PIO(®->flash_address, (uint16_t)addr); + do { + data = RD_REG_WORD_PIO(®->flash_data); + barrier(); + cpu_relax(); + data2 = RD_REG_WORD_PIO(®->flash_data); + } while (data != data2); + } else { + WRT_REG_WORD(®->flash_address, (uint16_t)addr); + data = qla2x00_debounce_register(®->flash_data); + } + + return (uint8_t)data; +} + +/** + * qla2x00_write_flash_byte() - Write a byte to flash + * @ha: HA context + * @addr: Address in flash to write + * @data: Data to write + */ +static void +qla2x00_write_flash_byte(scsi_qla_host_t *ha, uint32_t addr, uint8_t data) +{ + uint16_t bank_select; + struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; + + bank_select = RD_REG_WORD(®->ctrl_status); + if (IS_QLA2322(ha) || IS_QLA6322(ha)) { + /* Specify 64K address range: */ + /* clear out Module Select and Flash Address bits [19:16]. */ + bank_select &= ~0xf8; + bank_select |= addr >> 12 & 0xf0; + bank_select |= CSR_FLASH_64K_BANK; + WRT_REG_WORD(®->ctrl_status, bank_select); + RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ + + WRT_REG_WORD(®->flash_address, (uint16_t)addr); + RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ + WRT_REG_WORD(®->flash_data, (uint16_t)data); + RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ + + return; + } + + /* Setup bit 16 of flash address. */ + if ((addr & BIT_16) && ((bank_select & CSR_FLASH_64K_BANK) == 0)) { + bank_select |= CSR_FLASH_64K_BANK; + WRT_REG_WORD(®->ctrl_status, bank_select); + RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ + } else if (((addr & BIT_16) == 0) && + (bank_select & CSR_FLASH_64K_BANK)) { + bank_select &= ~(CSR_FLASH_64K_BANK); + WRT_REG_WORD(®->ctrl_status, bank_select); + RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ + } + + /* Always perform IO mapped accesses to the FLASH registers. */ + if (ha->pio_address) { + reg = (struct device_reg_2xxx __iomem *)ha->pio_address; + WRT_REG_WORD_PIO(®->flash_address, (uint16_t)addr); + WRT_REG_WORD_PIO(®->flash_data, (uint16_t)data); + } else { + WRT_REG_WORD(®->flash_address, (uint16_t)addr); + RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ + WRT_REG_WORD(®->flash_data, (uint16_t)data); + RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ + } +} + +/** + * qla2x00_poll_flash() - Polls flash for completion. + * @ha: HA context + * @addr: Address in flash to poll + * @poll_data: Data to be polled + * @man_id: Flash manufacturer ID + * @flash_id: Flash ID + * + * This function polls the device until bit 7 of what is read matches data + * bit 7 or until data bit 5 becomes a 1. If that hapens, the flash ROM timed + * out (a fatal error). The flash book recommeds reading bit 7 again after + * reading bit 5 as a 1. + * + * Returns 0 on success, else non-zero. + */ +static int +qla2x00_poll_flash(scsi_qla_host_t *ha, uint32_t addr, uint8_t poll_data, + uint8_t man_id, uint8_t flash_id) +{ + int status; + uint8_t flash_data; + uint32_t cnt; + + status = 1; + + /* Wait for 30 seconds for command to finish. */ + poll_data &= BIT_7; + for (cnt = 3000000; cnt; cnt--) { + flash_data = qla2x00_read_flash_byte(ha, addr); + if ((flash_data & BIT_7) == poll_data) { + status = 0; + break; + } + + if (man_id != 0x40 && man_id != 0xda) { + if ((flash_data & BIT_5) && cnt > 2) + cnt = 2; + } + udelay(10); + barrier(); + } + return status; +} + +#define IS_OEM_001(ha) \ + ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2322 && \ + (ha)->pdev->subsystem_vendor == 0x1028 && \ + (ha)->pdev->subsystem_device == 0x0170) + +/** + * qla2x00_program_flash_address() - Programs a flash address + * @ha: HA context + * @addr: Address in flash to program + * @data: Data to be written in flash + * @man_id: Flash manufacturer ID + * @flash_id: Flash ID + * + * Returns 0 on success, else non-zero. + */ +static int +qla2x00_program_flash_address(scsi_qla_host_t *ha, uint32_t addr, uint8_t data, + uint8_t man_id, uint8_t flash_id) +{ + /* Write Program Command Sequence. */ + if (IS_OEM_001(ha)) { + qla2x00_write_flash_byte(ha, 0xaaa, 0xaa); + qla2x00_write_flash_byte(ha, 0x555, 0x55); + qla2x00_write_flash_byte(ha, 0xaaa, 0xa0); + qla2x00_write_flash_byte(ha, addr, data); + } else { + if (man_id == 0xda && flash_id == 0xc1) { + qla2x00_write_flash_byte(ha, addr, data); + if (addr & 0x7e) + return 0; + } else { + qla2x00_write_flash_byte(ha, 0x5555, 0xaa); + qla2x00_write_flash_byte(ha, 0x2aaa, 0x55); + qla2x00_write_flash_byte(ha, 0x5555, 0xa0); + qla2x00_write_flash_byte(ha, addr, data); + } + } + + udelay(150); + + /* Wait for write to complete. */ + return qla2x00_poll_flash(ha, addr, data, man_id, flash_id); +} + +/** + * qla2x00_erase_flash() - Erase the flash. + * @ha: HA context + * @man_id: Flash manufacturer ID + * @flash_id: Flash ID + * + * Returns 0 on success, else non-zero. + */ +static int +qla2x00_erase_flash(scsi_qla_host_t *ha, uint8_t man_id, uint8_t flash_id) +{ + /* Individual Sector Erase Command Sequence */ + if (IS_OEM_001(ha)) { + qla2x00_write_flash_byte(ha, 0xaaa, 0xaa); + qla2x00_write_flash_byte(ha, 0x555, 0x55); + qla2x00_write_flash_byte(ha, 0xaaa, 0x80); + qla2x00_write_flash_byte(ha, 0xaaa, 0xaa); + qla2x00_write_flash_byte(ha, 0x555, 0x55); + qla2x00_write_flash_byte(ha, 0xaaa, 0x10); + } else { + qla2x00_write_flash_byte(ha, 0x5555, 0xaa); + qla2x00_write_flash_byte(ha, 0x2aaa, 0x55); + qla2x00_write_flash_byte(ha, 0x5555, 0x80); + qla2x00_write_flash_byte(ha, 0x5555, 0xaa); + qla2x00_write_flash_byte(ha, 0x2aaa, 0x55); + qla2x00_write_flash_byte(ha, 0x5555, 0x10); + } + + udelay(150); + + /* Wait for erase to complete. */ + return qla2x00_poll_flash(ha, 0x00, 0x80, man_id, flash_id); +} + +/** + * qla2x00_erase_flash_sector() - Erase a flash sector. + * @ha: HA context + * @addr: Flash sector to erase + * @sec_mask: Sector address mask + * @man_id: Flash manufacturer ID + * @flash_id: Flash ID + * + * Returns 0 on success, else non-zero. + */ +static int +qla2x00_erase_flash_sector(scsi_qla_host_t *ha, uint32_t addr, + uint32_t sec_mask, uint8_t man_id, uint8_t flash_id) +{ + /* Individual Sector Erase Command Sequence */ + qla2x00_write_flash_byte(ha, 0x5555, 0xaa); + qla2x00_write_flash_byte(ha, 0x2aaa, 0x55); + qla2x00_write_flash_byte(ha, 0x5555, 0x80); + qla2x00_write_flash_byte(ha, 0x5555, 0xaa); + qla2x00_write_flash_byte(ha, 0x2aaa, 0x55); + if (man_id == 0x1f && flash_id == 0x13) + qla2x00_write_flash_byte(ha, addr & sec_mask, 0x10); + else + qla2x00_write_flash_byte(ha, addr & sec_mask, 0x30); + + udelay(150); + + /* Wait for erase to complete. */ + return qla2x00_poll_flash(ha, addr, 0x80, man_id, flash_id); +} + +/** + * qla2x00_get_flash_manufacturer() - Read manufacturer ID from flash chip. + * @man_id: Flash manufacturer ID + * @flash_id: Flash ID + */ +static void +qla2x00_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id, + uint8_t *flash_id) +{ + qla2x00_write_flash_byte(ha, 0x5555, 0xaa); + qla2x00_write_flash_byte(ha, 0x2aaa, 0x55); + qla2x00_write_flash_byte(ha, 0x5555, 0x90); + *man_id = qla2x00_read_flash_byte(ha, 0x0000); + *flash_id = qla2x00_read_flash_byte(ha, 0x0001); + qla2x00_write_flash_byte(ha, 0x5555, 0xaa); + qla2x00_write_flash_byte(ha, 0x2aaa, 0x55); + qla2x00_write_flash_byte(ha, 0x5555, 0xf0); +} + + +static inline void +qla2x00_suspend_hba(struct scsi_qla_host *ha) +{ + int cnt; + unsigned long flags; + struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; + + /* Suspend HBA. */ + scsi_block_requests(ha->host); + ha->isp_ops.disable_intrs(ha); + set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); + + /* Pause RISC. */ + spin_lock_irqsave(&ha->hardware_lock, flags); + WRT_REG_WORD(®->hccr, HCCR_PAUSE_RISC); + RD_REG_WORD(®->hccr); + if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) { + for (cnt = 0; cnt < 30000; cnt++) { + if ((RD_REG_WORD(®->hccr) & HCCR_RISC_PAUSE) != 0) + break; + udelay(100); + } + } else { + udelay(10); + } + spin_unlock_irqrestore(&ha->hardware_lock, flags); +} + +static inline void +qla2x00_resume_hba(struct scsi_qla_host *ha) +{ + /* Resume HBA. */ + clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + up(ha->dpc_wait); + qla2x00_wait_for_hba_online(ha); + scsi_unblock_requests(ha->host); +} + +uint8_t * +qla2x00_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, + uint32_t offset, uint32_t length) +{ + unsigned long flags; + uint32_t addr, midpoint; + uint8_t *data; + struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; + + /* Suspend HBA. */ + qla2x00_suspend_hba(ha); + + /* Go with read. */ + spin_lock_irqsave(&ha->hardware_lock, flags); + midpoint = ha->optrom_size / 2; + + qla2x00_flash_enable(ha); + WRT_REG_WORD(®->nvram, 0); + RD_REG_WORD(®->nvram); /* PCI Posting. */ + for (addr = offset, data = buf; addr < length; addr++, data++) { + if (addr == midpoint) { + WRT_REG_WORD(®->nvram, NVR_SELECT); + RD_REG_WORD(®->nvram); /* PCI Posting. */ + } + + *data = qla2x00_read_flash_byte(ha, addr); + } + qla2x00_flash_disable(ha); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + /* Resume HBA. */ + qla2x00_resume_hba(ha); + + return buf; +} + +int +qla2x00_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, + uint32_t offset, uint32_t length) +{ + + int rval; + unsigned long flags; + uint8_t man_id, flash_id, sec_number, data; + uint16_t wd; + uint32_t addr, liter, sec_mask, rest_addr; + struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; + + /* Suspend HBA. */ + qla2x00_suspend_hba(ha); + + rval = QLA_SUCCESS; + sec_number = 0; + + /* Reset ISP chip. */ + spin_lock_irqsave(&ha->hardware_lock, flags); + WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET); + pci_read_config_word(ha->pdev, PCI_COMMAND, &wd); + + /* Go with write. */ + qla2x00_flash_enable(ha); + do { /* Loop once to provide quick error exit */ + /* Structure of flash memory based on manufacturer */ + if (IS_OEM_001(ha)) { + /* OEM variant with special flash part. */ + man_id = flash_id = 0; + rest_addr = 0xffff; + sec_mask = 0x10000; + goto update_flash; + } + qla2x00_get_flash_manufacturer(ha, &man_id, &flash_id); + switch (man_id) { + case 0x20: /* ST flash. */ + if (flash_id == 0xd2 || flash_id == 0xe3) { + /* + * ST m29w008at part - 64kb sector size with + * 32kb,8kb,8kb,16kb sectors at memory address + * 0xf0000. + */ + rest_addr = 0xffff; + sec_mask = 0x10000; + break; + } + /* + * ST m29w010b part - 16kb sector size + * Default to 16kb sectors + */ + rest_addr = 0x3fff; + sec_mask = 0x1c000; + break; + case 0x40: /* Mostel flash. */ + /* Mostel v29c51001 part - 512 byte sector size. */ + rest_addr = 0x1ff; + sec_mask = 0x1fe00; + break; + case 0xbf: /* SST flash. */ + /* SST39sf10 part - 4kb sector size. */ + rest_addr = 0xfff; + sec_mask = 0x1f000; + break; + case 0xda: /* Winbond flash. */ + /* Winbond W29EE011 part - 256 byte sector size. */ + rest_addr = 0x7f; + sec_mask = 0x1ff80; + break; + case 0xc2: /* Macronix flash. */ + /* 64k sector size. */ + if (flash_id == 0x38 || flash_id == 0x4f) { + rest_addr = 0xffff; + sec_mask = 0x10000; + break; + } + /* Fall through... */ + + case 0x1f: /* Atmel flash. */ + /* 512k sector size. */ + if (flash_id == 0x13) { + rest_addr = 0x7fffffff; + sec_mask = 0x80000000; + break; + } + /* Fall through... */ + + case 0x01: /* AMD flash. */ + if (flash_id == 0x38 || flash_id == 0x40 || + flash_id == 0x4f) { + /* Am29LV081 part - 64kb sector size. */ + /* Am29LV002BT part - 64kb sector size. */ + rest_addr = 0xffff; + sec_mask = 0x10000; + break; + } else if (flash_id == 0x3e) { + /* + * Am29LV008b part - 64kb sector size with + * 32kb,8kb,8kb,16kb sector at memory address + * h0xf0000. + */ + rest_addr = 0xffff; + sec_mask = 0x10000; + break; + } else if (flash_id == 0x20 || flash_id == 0x6e) { + /* + * Am29LV010 part or AM29f010 - 16kb sector + * size. + */ + rest_addr = 0x3fff; + sec_mask = 0x1c000; + break; + } else if (flash_id == 0x6d) { + /* Am29LV001 part - 8kb sector size. */ + rest_addr = 0x1fff; + sec_mask = 0x1e000; + break; + } + default: + /* Default to 16 kb sector size. */ + rest_addr = 0x3fff; + sec_mask = 0x1c000; + break; + } + +update_flash: + if (IS_QLA2322(ha) || IS_QLA6322(ha)) { + if (qla2x00_erase_flash(ha, man_id, flash_id)) { + rval = QLA_FUNCTION_FAILED; + break; + } + } + + for (addr = offset, liter = 0; liter < length; liter++, + addr++) { + data = buf[liter]; + /* Are we at the beginning of a sector? */ + if ((addr & rest_addr) == 0) { + if (IS_QLA2322(ha) || IS_QLA6322(ha)) { + if (addr >= 0x10000UL) { + if (((addr >> 12) & 0xf0) && + ((man_id == 0x01 && + flash_id == 0x3e) || + (man_id == 0x20 && + flash_id == 0xd2))) { + sec_number++; + if (sec_number == 1) { + rest_addr = + 0x7fff; + sec_mask = + 0x18000; + } else if ( + sec_number == 2 || + sec_number == 3) { + rest_addr = + 0x1fff; + sec_mask = + 0x1e000; + } else if ( + sec_number == 4) { + rest_addr = + 0x3fff; + sec_mask = + 0x1c000; + } + } + } + } else if (addr == ha->optrom_size / 2) { + WRT_REG_WORD(®->nvram, NVR_SELECT); + RD_REG_WORD(®->nvram); + } + + if (flash_id == 0xda && man_id == 0xc1) { + qla2x00_write_flash_byte(ha, 0x5555, + 0xaa); + qla2x00_write_flash_byte(ha, 0x2aaa, + 0x55); + qla2x00_write_flash_byte(ha, 0x5555, + 0xa0); + } else if (!IS_QLA2322(ha) && !IS_QLA6322(ha)) { + /* Then erase it */ + if (qla2x00_erase_flash_sector(ha, + addr, sec_mask, man_id, + flash_id)) { + rval = QLA_FUNCTION_FAILED; + break; + } + if (man_id == 0x01 && flash_id == 0x6d) + sec_number++; + } + } + + if (man_id == 0x01 && flash_id == 0x6d) { + if (sec_number == 1 && + addr == (rest_addr - 1)) { + rest_addr = 0x0fff; + sec_mask = 0x1f000; + } else if (sec_number == 3 && (addr & 0x7ffe)) { + rest_addr = 0x3fff; + sec_mask = 0x1c000; + } + } + + if (qla2x00_program_flash_address(ha, addr, data, + man_id, flash_id)) { + rval = QLA_FUNCTION_FAILED; + break; + } + } + } while (0); + qla2x00_flash_disable(ha); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + /* Resume HBA. */ + qla2x00_resume_hba(ha); + + return rval; +} + +uint8_t * +qla24xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, + uint32_t offset, uint32_t length) +{ + /* Suspend HBA. */ + scsi_block_requests(ha->host); + ha->isp_ops.disable_intrs(ha); + set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); + + /* Go with read. */ + qla24xx_read_flash_data(ha, (uint32_t *)buf, offset >> 2, length >> 2); + + /* Resume HBA. */ + clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); + ha->isp_ops.enable_intrs(ha); + scsi_unblock_requests(ha->host); + + return buf; +} + +int +qla24xx_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, + uint32_t offset, uint32_t length) +{ + int rval; + + /* Suspend HBA. */ + scsi_block_requests(ha->host); + ha->isp_ops.disable_intrs(ha); + set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); + + /* Go with write. */ + rval = qla24xx_write_flash_data(ha, (uint32_t *)buf, offset >> 2, + length >> 2); + + /* Resume HBA -- RISC reset needed. */ + clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + up(ha->dpc_wait); + qla2x00_wait_for_hba_online(ha); + scsi_unblock_requests(ha->host); + + return rval; +} -- cgit v1.2.3 From d8a571135aad527e5984c8094b7977c6914f2550 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Wed, 1 Feb 2006 09:30:31 -0800 Subject: [SCSI] aacraid: reduce device probe warnings Received from Mark Salyzyn. This patch sets up some device quirks surrounding arrays to inform the scsi layer that various mode pages are not supported. This reduces the severity of the complaints that show up in the logs as the array devices are enumerated. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/linit.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 0bf5f9a943e8..45fc171e5f36 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -386,6 +386,10 @@ static int aac_biosparm(struct scsi_device *sdev, struct block_device *bdev, static int aac_slave_configure(struct scsi_device *sdev) { struct Scsi_Host *host = sdev->host; + if (sdev_channel(sdev) == CONTAINER_CHANNEL) { + sdev->skip_ms_page_8 = 1; + sdev->skip_ms_page_3f = 1; + } if (sdev->tagged_supported) scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, 128); -- cgit v1.2.3 From bfb35aa85057da4336af56a7f26e08031f4e3468 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Wed, 1 Feb 2006 09:30:55 -0800 Subject: [SCSI] aacraid: Update global function names Received from Mark Salyzyn, Reduce the possibility of namespace collision. Prefix with aac_. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aachba.c | 164 ++++++++++++++++++++-------------------- drivers/scsi/aacraid/aacraid.h | 18 ++--- drivers/scsi/aacraid/commctrl.c | 22 +++--- drivers/scsi/aacraid/comminit.c | 12 +-- drivers/scsi/aacraid/commsup.c | 50 ++++++------ drivers/scsi/aacraid/dpcsup.c | 2 +- drivers/scsi/aacraid/linit.c | 4 +- 7 files changed, 137 insertions(+), 135 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 7139659dd952..b0f314e415c9 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -173,10 +173,10 @@ int aac_get_config_status(struct aac_dev *dev) int status = 0; struct fib * fibptr; - if (!(fibptr = fib_alloc(dev))) + if (!(fibptr = aac_fib_alloc(dev))) return -ENOMEM; - fib_init(fibptr); + aac_fib_init(fibptr); { struct aac_get_config_status *dinfo; dinfo = (struct aac_get_config_status *) fib_data(fibptr); @@ -186,7 +186,7 @@ int aac_get_config_status(struct aac_dev *dev) dinfo->count = cpu_to_le32(sizeof(((struct aac_get_config_status_resp *)NULL)->data)); } - status = fib_send(ContainerCommand, + status = aac_fib_send(ContainerCommand, fibptr, sizeof (struct aac_get_config_status), FsaNormal, @@ -209,30 +209,30 @@ int aac_get_config_status(struct aac_dev *dev) status = -EINVAL; } } - fib_complete(fibptr); + aac_fib_complete(fibptr); /* Send a CT_COMMIT_CONFIG to enable discovery of devices */ if (status >= 0) { if (commit == 1) { struct aac_commit_config * dinfo; - fib_init(fibptr); + aac_fib_init(fibptr); dinfo = (struct aac_commit_config *) fib_data(fibptr); dinfo->command = cpu_to_le32(VM_ContainerConfig); dinfo->type = cpu_to_le32(CT_COMMIT_CONFIG); - status = fib_send(ContainerCommand, + status = aac_fib_send(ContainerCommand, fibptr, sizeof (struct aac_commit_config), FsaNormal, 1, 1, NULL, NULL); - fib_complete(fibptr); + aac_fib_complete(fibptr); } else if (commit == 0) { printk(KERN_WARNING "aac_get_config_status: Foreign device configurations are being ignored\n"); } } - fib_free(fibptr); + aac_fib_free(fibptr); return status; } @@ -255,15 +255,15 @@ int aac_get_containers(struct aac_dev *dev) instance = dev->scsi_host_ptr->unique_id; - if (!(fibptr = fib_alloc(dev))) + if (!(fibptr = aac_fib_alloc(dev))) return -ENOMEM; - fib_init(fibptr); + aac_fib_init(fibptr); dinfo = (struct aac_get_container_count *) fib_data(fibptr); dinfo->command = cpu_to_le32(VM_ContainerConfig); dinfo->type = cpu_to_le32(CT_GET_CONTAINER_COUNT); - status = fib_send(ContainerCommand, + status = aac_fib_send(ContainerCommand, fibptr, sizeof (struct aac_get_container_count), FsaNormal, @@ -272,7 +272,7 @@ int aac_get_containers(struct aac_dev *dev) if (status >= 0) { dresp = (struct aac_get_container_count_resp *)fib_data(fibptr); maximum_num_containers = le32_to_cpu(dresp->ContainerSwitchEntries); - fib_complete(fibptr); + aac_fib_complete(fibptr); } if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS) @@ -280,7 +280,7 @@ int aac_get_containers(struct aac_dev *dev) fsa_dev_ptr = (struct fsa_dev_info *) kmalloc( sizeof(*fsa_dev_ptr) * maximum_num_containers, GFP_KERNEL); if (!fsa_dev_ptr) { - fib_free(fibptr); + aac_fib_free(fibptr); return -ENOMEM; } memset(fsa_dev_ptr, 0, sizeof(*fsa_dev_ptr) * maximum_num_containers); @@ -294,14 +294,14 @@ int aac_get_containers(struct aac_dev *dev) fsa_dev_ptr[index].devname[0] = '\0'; - fib_init(fibptr); + aac_fib_init(fibptr); dinfo = (struct aac_query_mount *) fib_data(fibptr); dinfo->command = cpu_to_le32(VM_NameServe); dinfo->count = cpu_to_le32(index); dinfo->type = cpu_to_le32(FT_FILESYS); - status = fib_send(ContainerCommand, + status = aac_fib_send(ContainerCommand, fibptr, sizeof (struct aac_query_mount), FsaNormal, @@ -319,7 +319,7 @@ int aac_get_containers(struct aac_dev *dev) dinfo->count = cpu_to_le32(index); dinfo->type = cpu_to_le32(FT_FILESYS); - if (fib_send(ContainerCommand, + if (aac_fib_send(ContainerCommand, fibptr, sizeof(struct aac_query_mount), FsaNormal, @@ -347,7 +347,7 @@ int aac_get_containers(struct aac_dev *dev) if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY) fsa_dev_ptr[index].ro = 1; } - fib_complete(fibptr); + aac_fib_complete(fibptr); /* * If there are no more containers, then stop asking. */ @@ -355,7 +355,7 @@ int aac_get_containers(struct aac_dev *dev) break; } } - fib_free(fibptr); + aac_fib_free(fibptr); return status; } @@ -413,8 +413,8 @@ static void get_container_name_callback(void *context, struct fib * fibptr) scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; - fib_complete(fibptr); - fib_free(fibptr); + aac_fib_complete(fibptr); + aac_fib_free(fibptr); scsicmd->scsi_done(scsicmd); } @@ -430,10 +430,10 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid) dev = (struct aac_dev *)scsicmd->device->host->hostdata; - if (!(cmd_fibcontext = fib_alloc(dev))) + if (!(cmd_fibcontext = aac_fib_alloc(dev))) return -ENOMEM; - fib_init(cmd_fibcontext); + aac_fib_init(cmd_fibcontext); dinfo = (struct aac_get_name *) fib_data(cmd_fibcontext); dinfo->command = cpu_to_le32(VM_ContainerConfig); @@ -441,7 +441,7 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid) dinfo->cid = cpu_to_le32(cid); dinfo->count = cpu_to_le32(sizeof(((struct aac_get_name_resp *)NULL)->data)); - status = fib_send(ContainerCommand, + status = aac_fib_send(ContainerCommand, cmd_fibcontext, sizeof (struct aac_get_name), FsaNormal, @@ -455,14 +455,14 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid) if (status == -EINPROGRESS) return 0; - printk(KERN_WARNING "aac_get_container_name: fib_send failed with status: %d.\n", status); - fib_complete(cmd_fibcontext); - fib_free(cmd_fibcontext); + printk(KERN_WARNING "aac_get_container_name: aac_fib_send failed with status: %d.\n", status); + aac_fib_complete(cmd_fibcontext); + aac_fib_free(cmd_fibcontext); return -1; } /** - * probe_container - query a logical volume + * aac_probe_container - query a logical volume * @dev: device to query * @cid: container identifier * @@ -470,7 +470,7 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid) * is updated in the struct fsa_dev_info structure rather than returned. */ -int probe_container(struct aac_dev *dev, int cid) +int aac_probe_container(struct aac_dev *dev, int cid) { struct fsa_dev_info *fsa_dev_ptr; int status; @@ -482,10 +482,10 @@ int probe_container(struct aac_dev *dev, int cid) fsa_dev_ptr = dev->fsa_dev; instance = dev->scsi_host_ptr->unique_id; - if (!(fibptr = fib_alloc(dev))) + if (!(fibptr = aac_fib_alloc(dev))) return -ENOMEM; - fib_init(fibptr); + aac_fib_init(fibptr); dinfo = (struct aac_query_mount *)fib_data(fibptr); @@ -493,14 +493,14 @@ int probe_container(struct aac_dev *dev, int cid) dinfo->count = cpu_to_le32(cid); dinfo->type = cpu_to_le32(FT_FILESYS); - status = fib_send(ContainerCommand, + status = aac_fib_send(ContainerCommand, fibptr, sizeof(struct aac_query_mount), FsaNormal, 1, 1, NULL, NULL); if (status < 0) { - printk(KERN_WARNING "aacraid: probe_container query failed.\n"); + printk(KERN_WARNING "aacraid: aac_probe_container query failed.\n"); goto error; } @@ -512,7 +512,7 @@ int probe_container(struct aac_dev *dev, int cid) dinfo->count = cpu_to_le32(cid); dinfo->type = cpu_to_le32(FT_FILESYS); - if (fib_send(ContainerCommand, + if (aac_fib_send(ContainerCommand, fibptr, sizeof(struct aac_query_mount), FsaNormal, @@ -535,8 +535,8 @@ int probe_container(struct aac_dev *dev, int cid) } error: - fib_complete(fibptr); - fib_free(fibptr); + aac_fib_complete(fibptr); + aac_fib_free(fibptr); return status; } @@ -700,14 +700,14 @@ int aac_get_adapter_info(struct aac_dev* dev) struct aac_bus_info *command; struct aac_bus_info_response *bus_info; - if (!(fibptr = fib_alloc(dev))) + if (!(fibptr = aac_fib_alloc(dev))) return -ENOMEM; - fib_init(fibptr); + aac_fib_init(fibptr); info = (struct aac_adapter_info *) fib_data(fibptr); memset(info,0,sizeof(*info)); - rcode = fib_send(RequestAdapterInfo, + rcode = aac_fib_send(RequestAdapterInfo, fibptr, sizeof(*info), FsaNormal, @@ -716,8 +716,8 @@ int aac_get_adapter_info(struct aac_dev* dev) NULL); if (rcode < 0) { - fib_complete(fibptr); - fib_free(fibptr); + aac_fib_complete(fibptr); + aac_fib_free(fibptr); return rcode; } memcpy(&dev->adapter_info, info, sizeof(*info)); @@ -725,13 +725,13 @@ int aac_get_adapter_info(struct aac_dev* dev) if (dev->adapter_info.options & AAC_OPT_SUPPLEMENT_ADAPTER_INFO) { struct aac_supplement_adapter_info * info; - fib_init(fibptr); + aac_fib_init(fibptr); info = (struct aac_supplement_adapter_info *) fib_data(fibptr); memset(info,0,sizeof(*info)); - rcode = fib_send(RequestSupplementAdapterInfo, + rcode = aac_fib_send(RequestSupplementAdapterInfo, fibptr, sizeof(*info), FsaNormal, @@ -748,7 +748,7 @@ int aac_get_adapter_info(struct aac_dev* dev) * GetBusInfo */ - fib_init(fibptr); + aac_fib_init(fibptr); bus_info = (struct aac_bus_info_response *) fib_data(fibptr); @@ -761,7 +761,7 @@ int aac_get_adapter_info(struct aac_dev* dev) command->MethodId = cpu_to_le32(1); command->CtlCmd = cpu_to_le32(GetBusInfo); - rcode = fib_send(ContainerCommand, + rcode = aac_fib_send(ContainerCommand, fibptr, sizeof (*bus_info), FsaNormal, @@ -891,8 +891,8 @@ int aac_get_adapter_info(struct aac_dev* dev) } } - fib_complete(fibptr); - fib_free(fibptr); + aac_fib_complete(fibptr); + aac_fib_free(fibptr); return rcode; } @@ -976,8 +976,8 @@ static void io_callback(void *context, struct fib * fibptr) ? sizeof(scsicmd->sense_buffer) : sizeof(dev->fsa_dev[cid].sense_data)); } - fib_complete(fibptr); - fib_free(fibptr); + aac_fib_complete(fibptr); + aac_fib_free(fibptr); scsicmd->scsi_done(scsicmd); } @@ -1062,11 +1062,11 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) /* * Alocate and initialize a Fib */ - if (!(cmd_fibcontext = fib_alloc(dev))) { + if (!(cmd_fibcontext = aac_fib_alloc(dev))) { return -1; } - fib_init(cmd_fibcontext); + aac_fib_init(cmd_fibcontext); if (dev->raw_io_interface) { struct aac_raw_io *readcmd; @@ -1086,7 +1086,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) /* * Now send the Fib to the adapter */ - status = fib_send(ContainerRawIo, + status = aac_fib_send(ContainerRawIo, cmd_fibcontext, fibsize, FsaNormal, @@ -1112,7 +1112,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) /* * Now send the Fib to the adapter */ - status = fib_send(ContainerCommand64, + status = aac_fib_send(ContainerCommand64, cmd_fibcontext, fibsize, FsaNormal, @@ -1136,7 +1136,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) /* * Now send the Fib to the adapter */ - status = fib_send(ContainerCommand, + status = aac_fib_send(ContainerCommand, cmd_fibcontext, fibsize, FsaNormal, @@ -1153,14 +1153,14 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) if (status == -EINPROGRESS) return 0; - printk(KERN_WARNING "aac_read: fib_send failed with status: %d.\n", status); + printk(KERN_WARNING "aac_read: aac_fib_send failed with status: %d.\n", status); /* * For some reason, the Fib didn't queue, return QUEUE_FULL */ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_FULL; scsicmd->scsi_done(scsicmd); - fib_complete(cmd_fibcontext); - fib_free(cmd_fibcontext); + aac_fib_complete(cmd_fibcontext); + aac_fib_free(cmd_fibcontext); return 0; } @@ -1228,12 +1228,12 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) /* * Allocate and initialize a Fib then setup a BlockWrite command */ - if (!(cmd_fibcontext = fib_alloc(dev))) { + if (!(cmd_fibcontext = aac_fib_alloc(dev))) { scsicmd->result = DID_ERROR << 16; scsicmd->scsi_done(scsicmd); return 0; } - fib_init(cmd_fibcontext); + aac_fib_init(cmd_fibcontext); if (dev->raw_io_interface) { struct aac_raw_io *writecmd; @@ -1253,7 +1253,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) /* * Now send the Fib to the adapter */ - status = fib_send(ContainerRawIo, + status = aac_fib_send(ContainerRawIo, cmd_fibcontext, fibsize, FsaNormal, @@ -1279,7 +1279,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) /* * Now send the Fib to the adapter */ - status = fib_send(ContainerCommand64, + status = aac_fib_send(ContainerCommand64, cmd_fibcontext, fibsize, FsaNormal, @@ -1305,7 +1305,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) /* * Now send the Fib to the adapter */ - status = fib_send(ContainerCommand, + status = aac_fib_send(ContainerCommand, cmd_fibcontext, fibsize, FsaNormal, @@ -1322,15 +1322,15 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) return 0; } - printk(KERN_WARNING "aac_write: fib_send failed with status: %d\n", status); + printk(KERN_WARNING "aac_write: aac_fib_send failed with status: %d\n", status); /* * For some reason, the Fib didn't queue, return QUEUE_FULL */ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_FULL; scsicmd->scsi_done(scsicmd); - fib_complete(cmd_fibcontext); - fib_free(cmd_fibcontext); + aac_fib_complete(cmd_fibcontext); + aac_fib_free(cmd_fibcontext); return 0; } @@ -1369,8 +1369,8 @@ static void synchronize_callback(void *context, struct fib *fibptr) sizeof(cmd->sense_buffer))); } - fib_complete(fibptr); - fib_free(fibptr); + aac_fib_complete(fibptr); + aac_fib_free(fibptr); cmd->scsi_done(cmd); } @@ -1407,10 +1407,10 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid) * Allocate and initialize a Fib */ if (!(cmd_fibcontext = - fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata))) + aac_fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata))) return SCSI_MLQUEUE_HOST_BUSY; - fib_init(cmd_fibcontext); + aac_fib_init(cmd_fibcontext); synchronizecmd = fib_data(cmd_fibcontext); synchronizecmd->command = cpu_to_le32(VM_ContainerConfig); @@ -1422,7 +1422,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid) /* * Now send the Fib to the adapter */ - status = fib_send(ContainerCommand, + status = aac_fib_send(ContainerCommand, cmd_fibcontext, sizeof(struct aac_synchronize), FsaNormal, @@ -1437,9 +1437,9 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid) return 0; printk(KERN_WARNING - "aac_synchronize: fib_send failed with status: %d.\n", status); - fib_complete(cmd_fibcontext); - fib_free(cmd_fibcontext); + "aac_synchronize: aac_fib_send failed with status: %d.\n", status); + aac_fib_complete(cmd_fibcontext); + aac_fib_free(cmd_fibcontext); return SCSI_MLQUEUE_HOST_BUSY; } @@ -1488,7 +1488,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) case READ_CAPACITY: case TEST_UNIT_READY: spin_unlock_irq(host->host_lock); - probe_container(dev, cid); + aac_probe_container(dev, cid); if ((fsa_dev_ptr[cid].valid & 1) == 0) fsa_dev_ptr[cid].valid = 0; spin_lock_irq(host->host_lock); @@ -2089,8 +2089,8 @@ static void aac_srb_callback(void *context, struct fib * fibptr) */ scsicmd->result |= le32_to_cpu(srbreply->scsi_status); - fib_complete(fibptr); - fib_free(fibptr); + aac_fib_complete(fibptr); + aac_fib_free(fibptr); scsicmd->scsi_done(scsicmd); } @@ -2142,10 +2142,10 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd) /* * Allocate and initialize a Fib then setup a BlockWrite command */ - if (!(cmd_fibcontext = fib_alloc(dev))) { + if (!(cmd_fibcontext = aac_fib_alloc(dev))) { return -1; } - fib_init(cmd_fibcontext); + aac_fib_init(cmd_fibcontext); srbcmd = (struct aac_srb*) fib_data(cmd_fibcontext); srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); @@ -2179,7 +2179,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd) /* * Now send the Fib to the adapter */ - status = fib_send(ScsiPortCommand64, cmd_fibcontext, + status = aac_fib_send(ScsiPortCommand64, cmd_fibcontext, fibsize, FsaNormal, 0, 1, (fib_callback) aac_srb_callback, (void *) scsicmd); @@ -2201,7 +2201,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd) /* * Now send the Fib to the adapter */ - status = fib_send(ScsiPortCommand, cmd_fibcontext, fibsize, FsaNormal, 0, 1, + status = aac_fib_send(ScsiPortCommand, cmd_fibcontext, fibsize, FsaNormal, 0, 1, (fib_callback) aac_srb_callback, (void *) scsicmd); } /* @@ -2211,9 +2211,9 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd) return 0; } - printk(KERN_WARNING "aac_srb: fib_send failed with status: %d\n", status); - fib_complete(cmd_fibcontext); - fib_free(cmd_fibcontext); + printk(KERN_WARNING "aac_srb: aac_fib_send failed with status: %d\n", status); + aac_fib_complete(cmd_fibcontext); + aac_fib_free(cmd_fibcontext); return -1; } diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 66dbb6d2c506..2d430b7e8cf4 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -1774,16 +1774,16 @@ static inline u32 cap_to_cyls(sector_t capacity, u32 divisor) struct scsi_cmnd; const char *aac_driverinfo(struct Scsi_Host *); -struct fib *fib_alloc(struct aac_dev *dev); -int fib_setup(struct aac_dev *dev); -void fib_map_free(struct aac_dev *dev); -void fib_free(struct fib * context); -void fib_init(struct fib * context); +struct fib *aac_fib_alloc(struct aac_dev *dev); +int aac_fib_setup(struct aac_dev *dev); +void aac_fib_map_free(struct aac_dev *dev); +void aac_fib_free(struct fib * context); +void aac_fib_init(struct fib * context); void aac_printf(struct aac_dev *dev, u32 val); -int fib_send(u16 command, struct fib * context, unsigned long size, int priority, int wait, int reply, fib_callback callback, void *ctxt); +int aac_fib_send(u16 command, struct fib * context, unsigned long size, int priority, int wait, int reply, fib_callback callback, void *ctxt); int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry); void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum); -int fib_complete(struct fib * context); +int aac_fib_complete(struct fib * context); #define fib_data(fibctx) ((void *)(fibctx)->hw_fib->data) struct aac_dev *aac_init_adapter(struct aac_dev *dev); int aac_get_config_status(struct aac_dev *dev); @@ -1799,11 +1799,11 @@ unsigned int aac_command_normal(struct aac_queue * q); unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index); int aac_command_thread(struct aac_dev * dev); int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx); -int fib_adapter_complete(struct fib * fibptr, unsigned short size); +int aac_fib_adapter_complete(struct fib * fibptr, unsigned short size); struct aac_driver_ident* aac_get_driver_ident(int devtype); int aac_get_adapter_info(struct aac_dev* dev); int aac_send_shutdown(struct aac_dev *dev); -int probe_container(struct aac_dev *dev, int cid); +int aac_probe_container(struct aac_dev *dev, int cid); extern int numacb; extern int acbsize; extern char aac_driver_version[]; diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index 4fe79cd7c957..47fefca72695 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c @@ -63,7 +63,7 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg) unsigned size; int retval; - fibptr = fib_alloc(dev); + fibptr = aac_fib_alloc(dev); if(fibptr == NULL) { return -ENOMEM; } @@ -73,7 +73,7 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg) * First copy in the header so that we can check the size field. */ if (copy_from_user((void *)kfib, arg, sizeof(struct aac_fibhdr))) { - fib_free(fibptr); + aac_fib_free(fibptr); return -EFAULT; } /* @@ -110,13 +110,13 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg) */ kfib->header.XferState = 0; } else { - retval = fib_send(le16_to_cpu(kfib->header.Command), fibptr, + retval = aac_fib_send(le16_to_cpu(kfib->header.Command), fibptr, le16_to_cpu(kfib->header.Size) , FsaNormal, 1, 1, NULL, NULL); if (retval) { goto cleanup; } - if (fib_complete(fibptr) != 0) { + if (aac_fib_complete(fibptr) != 0) { retval = -EINVAL; goto cleanup; } @@ -138,7 +138,7 @@ cleanup: fibptr->hw_fib_pa = hw_fib_pa; fibptr->hw_fib = hw_fib; } - fib_free(fibptr); + aac_fib_free(fibptr); return retval; } @@ -464,10 +464,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) /* * Allocate and initialize a Fib then setup a BlockWrite command */ - if (!(srbfib = fib_alloc(dev))) { + if (!(srbfib = aac_fib_alloc(dev))) { return -ENOMEM; } - fib_init(srbfib); + aac_fib_init(srbfib); srbcmd = (struct aac_srb*) fib_data(srbfib); @@ -601,7 +601,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) srbcmd->count = cpu_to_le32(byte_count); psg->count = cpu_to_le32(sg_indx+1); - status = fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,NULL,NULL); + status = aac_fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,NULL,NULL); } else { struct user_sgmap* upsg = &user_srbcmd->sg; struct sgmap* psg = &srbcmd->sg; @@ -649,7 +649,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) } srbcmd->count = cpu_to_le32(byte_count); psg->count = cpu_to_le32(sg_indx+1); - status = fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL); + status = aac_fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL); } if (status != 0){ @@ -684,8 +684,8 @@ cleanup: for(i=0; i <= sg_indx; i++){ kfree(sg_list[i]); } - fib_complete(srbfib); - fib_free(srbfib); + aac_fib_complete(srbfib); + aac_fib_free(srbfib); return rcode; } diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 82821d331c07..1628d094943d 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c @@ -185,17 +185,17 @@ int aac_send_shutdown(struct aac_dev * dev) struct aac_close *cmd; int status; - fibctx = fib_alloc(dev); + fibctx = aac_fib_alloc(dev); if (!fibctx) return -ENOMEM; - fib_init(fibctx); + aac_fib_init(fibctx); cmd = (struct aac_close *) fib_data(fibctx); cmd->command = cpu_to_le32(VM_CloseAll); cmd->cid = cpu_to_le32(0xffffffff); - status = fib_send(ContainerCommand, + status = aac_fib_send(ContainerCommand, fibctx, sizeof(struct aac_close), FsaNormal, @@ -203,8 +203,8 @@ int aac_send_shutdown(struct aac_dev * dev) NULL, NULL); if (status == 0) - fib_complete(fibctx); - fib_free(fibctx); + aac_fib_complete(fibctx); + aac_fib_free(fibctx); return status; } @@ -427,7 +427,7 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) /* * Initialize the list of fibs */ - if(fib_setup(dev)<0){ + if (aac_fib_setup(dev) < 0) { kfree(dev->queues); return NULL; } diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 38d6d00fb0fc..97354ba7b185 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -67,27 +67,27 @@ static int fib_map_alloc(struct aac_dev *dev) } /** - * fib_map_free - free the fib objects + * aac_fib_map_free - free the fib objects * @dev: Adapter to free * * Free the PCI mappings and the memory allocated for FIB blocks * on this adapter. */ -void fib_map_free(struct aac_dev *dev) +void aac_fib_map_free(struct aac_dev *dev) { pci_free_consistent(dev->pdev, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB), dev->hw_fib_va, dev->hw_fib_pa); } /** - * fib_setup - setup the fibs + * aac_fib_setup - setup the fibs * @dev: Adapter to set up * * Allocate the PCI space for the fibs, map it and then intialise the * fib area, the unmapped fib data and also the free list */ -int fib_setup(struct aac_dev * dev) +int aac_fib_setup(struct aac_dev * dev) { struct fib *fibptr; struct hw_fib *hw_fib_va; @@ -134,14 +134,14 @@ int fib_setup(struct aac_dev * dev) } /** - * fib_alloc - allocate a fib + * aac_fib_alloc - allocate a fib * @dev: Adapter to allocate the fib for * * Allocate a fib from the adapter fib pool. If the pool is empty we * return NULL. */ -struct fib * fib_alloc(struct aac_dev *dev) +struct fib *aac_fib_alloc(struct aac_dev *dev) { struct fib * fibptr; unsigned long flags; @@ -170,14 +170,14 @@ struct fib * fib_alloc(struct aac_dev *dev) } /** - * fib_free - free a fib + * aac_fib_free - free a fib * @fibptr: fib to free up * * Frees up a fib and places it on the appropriate queue * (either free or timed out) */ -void fib_free(struct fib * fibptr) +void aac_fib_free(struct fib *fibptr) { unsigned long flags; @@ -188,7 +188,7 @@ void fib_free(struct fib * fibptr) fibptr->dev->timeout_fib = fibptr; } else { if (fibptr->hw_fib->header.XferState != 0) { - printk(KERN_WARNING "fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n", + printk(KERN_WARNING "aac_fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n", (void*)fibptr, le32_to_cpu(fibptr->hw_fib->header.XferState)); } @@ -199,13 +199,13 @@ void fib_free(struct fib * fibptr) } /** - * fib_init - initialise a fib + * aac_fib_init - initialise a fib * @fibptr: The fib to initialize * * Set up the generic fib fields ready for use */ -void fib_init(struct fib *fibptr) +void aac_fib_init(struct fib *fibptr) { struct hw_fib *hw_fib = fibptr->hw_fib; @@ -362,7 +362,7 @@ static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_f */ /** - * fib_send - send a fib to the adapter + * aac_fib_send - send a fib to the adapter * @command: Command to send * @fibptr: The fib * @size: Size of fib data area @@ -378,7 +378,9 @@ static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_f * response FIB is received from the adapter. */ -int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority, int wait, int reply, fib_callback callback, void * callback_data) +int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, + int priority, int wait, int reply, fib_callback callback, + void *callback_data) { struct aac_dev * dev = fibptr->dev; struct hw_fib * hw_fib = fibptr->hw_fib; @@ -493,7 +495,7 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority q->numpending++; *(q->headers.producer) = cpu_to_le32(index + 1); spin_unlock_irqrestore(q->lock, qflags); - dprintk((KERN_DEBUG "fib_send: inserting a queue entry at index %d.\n",index)); + dprintk((KERN_DEBUG "aac_fib_send: inserting a queue entry at index %d.\n",index)); if (!(nointr & aac_config.irq_mod)) aac_adapter_notify(dev, AdapNormCmdQueue); } @@ -520,7 +522,7 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority list_del(&fibptr->queue); spin_unlock_irqrestore(q->lock, qflags); if (wait == -1) { - printk(KERN_ERR "aacraid: fib_send: first asynchronous command timed out.\n" + printk(KERN_ERR "aacraid: aac_fib_send: first asynchronous command timed out.\n" "Usually a result of a PCI interrupt routing problem;\n" "update mother board BIOS or consider utilizing one of\n" "the SAFE mode kernel options (acpi, apic etc)\n"); @@ -624,7 +626,7 @@ void aac_consumer_free(struct aac_dev * dev, struct aac_queue *q, u32 qid) } /** - * fib_adapter_complete - complete adapter issued fib + * aac_fib_adapter_complete - complete adapter issued fib * @fibptr: fib to complete * @size: size of fib * @@ -632,7 +634,7 @@ void aac_consumer_free(struct aac_dev * dev, struct aac_queue *q, u32 qid) * the adapter. */ -int fib_adapter_complete(struct fib * fibptr, unsigned short size) +int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size) { struct hw_fib * hw_fib = fibptr->hw_fib; struct aac_dev * dev = fibptr->dev; @@ -683,20 +685,20 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size) } else { - printk(KERN_WARNING "fib_adapter_complete: Unknown xferstate detected.\n"); + printk(KERN_WARNING "aac_fib_adapter_complete: Unknown xferstate detected.\n"); BUG(); } return 0; } /** - * fib_complete - fib completion handler + * aac_fib_complete - fib completion handler * @fib: FIB to complete * * Will do all necessary work to complete a FIB. */ -int fib_complete(struct fib * fibptr) +int aac_fib_complete(struct fib *fibptr) { struct hw_fib * hw_fib = fibptr->hw_fib; @@ -995,14 +997,14 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) if (!dev || !dev->scsi_host_ptr) return; /* - * force reload of disk info via probe_container + * force reload of disk info via aac_probe_container */ if ((device_config_needed == CHANGE) && (dev->fsa_dev[container].valid == 1)) dev->fsa_dev[container].valid = 2; if ((device_config_needed == CHANGE) || (device_config_needed == ADD)) - probe_container(dev, container); + aac_probe_container(dev, container); device = scsi_device_lookup(dev->scsi_host_ptr, CONTAINER_TO_CHANNEL(container), CONTAINER_TO_ID(container), @@ -1104,7 +1106,7 @@ int aac_command_thread(struct aac_dev * dev) /* Handle Driver Notify Events */ aac_handle_aif(dev, fib); *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK); - fib_adapter_complete(fib, (u16)sizeof(u32)); + aac_fib_adapter_complete(fib, (u16)sizeof(u32)); } else { struct list_head *entry; /* The u32 here is important and intended. We are using @@ -1241,7 +1243,7 @@ int aac_command_thread(struct aac_dev * dev) * Set the status of this FIB */ *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK); - fib_adapter_complete(fib, sizeof(u32)); + aac_fib_adapter_complete(fib, sizeof(u32)); spin_unlock_irqrestore(&dev->fib_lock, flagv); /* Free up the remaining resources */ hw_fib_p = hw_fib_pool; diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c index 439948ef8251..f6bcb9486f85 100644 --- a/drivers/scsi/aacraid/dpcsup.c +++ b/drivers/scsi/aacraid/dpcsup.c @@ -206,7 +206,7 @@ unsigned int aac_command_normal(struct aac_queue *q) * Set the status of this FIB */ *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK); - fib_adapter_complete(fib, sizeof(u32)); + aac_fib_adapter_complete(fib, sizeof(u32)); spin_lock_irqsave(q->lock, flags); } } diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 45fc171e5f36..9defee03b823 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -917,7 +917,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, aac_adapter_disable_int(aac); free_irq(pdev->irq, aac); out_unmap: - fib_map_free(aac); + aac_fib_map_free(aac); pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys); kfree(aac->queues); iounmap(aac->regs.sa); @@ -951,7 +951,7 @@ static void __devexit aac_remove_one(struct pci_dev *pdev) aac_send_shutdown(aac); aac_adapter_disable_int(aac); - fib_map_free(aac); + aac_fib_map_free(aac); pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys); kfree(aac->queues); -- cgit v1.2.3 From bb08f92ebd75704e07d69bb9d8ee234d1a500b98 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Wed, 1 Feb 2006 09:30:44 -0800 Subject: [SCSI] aacraid: use no_uld_attach flag Received From Mark Salyzyn. In order to support user tools accessing the array components (SMART, Mode Page information, Cache page adjustments, WWN determination, Firmware updates etc), we take advantage of the no_uld_attach flag and deprecate the code that filters Inquiries to block the requests to array components. The quirk prevents the sd layer from attaching to the components. We also took the opportunity to balance the queue depths based on the total adapter queue depth to the array devices to reduce the chances of starvation. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aachba.c | 53 +++---------------------------------------- drivers/scsi/aacraid/linit.c | 42 ++++++++++++++++++++++++++-------- 2 files changed, 36 insertions(+), 59 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index b0f314e415c9..a16f8ded8f1d 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -1465,7 +1465,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) * itself. */ if (scmd_id(scsicmd) != host->this_id) { - if ((scsicmd->device->channel == 0) ){ + if ((scsicmd->device->channel == CONTAINER_CHANNEL)) { if( (scsicmd->device->id >= dev->maximum_num_containers) || (scsicmd->device->lun != 0)){ scsicmd->result = DID_NO_CONNECT << 16; scsicmd->scsi_done(scsicmd); @@ -1935,33 +1935,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr) case SRB_STATUS_ERROR_RECOVERY: case SRB_STATUS_PENDING: case SRB_STATUS_SUCCESS: - if(scsicmd->cmnd[0] == INQUIRY ){ - u8 b; - u8 b1; - /* We can't expose disk devices because we can't tell whether they - * are the raw container drives or stand alone drives. If they have - * the removable bit set then we should expose them though. - */ - b = (*(u8*)scsicmd->buffer)&0x1f; - b1 = ((u8*)scsicmd->buffer)[1]; - if( b==TYPE_TAPE || b==TYPE_WORM || b==TYPE_ROM || b==TYPE_MOD|| b==TYPE_MEDIUM_CHANGER - || (b==TYPE_DISK && (b1&0x80)) ){ - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; - /* - * We will allow disk devices if in RAID/SCSI mode and - * the channel is 2 - */ - } else if ((dev->raid_scsi_mode) && - (scmd_channel(scsicmd) == 2)) { - scsicmd->result = DID_OK << 16 | - COMMAND_COMPLETE << 8; - } else { - scsicmd->result = DID_NO_CONNECT << 16 | - COMMAND_COMPLETE << 8; - } - } else { - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; - } + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; break; case SRB_STATUS_DATA_OVERRUN: switch(scsicmd->cmnd[0]){ @@ -1981,28 +1955,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr) scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8; break; case INQUIRY: { - u8 b; - u8 b1; - /* We can't expose disk devices because we can't tell whether they - * are the raw container drives or stand alone drives - */ - b = (*(u8*)scsicmd->buffer)&0x0f; - b1 = ((u8*)scsicmd->buffer)[1]; - if( b==TYPE_TAPE || b==TYPE_WORM || b==TYPE_ROM || b==TYPE_MOD|| b==TYPE_MEDIUM_CHANGER - || (b==TYPE_DISK && (b1&0x80)) ){ - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; - /* - * We will allow disk devices if in RAID/SCSI mode and - * the channel is 2 - */ - } else if ((dev->raid_scsi_mode) && - (scmd_channel(scsicmd) == 2)) { - scsicmd->result = DID_OK << 16 | - COMMAND_COMPLETE << 8; - } else { - scsicmd->result = DID_NO_CONNECT << 16 | - COMMAND_COMPLETE << 8; - } + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; break; } default: diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 9defee03b823..271617890562 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -385,21 +385,45 @@ static int aac_biosparm(struct scsi_device *sdev, struct block_device *bdev, static int aac_slave_configure(struct scsi_device *sdev) { - struct Scsi_Host *host = sdev->host; if (sdev_channel(sdev) == CONTAINER_CHANNEL) { sdev->skip_ms_page_8 = 1; sdev->skip_ms_page_3f = 1; } + if ((sdev->type == TYPE_DISK) && + (sdev_channel(sdev) != CONTAINER_CHANNEL)) { + struct aac_dev *aac = (struct aac_dev *)sdev->host->hostdata; + if (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2)) + sdev->no_uld_attach = 1; + } + if (sdev->tagged_supported && (sdev->type == TYPE_DISK) && + (sdev_channel(sdev) == CONTAINER_CHANNEL)) { + struct scsi_device * dev; + struct Scsi_Host *host = sdev->host; + unsigned num_lsu = 0; + unsigned num_one = 0; + unsigned depth; - if (sdev->tagged_supported) - scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, 128); - else + __shost_for_each_device(dev, host) { + if (dev->tagged_supported && (dev->type == TYPE_DISK) && + (sdev_channel(dev) == CONTAINER_CHANNEL)) + ++num_lsu; + else + ++num_one; + } + if (num_lsu == 0) + ++num_lsu; + depth = (host->can_queue - num_one) / num_lsu; + if (depth > 256) + depth = 256; + else if (depth < 2) + depth = 2; + scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, depth); + if (!(((struct aac_dev *)host->hostdata)->adapter_info.options & + AAC_OPT_NEW_COMM)) + blk_queue_max_segment_size(sdev->request_queue, 65536); + } else scsi_adjust_queue_depth(sdev, 0, 1); - if (!(((struct aac_dev *)host->hostdata)->adapter_info.options - & AAC_OPT_NEW_COMM)) - blk_queue_max_segment_size(sdev->request_queue, 65536); - return 0; } @@ -874,7 +898,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, /* * max channel will be the physical channels plus 1 virtual channel - * all containers are on the virtual channel 0 + * all containers are on the virtual channel 0 (CONTAINER_CHANNEL) * physical channels are address by their actual physical number+1 */ if (aac->nondasd_support == 1) -- cgit v1.2.3 From 7b7232f3fb5ecd7c30cb52df368070cc5f5ca614 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 1 Feb 2006 21:06:49 -0600 Subject: [SCSI] iscsi update: cleanup iscsi class interface From: michaelc@cs.wisc.edu fujita.tomonori@lab.ntt.co.jp da-x@monatomic.org and err path fixup from: ogerlitz@voltaire.com This patch cleans up that interface by having the lld and class pass a iscsi_cls_session or iscsi_cls_conn between each other when the function is used by HW and SW iscsi llds. This way the lld does not have to remember if it has to send a handle or pointer and a handle or pointer to connection, session or host. This also has the class verify the session handle that gets passed from userspace instead of using the pointer passed into the kernel directly. Signed-off-by: Mike Christie Signed-off-by: Alex Aizman Signed-off-by: Dmitry Yusupov Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 70 +++++++----- drivers/scsi/iscsi_tcp.h | 3 + drivers/scsi/scsi_transport_iscsi.c | 221 ++++++++++++++++++------------------ 3 files changed, 154 insertions(+), 140 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 780bfcc67096..d07d309ac026 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -146,7 +146,7 @@ iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err) spin_unlock_irqrestore(&session->lock, flags); set_bit(SUSPEND_BIT, &conn->suspend_tx); set_bit(SUSPEND_BIT, &conn->suspend_rx); - iscsi_conn_error(iscsi_handle(conn), err); + iscsi_conn_error(conn->cls_conn, err); } static inline int @@ -689,7 +689,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn) break; if (!conn->in.datalen) { - rc = iscsi_recv_pdu(iscsi_handle(conn), hdr, + rc = iscsi_recv_pdu(conn->cls_conn, hdr, NULL, 0); if (conn->login_mtask != mtask) { spin_lock(&session->lock); @@ -737,7 +737,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn) if (!conn->in.datalen) { struct iscsi_mgmt_task *mtask; - rc = iscsi_recv_pdu(iscsi_handle(conn), hdr, + rc = iscsi_recv_pdu(conn->cls_conn, hdr, NULL, 0); mtask = (struct iscsi_mgmt_task *) session->mgmt_cmds[conn->in.itt - @@ -761,7 +761,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn) rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)hdr); if (!rc && hdr->ttt != ISCSI_RESERVED_TAG) - rc = iscsi_recv_pdu(iscsi_handle(conn), + rc = iscsi_recv_pdu(conn->cls_conn, hdr, NULL, 0); } else rc = ISCSI_ERR_PROTO; @@ -1044,7 +1044,7 @@ iscsi_data_recv(struct iscsi_conn *conn) goto exit; } - rc = iscsi_recv_pdu(iscsi_handle(conn), conn->in.hdr, + rc = iscsi_recv_pdu(conn->cls_conn, conn->in.hdr, conn->data, conn->in.datalen); if (!rc && conn->datadgst_en && @@ -2428,19 +2428,20 @@ iscsi_pool_free(struct iscsi_queue *q, void **items) } static struct iscsi_cls_conn * -iscsi_conn_create(struct Scsi_Host *shost, uint32_t conn_idx) +iscsi_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx) { + struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); struct iscsi_session *session = iscsi_hostdata(shost->hostdata); struct iscsi_conn *conn; struct iscsi_cls_conn *cls_conn; - cls_conn = iscsi_create_conn(hostdata_session(shost->hostdata), - conn_idx); + cls_conn = iscsi_create_conn(cls_session, conn_idx); if (!cls_conn) return NULL; conn = cls_conn->dd_data; + memset(conn, 0, sizeof(*conn)); - memset(conn, 0, sizeof(struct iscsi_conn)); + conn->cls_conn = cls_conn; conn->c_stage = ISCSI_CONN_INITIAL_STAGE; conn->in_progress = IN_PROGRESS_WAIT_HEADER; conn->id = conn_idx; @@ -2625,11 +2626,13 @@ iscsi_conn_destroy(struct iscsi_cls_conn *cls_conn) } static int -iscsi_conn_bind(iscsi_sessionh_t sessionh, iscsi_connh_t connh, - uint32_t transport_fd, int is_leading) +iscsi_conn_bind(struct iscsi_cls_session *cls_session, + struct iscsi_cls_conn *cls_conn, uint32_t transport_fd, + int is_leading) { - struct iscsi_session *session = iscsi_ptr(sessionh); - struct iscsi_conn *tmp = ERR_PTR(-EEXIST), *conn = iscsi_ptr(connh); + struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); + struct iscsi_session *session = iscsi_hostdata(shost->hostdata); + struct iscsi_conn *tmp = ERR_PTR(-EEXIST), *conn = cls_conn->dd_data; struct sock *sk; struct socket *sock; int err; @@ -2703,9 +2706,9 @@ iscsi_conn_bind(iscsi_sessionh_t sessionh, iscsi_connh_t connh, } static int -iscsi_conn_start(iscsi_connh_t connh) +iscsi_conn_start(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; struct sock *sk; @@ -2754,9 +2757,9 @@ iscsi_conn_start(iscsi_connh_t connh) } static void -iscsi_conn_stop(iscsi_connh_t connh, int flag) +iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) { - struct iscsi_conn *conn = iscsi_ptr(connh); + struct iscsi_conn *conn = cls_conn->dd_data; struct iscsi_session *session = conn->session; struct sock *sk; unsigned long flags; @@ -3253,9 +3256,9 @@ static struct scsi_host_template iscsi_sht = { static struct iscsi_transport iscsi_tcp_transport; -static struct Scsi_Host * +static struct iscsi_cls_session * iscsi_session_create(struct scsi_transport_template *scsit, - uint32_t initial_cmdsn) + uint32_t initial_cmdsn, uint32_t *sid) { struct Scsi_Host *shost; struct iscsi_session *session; @@ -3275,6 +3278,7 @@ iscsi_session_create(struct scsi_transport_template *scsit, session->exp_cmdsn = initial_cmdsn + 1; session->max_cmdsn = initial_cmdsn + 1; session->max_r2t = 1; + *sid = shost->host_no; /* initialize SCSI PDU commands pool */ if (iscsi_pool_init(&session->cmdpool, session->cmds_max, @@ -3311,7 +3315,7 @@ iscsi_session_create(struct scsi_transport_template *scsit, if (iscsi_r2tpool_alloc(session)) goto r2tpool_alloc_fail; - return shost; + return hostdata_session(shost->hostdata); r2tpool_alloc_fail: for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) @@ -3321,12 +3325,14 @@ immdata_alloc_fail: mgmtpool_alloc_fail: iscsi_pool_free(&session->cmdpool, (void**)session->cmds); cmdpool_alloc_fail: + iscsi_transport_destroy_session(shost); return NULL; } static void -iscsi_session_destroy(struct Scsi_Host *shost) +iscsi_session_destroy(struct iscsi_cls_session *cls_session) { + struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); struct iscsi_session *session = iscsi_hostdata(shost->hostdata); int cmd_i; struct iscsi_data_task *dtask, *n; @@ -3350,10 +3356,10 @@ iscsi_session_destroy(struct Scsi_Host *shost) } static int -iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param, +iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, uint32_t value) { - struct iscsi_conn *conn = iscsi_ptr(connh); + struct iscsi_conn *conn = cls_conn->dd_data; struct iscsi_session *session = conn->session; spin_lock_bh(&session->lock); @@ -3495,9 +3501,10 @@ iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param, } static int -iscsi_session_get_param(struct Scsi_Host *shost, +iscsi_session_get_param(struct iscsi_cls_session *cls_session, enum iscsi_param param, uint32_t *value) { + struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); struct iscsi_session *session = iscsi_hostdata(shost->hostdata); switch(param) { @@ -3539,9 +3546,10 @@ iscsi_session_get_param(struct Scsi_Host *shost, } static int -iscsi_conn_get_param(void *data, enum iscsi_param param, uint32_t *value) +iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, + enum iscsi_param param, uint32_t *value) { - struct iscsi_conn *conn = data; + struct iscsi_conn *conn = cls_conn->dd_data; switch(param) { case ISCSI_PARAM_MAX_RECV_DLENGTH: @@ -3564,9 +3572,9 @@ iscsi_conn_get_param(void *data, enum iscsi_param param, uint32_t *value) } static void -iscsi_conn_get_stats(iscsi_connh_t connh, struct iscsi_stats *stats) +iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats) { - struct iscsi_conn *conn = iscsi_ptr(connh); + struct iscsi_conn *conn = cls_conn->dd_data; stats->txdata_octets = conn->txdata_octets; stats->rxdata_octets = conn->rxdata_octets; @@ -3587,10 +3595,10 @@ iscsi_conn_get_stats(iscsi_connh_t connh, struct iscsi_stats *stats) } static int -iscsi_conn_send_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr, char *data, - uint32_t data_size) +iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr, + char *data, uint32_t data_size) { - struct iscsi_conn *conn = iscsi_ptr(connh); + struct iscsi_conn *conn = cls_conn->dd_data; int rc; mutex_lock(&conn->xmitmutex); diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h index f95e61b76f70..6766b817db2d 100644 --- a/drivers/scsi/iscsi_tcp.h +++ b/drivers/scsi/iscsi_tcp.h @@ -113,7 +113,10 @@ struct iscsi_tcp_recv { int datadgst; }; +struct iscsi_cls_conn; + struct iscsi_conn { + struct iscsi_cls_conn *cls_conn; /* ptr to class connection */ struct iscsi_hdr hdr; /* header placeholder */ char hdrext[4*sizeof(__u16) + sizeof(__u32)]; diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 59a1c9d9d3bd..b61868587dca 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -164,9 +164,43 @@ static struct mempool_zone *z_reply; #define Z_MAX_ERROR 16 #define Z_HIWAT_ERROR 12 +static LIST_HEAD(sesslist); +static DEFINE_SPINLOCK(sesslock); static LIST_HEAD(connlist); static DEFINE_SPINLOCK(connlock); +static struct iscsi_cls_session *iscsi_session_lookup(uint64_t handle) +{ + unsigned long flags; + struct iscsi_cls_session *sess; + + spin_lock_irqsave(&sesslock, flags); + list_for_each_entry(sess, &sesslist, sess_list) { + if (sess == iscsi_ptr(handle)) { + spin_unlock_irqrestore(&sesslock, flags); + return sess; + } + } + spin_unlock_irqrestore(&sesslock, flags); + return NULL; +} + +static struct iscsi_cls_conn *iscsi_conn_lookup(uint64_t handle) +{ + unsigned long flags; + struct iscsi_cls_conn *conn; + + spin_lock_irqsave(&connlock, flags); + list_for_each_entry(conn, &connlist, conn_list) { + if (conn == iscsi_ptr(handle)) { + spin_unlock_irqrestore(&connlock, flags); + return conn; + } + } + spin_unlock_irqrestore(&connlock, flags); + return NULL; +} + /* * The following functions can be used by LLDs that allocate * their own scsi_hosts or by software iscsi LLDs @@ -365,6 +399,7 @@ iscsi_transport_create_session(struct scsi_transport_template *scsit, { struct iscsi_cls_session *session; struct Scsi_Host *shost; + unsigned long flags; shost = scsi_host_alloc(transport->host_template, hostdata_privsize(transport)); @@ -389,6 +424,9 @@ iscsi_transport_create_session(struct scsi_transport_template *scsit, goto remove_host; *(unsigned long*)shost->hostdata = (unsigned long)session; + spin_lock_irqsave(&sesslock, flags); + list_add(&session->sess_list, &sesslist); + spin_unlock_irqrestore(&sesslock, flags); return shost; remove_host: @@ -410,9 +448,13 @@ EXPORT_SYMBOL_GPL(iscsi_transport_create_session); int iscsi_transport_destroy_session(struct Scsi_Host *shost) { struct iscsi_cls_session *session; + unsigned long flags; scsi_remove_host(shost); session = hostdata_session(shost->hostdata); + spin_lock_irqsave(&sesslock, flags); + list_del(&session->sess_list); + spin_unlock_irqrestore(&sesslock, flags); iscsi_destroy_session(session); /* ref from host alloc */ scsi_host_put(shost); @@ -424,22 +466,6 @@ 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_cls_conn *conn; - - spin_lock_irqsave(&connlock, flags); - list_for_each_entry(conn, &connlist, conn_list) - if (conn->connh == key) { - spin_unlock_irqrestore(&connlock, flags); - return conn; - } - spin_unlock_irqrestore(&connlock, flags); - return NULL; -} - static struct iscsi_internal * iscsi_if_transport_lookup(struct iscsi_transport *tt) { @@ -559,25 +585,21 @@ iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb) return 0; } -int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr, +int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr, char *data, uint32_t data_size) { struct nlmsghdr *nlh; struct sk_buff *skb; struct iscsi_uevent *ev; - struct iscsi_cls_conn *conn; char *pdu; int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) + data_size); - conn = iscsi_if_find_conn(connh); - BUG_ON(!conn); - mempool_zone_complete(conn->z_pdu); skb = mempool_zone_get_skb(conn->z_pdu); if (!skb) { - iscsi_conn_error(connh, ISCSI_ERR_CONN_FAILED); + iscsi_conn_error(conn, ISCSI_ERR_CONN_FAILED); dev_printk(KERN_ERR, &conn->dev, "iscsi: can not deliver " "control PDU: OOM\n"); return -ENOMEM; @@ -590,7 +612,7 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr, ev->type = ISCSI_KEVENT_RECV_PDU; if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat) ev->iferror = -ENOMEM; - ev->r.recv_req.conn_handle = connh; + ev->r.recv_req.conn_handle = iscsi_handle(conn); pdu = (char*)ev + sizeof(*ev); memcpy(pdu, hdr, sizeof(struct iscsi_hdr)); memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size); @@ -599,17 +621,13 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr, } EXPORT_SYMBOL_GPL(iscsi_recv_pdu); -void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error) +void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error) { struct nlmsghdr *nlh; struct sk_buff *skb; struct iscsi_uevent *ev; - 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); skb = mempool_zone_get_skb(conn->z_error); @@ -626,7 +644,7 @@ void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error) 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; + ev->r.connerror.conn_handle = iscsi_handle(conn); iscsi_unicast_skb(conn->z_error, skb); @@ -677,7 +695,7 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb, ISCSI_STATS_CUSTOM_MAX); int err = 0; - conn = iscsi_if_find_conn(ev->u.get_stats.conn_handle); + conn = iscsi_conn_lookup(ev->u.get_stats.conn_handle); if (!conn) return -EEXIST; @@ -707,7 +725,7 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb, ((char*)evstat + sizeof(*evstat)); memset(stats, 0, sizeof(*stats)); - transport->get_stats(ev->u.get_stats.conn_handle, stats); + transport->get_stats(conn, stats); actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) + sizeof(struct iscsi_stats) + sizeof(struct iscsi_stats_custom) * @@ -727,58 +745,34 @@ static int iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev) { struct iscsi_transport *transport = priv->iscsi_transport; - struct Scsi_Host *shost; - - if (!transport->create_session) - return -EINVAL; + struct iscsi_cls_session *session; + uint32_t sid; - shost = transport->create_session(&priv->t, - ev->u.c_session.initial_cmdsn); - if (!shost) + session = transport->create_session(&priv->t, + ev->u.c_session.initial_cmdsn, + &sid); + if (!session) return -ENOMEM; - ev->r.c_session_ret.session_handle = iscsi_handle(iscsi_hostdata(shost->hostdata)); - ev->r.c_session_ret.sid = shost->host_no; + ev->r.c_session_ret.session_handle = iscsi_handle(session); + ev->r.c_session_ret.sid = sid; return 0; } static int -iscsi_if_destroy_session(struct iscsi_internal *priv, struct iscsi_uevent *ev) +iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev) { - struct iscsi_transport *transport = priv->iscsi_transport; - - struct Scsi_Host *shost; - - if (!transport->destroy_session) - return -EINVAL; - - shost = scsi_host_lookup(ev->u.d_session.sid); - if (shost == ERR_PTR(-ENXIO)) - return -EEXIST; - - 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 Scsi_Host *shost; struct iscsi_cls_conn *conn; + struct iscsi_cls_session *session; unsigned long flags; - if (!transport->create_conn) + session = iscsi_session_lookup(ev->u.c_conn.session_handle); + if (!session) return -EINVAL; - shost = scsi_host_lookup(ev->u.c_conn.sid); - if (shost == ERR_PTR(-ENXIO)) - return -EEXIST; - - conn = transport->create_conn(shost, ev->u.c_conn.cid); + conn = transport->create_conn(session, ev->u.c_conn.cid); if (!conn) - goto release_ref; + return -ENOMEM; conn->z_pdu = mempool_zone_init(Z_MAX_PDU, NLMSG_SPACE(sizeof(struct iscsi_uevent) + @@ -800,14 +794,13 @@ iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev) goto free_pdu_pool; } - ev->r.handle = conn->connh = iscsi_handle(conn->dd_data); + ev->r.handle = iscsi_handle(conn); spin_lock_irqsave(&connlock, flags); list_add(&conn->conn_list, &connlist); conn->active = 1; spin_unlock_irqrestore(&connlock, flags); - scsi_host_put(shost); return 0; free_pdu_pool: @@ -815,8 +808,6 @@ free_pdu_pool: destroy_conn: if (transport->destroy_conn) transport->destroy_conn(conn->dd_data); -release_ref: - scsi_host_put(shost); return -ENOMEM; } @@ -827,13 +818,9 @@ iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev struct iscsi_cls_conn *conn; struct mempool_zone *z_error, *z_pdu; - conn = iscsi_if_find_conn(ev->u.d_conn.conn_handle); + conn = iscsi_conn_lookup(ev->u.d_conn.conn_handle); if (!conn) - return -EEXIST; - - if (!transport->destroy_conn) return -EINVAL; - spin_lock_irqsave(&connlock, flags); conn->active = 0; list_del(&conn->conn_list); @@ -858,6 +845,8 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) struct iscsi_uevent *ev = NLMSG_DATA(nlh); struct iscsi_transport *transport = NULL; struct iscsi_internal *priv; + struct iscsi_cls_session *session; + struct iscsi_cls_conn *conn; if (NETLINK_CREDS(skb)->uid) return -EPERM; @@ -867,6 +856,9 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) return -EINVAL; transport = priv->iscsi_transport; + if (!try_module_get(transport->owner)) + return -EINVAL; + daemon_pid = NETLINK_CREDS(skb)->pid; switch (nlh->nlmsg_type) { @@ -874,7 +866,11 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) err = iscsi_if_create_session(priv, ev); break; case ISCSI_UEVENT_DESTROY_SESSION: - err = iscsi_if_destroy_session(priv, ev); + session = iscsi_session_lookup(ev->u.d_session.session_handle); + if (session) + transport->destroy_session(session); + else + err = -EINVAL; break; case ISCSI_UEVENT_CREATE_CONN: err = iscsi_if_create_conn(transport, ev); @@ -883,41 +879,48 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) err = iscsi_if_destroy_conn(transport, ev); break; case ISCSI_UEVENT_BIND_CONN: - if (!iscsi_if_find_conn(ev->u.b_conn.conn_handle)) - return -EEXIST; - ev->r.retcode = transport->bind_conn( - ev->u.b_conn.session_handle, - ev->u.b_conn.conn_handle, - ev->u.b_conn.transport_fd, - ev->u.b_conn.is_leading); + session = iscsi_session_lookup(ev->u.b_conn.session_handle); + conn = iscsi_conn_lookup(ev->u.b_conn.conn_handle); + + if (session && conn) + ev->r.retcode = transport->bind_conn(session, conn, + ev->u.b_conn.transport_fd, + ev->u.b_conn.is_leading); + else + err = -EINVAL; break; case ISCSI_UEVENT_SET_PARAM: - if (!iscsi_if_find_conn(ev->u.set_param.conn_handle)) - return -EEXIST; - ev->r.retcode = transport->set_param( - ev->u.set_param.conn_handle, - ev->u.set_param.param, ev->u.set_param.value); + conn = iscsi_conn_lookup(ev->u.set_param.conn_handle); + if (conn) + ev->r.retcode = transport->set_param(conn, + ev->u.set_param.param, ev->u.set_param.value); + else + err = -EINVAL; break; case ISCSI_UEVENT_START_CONN: - if (!iscsi_if_find_conn(ev->u.start_conn.conn_handle)) - return -EEXIST; - ev->r.retcode = transport->start_conn( - ev->u.start_conn.conn_handle); + conn = iscsi_conn_lookup(ev->u.start_conn.conn_handle); + if (conn) + ev->r.retcode = transport->start_conn(conn); + else + err = -EINVAL; + break; case ISCSI_UEVENT_STOP_CONN: - if (!iscsi_if_find_conn(ev->u.stop_conn.conn_handle)) - return -EEXIST; - transport->stop_conn(ev->u.stop_conn.conn_handle, - ev->u.stop_conn.flag); + conn = iscsi_conn_lookup(ev->u.stop_conn.conn_handle); + if (conn) + transport->stop_conn(conn, ev->u.stop_conn.flag); + else + err = -EINVAL; break; case ISCSI_UEVENT_SEND_PDU: - if (!iscsi_if_find_conn(ev->u.send_pdu.conn_handle)) - return -EEXIST; - ev->r.retcode = transport->send_pdu( - ev->u.send_pdu.conn_handle, - (struct iscsi_hdr*)((char*)ev + sizeof(*ev)), - (char*)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size, - ev->u.send_pdu.data_size); + conn = iscsi_conn_lookup(ev->u.send_pdu.conn_handle); + if (conn) + ev->r.retcode = transport->send_pdu(conn, + (struct iscsi_hdr*)((char*)ev + sizeof(*ev)), + (char*)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size, + ev->u.send_pdu.data_size); + else + err = -EINVAL; break; case ISCSI_UEVENT_GET_STATS: err = iscsi_if_get_stats(transport, skb, nlh); @@ -927,6 +930,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) break; } + module_put(transport->owner); return err; } @@ -997,7 +1001,7 @@ show_conn_int_param_##param(struct class_device *cdev, char *buf) \ struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev); \ struct iscsi_transport *t = conn->transport; \ \ - t->get_conn_param(conn->dd_data, param, &value); \ + t->get_conn_param(conn, param, &value); \ return snprintf(buf, 20, format"\n", value); \ } @@ -1024,10 +1028,9 @@ show_session_int_param_##param(struct class_device *cdev, char *buf) \ { \ uint32_t value = 0; \ 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; \ \ - t->get_session_param(shost, param, &value); \ + t->get_session_param(session, param, &value); \ return snprintf(buf, 20, format"\n", value); \ } -- cgit v1.2.3 From 5b940adf5b341b12dbb94e7cbdb416b35f52017b Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 1 Feb 2006 21:06:56 -0600 Subject: [SCSI] iscsi update: pass correct skb to skb_trim >From da-x@monatomic.org: Wrong skb is passed to skb_trim in iscsi_if_get_stats. Signed-off-by: Mike Christie Signed-off-by: Alex Aizman Signed-off-by: Dmitry Yusupov Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_iscsi.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index b61868587dca..79ca29ee1aee 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -680,8 +680,7 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi, } static int -iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb, - struct nlmsghdr *nlh) +iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh) { struct iscsi_uevent *ev = NLMSG_DATA(nlh); struct iscsi_stats *stats; @@ -732,7 +731,7 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb, stats->custom_length); actual_size -= sizeof(*nlhstat); actual_size = NLMSG_LENGTH(actual_size); - skb_trim(skb, NLMSG_ALIGN(actual_size)); + skb_trim(skbstat, NLMSG_ALIGN(actual_size)); nlhstat->nlmsg_len = actual_size; err = iscsi_unicast_skb(conn->z_pdu, skbstat); @@ -923,7 +922,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) err = -EINVAL; break; case ISCSI_UEVENT_GET_STATS: - err = iscsi_if_get_stats(transport, skb, nlh); + err = iscsi_if_get_stats(transport, nlh); break; default: err = -EINVAL; -- cgit v1.2.3 From 142e301fc818de9b116706835cd9fc864e73f203 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 1 Feb 2006 21:06:58 -0600 Subject: [SCSI] iscsi update: setup pool before using >From andmike@us.ibm.com: Ensure that pool data is setup prior to calling mempool_create as it will call the the alloc function during create. Signed-off-by: Mike Anderson Signed-off-by: Mike Christie Signed-off-by: Alex Aizman Signed-off-by: Dmitry Yusupov Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_iscsi.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 79ca29ee1aee..448fd78777f9 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -530,6 +530,12 @@ mempool_zone_init(unsigned max, unsigned size, unsigned hiwat) if (!zp) return NULL; + zp->size = size; + zp->hiwat = hiwat; + INIT_LIST_HEAD(&zp->freequeue); + spin_lock_init(&zp->freelock); + atomic_set(&zp->allocated, 0); + zp->pool = mempool_create(max, mempool_zone_alloc_skb, mempool_zone_free_skb, zp); if (!zp->pool) { @@ -537,13 +543,6 @@ mempool_zone_init(unsigned max, unsigned size, unsigned hiwat) return NULL; } - zp->size = size; - zp->hiwat = hiwat; - - INIT_LIST_HEAD(&zp->freequeue); - spin_lock_init(&zp->freelock); - atomic_set(&zp->allocated, 0); - return zp; } -- cgit v1.2.3 From ee7f8e405342722e42c15fe8e841a679f8951eea Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 1 Feb 2006 21:07:01 -0600 Subject: [SCSI] iscsi update: set deamon pid earlier >From michaelc@cs.wisc.edu: If the transport lookup fails we set the daemon pid too late. This can cause us deadlock since the netlink code will think we meant to call back into our iscsi_if_rx function. Signed-off-by: Mike Christie Signed-off-by: Alex Aizman Signed-off-by: Dmitry Yusupov Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_iscsi.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 448fd78777f9..7fb69183c72d 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -846,9 +846,6 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) struct iscsi_cls_session *session; struct iscsi_cls_conn *conn; - if (NETLINK_CREDS(skb)->uid) - return -EPERM; - priv = iscsi_if_transport_lookup(iscsi_ptr(ev->transport_handle)); if (!priv) return -EINVAL; @@ -857,8 +854,6 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (!try_module_get(transport->owner)) return -EINVAL; - daemon_pid = NETLINK_CREDS(skb)->pid; - switch (nlh->nlmsg_type) { case ISCSI_UEVENT_CREATE_SESSION: err = iscsi_if_create_session(priv, ev); @@ -934,7 +929,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) /* Get message from skb (based on rtnetlink_rcv_skb). Each message is * processed by iscsi_if_recv_msg. Malformed skbs with wrong length are - * discarded silently. */ + * or invalid creds discarded silently. */ static void iscsi_if_rx(struct sock *sk, int len) { @@ -942,6 +937,12 @@ iscsi_if_rx(struct sock *sk, int len) mutex_lock(&rx_queue_mutex); while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { + if (NETLINK_CREDS(skb)->uid) { + skb_pull(skb, skb->len); + goto free_skb; + } + daemon_pid = NETLINK_CREDS(skb)->pid; + while (skb->len >= NLMSG_SPACE(0)) { int err; uint32_t rlen; @@ -953,10 +954,12 @@ iscsi_if_rx(struct sock *sk, int len) skb->len < nlh->nlmsg_len) { break; } + ev = NLMSG_DATA(nlh); rlen = NLMSG_ALIGN(nlh->nlmsg_len); if (rlen > skb->len) rlen = skb->len; + err = iscsi_if_recv_msg(skb, nlh); if (err) { ev->type = ISCSI_KEVENT_IF_ERROR; @@ -980,6 +983,7 @@ iscsi_if_rx(struct sock *sk, int len) } while (err < 0 && err != -ECONNREFUSED); skb_pull(skb, rlen); } +free_skb: kfree_skb(skb); } mutex_unlock(&rx_queue_mutex); -- cgit v1.2.3 From 1fd459e367657f595ddf192b9a46298e18d4fc13 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 1 Feb 2006 21:07:03 -0600 Subject: [SCSI] iscsi update: rm conn lock >From erezz@voltaire.com: rm conn->lock since it is not used anymore. The dataqueue is protected by the session lock and xmitmutex. Signed-off-by: Mike Christie Signed-off-by: Alex Aizman Signed-off-by: Dmitry Yusupov Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 4 ---- drivers/scsi/iscsi_tcp.h | 1 - 2 files changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index d07d309ac026..0cd78b1d1aaa 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -244,12 +244,10 @@ iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) if (sc->sc_data_direction == DMA_TO_DEVICE) { struct iscsi_data_task *dtask, *n; /* WRITE: cleanup Data-Out's if any */ - spin_lock(&conn->lock); list_for_each_entry_safe(dtask, n, &ctask->dataqueue, item) { list_del(&dtask->item); mempool_free(dtask, ctask->datapool); } - spin_unlock(&conn->lock); } ctask->xmstate = XMSTATE_IDLE; ctask->r2t = NULL; @@ -2453,8 +2451,6 @@ iscsi_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx) conn->data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH; conn->max_recv_dlength = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH; - spin_lock_init(&conn->lock); - /* initialize general xmit PDU commands queue */ conn->xmitqueue = kfifo_alloc(session->cmds_max * sizeof(void*), GFP_KERNEL, NULL); diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h index 6766b817db2d..ba26741ac154 100644 --- a/drivers/scsi/iscsi_tcp.h +++ b/drivers/scsi/iscsi_tcp.h @@ -146,7 +146,6 @@ struct iscsi_conn { struct iscsi_mgmt_task *login_mtask; /* mtask used for login/text */ struct iscsi_mgmt_task *mtask; /* xmit mtask in progress */ struct iscsi_cmd_task *ctask; /* xmit ctask in progress */ - spinlock_t lock; /* FIXME: to be removed */ /* old values for socket callbacks */ void (*old_data_ready)(struct sock *, int); -- cgit v1.2.3 From 351f739e68e97a0316136a5bda145b952d99a989 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 1 Feb 2006 21:07:06 -0600 Subject: [SCSI] iscsi update: set correct state at creation time >From erezz@voltaire.com: We are still in ISCSI_STATE_FREE state at create time. The addition of the first connection puts us in ISCSI_STATE_LOGGED_IN. Signed-off-by: Mike Christie Signed-off-by: Alex Aizman Signed-off-by: Dmitry Yusupov Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 0cd78b1d1aaa..579eecfd186e 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -3267,7 +3267,7 @@ iscsi_session_create(struct scsi_transport_template *scsit, session = iscsi_hostdata(shost->hostdata); memset(session, 0, sizeof(struct iscsi_session)); session->host = shost; - session->state = ISCSI_STATE_LOGGED_IN; + session->state = ISCSI_STATE_FREE; session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX; session->cmds_max = ISCSI_XMIT_CMDS_MAX; session->cmdsn = initial_cmdsn; -- cgit v1.2.3 From b36ae07cb7757bd3eabd13c79844083dccac2f77 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 1 Feb 2006 21:07:09 -0600 Subject: [SCSI] iscsi update: fix mgmt pool err path release >From ogerlitz@voltaire.com: mgmtpool shoild be frees in immdata_alloc_fail label. Signed-off-by: Mike Christie Signed-off-by: Alex Aizman Signed-off-by: Dmitry Yusupov Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 579eecfd186e..ff79e68b347c 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -3316,8 +3316,8 @@ iscsi_session_create(struct scsi_transport_template *scsit, r2tpool_alloc_fail: for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) kfree(session->mgmt_cmds[cmd_i]->data); - iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); immdata_alloc_fail: + iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); mgmtpool_alloc_fail: iscsi_pool_free(&session->cmdpool, (void**)session->cmds); cmdpool_alloc_fail: -- cgit v1.2.3 From 28e5554df63085be3b8bd2aee6ddbc479f0d136e Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 1 Feb 2006 21:07:11 -0600 Subject: [SCSI] iscsi update: use gfp_t Use gfp_t. I accidentally removed this in our last update. Signed-off-by: Mike Christie Signed-off-by: Alex Aizman Signed-off-by: Dmitry Yusupov Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_iscsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 7fb69183c72d..55860d26f999 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -489,7 +489,7 @@ static inline struct list_head *skb_to_lh(struct sk_buff *skb) } static void* -mempool_zone_alloc_skb(unsigned int gfp_mask, void *pool_data) +mempool_zone_alloc_skb(gfp_t gfp_mask, void *pool_data) { struct mempool_zone *zone = pool_data; -- cgit v1.2.3 From b5b81016538cf84a10c80438b7aa750dd375ba93 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 1 Feb 2006 21:07:14 -0600 Subject: [SCSI] iscsi update: rm unused sessions list rm unused sessions list. This patch is last becuase I was not sure if this patchset was going to be applied over the kmalloc2kzalloc one by JesS. If it is then this patch will not apply and can be dropped for now. I will resend later when things setttle down. Signed-off-by: Mike Christie Signed-off-by: Alex Aizman Signed-off-by: Dmitry Yusupov Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_iscsi.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 55860d26f999..71e54a64adca 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -38,10 +38,6 @@ struct iscsi_internal { struct scsi_transport_template t; struct iscsi_transport *iscsi_transport; struct list_head list; - /* - * List of sessions for this transport - */ - struct list_head sessions; /* * based on transport capabilities, at register time we set these * bits to tell the transport class it wants attributes displayed @@ -1126,7 +1122,6 @@ iscsi_register_transport(struct iscsi_transport *tt) return NULL; memset(priv, 0, sizeof(*priv)); INIT_LIST_HEAD(&priv->list); - INIT_LIST_HEAD(&priv->sessions); priv->iscsi_transport = tt; priv->cdev.class = &iscsi_transport_class; -- cgit v1.2.3 From 096f7a2a094af3007937d6fd21560e28dca0994d Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Thu, 2 Feb 2006 17:19:30 -0700 Subject: [SCSI] fusion - mptctl - MPTCOMMAND - adding function types. This adds support for new function types in the existing MPTCOMMAND ioctl. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptctl.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers') diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index bdf709987982..70a812a2514d 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -1817,6 +1817,8 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) case MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR: case MPI_FUNCTION_FW_DOWNLOAD: case MPI_FUNCTION_FC_PRIMITIVE_SEND: + case MPI_FUNCTION_TOOLBOX: + case MPI_FUNCTION_SAS_IO_UNIT_CONTROL: break; case MPI_FUNCTION_SCSI_IO_REQUEST: @@ -1888,6 +1890,25 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) } break; + case MPI_FUNCTION_SMP_PASSTHROUGH: + /* Check mf->PassthruFlags to determine if + * transfer is ImmediateMode or not. + * Immediate mode returns data in the ReplyFrame. + * Else, we are sending request and response data + * in two SGLs at the end of the mf. + */ + break; + + case MPI_FUNCTION_SATA_PASSTHROUGH: + if (!ioc->sh) { + printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + "SCSI driver is not loaded. \n", + __FILE__, __LINE__); + rc = -EFAULT; + goto done_free_mem; + } + break; + case MPI_FUNCTION_RAID_ACTION: /* Just add a SGE */ -- cgit v1.2.3 From 9cc1cfbc67d77164f5b612fcf833460eca4d81e9 Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Thu, 2 Feb 2006 17:19:33 -0700 Subject: [SCSI] fusion - mptctl - adding support for bus_type=SAS Add bus_type recognization in ioctl path for SAS. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptctl.c | 8 +++++--- drivers/message/fusion/mptctl.h | 4 +++- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 70a812a2514d..1a1bc66c8e9c 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -1145,7 +1145,9 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) /* Fill in the data and return the structure to the calling * program */ - if (ioc->bus_type == FC) + if (ioc->bus_type == SAS) + karg->adapterType = MPT_IOCTL_INTERFACE_SAS; + else if (ioc->bus_type == FC) karg->adapterType = MPT_IOCTL_INTERFACE_FC; else karg->adapterType = MPT_IOCTL_INTERFACE_SCSI; @@ -2391,7 +2393,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) karg.base_io_addr = pci_resource_start(pdev, 0); - if (ioc->bus_type == FC) + if ((ioc->bus_type == SAS) || (ioc->bus_type == FC)) karg.bus_phys_width = HP_BUS_WIDTH_UNK; else karg.bus_phys_width = HP_BUS_WIDTH_16; @@ -2480,7 +2482,7 @@ mptctl_hp_targetinfo(unsigned long arg) /* There is nothing to do for FCP parts. */ - if (ioc->bus_type == FC) + if ((ioc->bus_type == SAS) || (ioc->bus_type == FC)) return 0; if ((ioc->spi_data.sdp0length == 0) || (ioc->sh == NULL)) diff --git a/drivers/message/fusion/mptctl.h b/drivers/message/fusion/mptctl.h index 518996e03481..a2f8a97992e6 100644 --- a/drivers/message/fusion/mptctl.h +++ b/drivers/message/fusion/mptctl.h @@ -169,8 +169,10 @@ struct mpt_ioctl_pci_info2 { * Read only. * Data starts at offset 0xC */ -#define MPT_IOCTL_INTERFACE_FC (0x01) #define MPT_IOCTL_INTERFACE_SCSI (0x00) +#define MPT_IOCTL_INTERFACE_FC (0x01) +#define MPT_IOCTL_INTERFACE_FC_IP (0x02) +#define MPT_IOCTL_INTERFACE_SAS (0x03) #define MPT_IOCTL_VERSION_LENGTH (32) struct mpt_ioctl_iocinfo { -- cgit v1.2.3 From 86a7dcaae9c67a344e51190734b98684072d181c Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Thu, 2 Feb 2006 17:19:37 -0700 Subject: [SCSI] fusion - mtctl - change to wait_event_timeout Change from using wait_event_interruptible_timeout to wait_event_timeout. Also delete white space and duplicate line of code. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptctl.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 1a1bc66c8e9c..8e2369ff3322 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -385,18 +385,18 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl) } /* Now wait for the command to complete */ - ii = wait_event_interruptible_timeout(mptctl_wait, + ii = wait_event_timeout(mptctl_wait, ioctl->wait_done == 1, HZ*5 /* 5 second timeout */); if(ii <=0 && (ioctl->wait_done != 1 )) { + mpt_free_msg_frame(hd->ioc, mf); ioctl->wait_done = 0; retval = -1; /* return failure */ } mptctl_bus_reset_done: - mpt_free_msg_frame(hd->ioc, mf); mptctl_free_tm_flags(ioctl->ioc); return retval; } @@ -807,7 +807,7 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) mpt_put_msg_frame(mptctl_id, iocp, mf); /* Now wait for the command to complete */ - ret = wait_event_interruptible_timeout(mptctl_wait, + ret = wait_event_timeout(mptctl_wait, iocp->ioctl->wait_done == 1, HZ*60); @@ -1172,12 +1172,11 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) karg->pciInfo.u.bits.deviceNumber = PCI_SLOT( pdev->devfn ); karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn ); } else if (cim_rev == 2) { - /* Get the PCI bus, device, function and segment ID numbers + /* Get the PCI bus, device, function and segment ID numbers for the IOC */ karg->pciInfo.u.bits.busNumber = pdev->bus->number; karg->pciInfo.u.bits.deviceNumber = PCI_SLOT( pdev->devfn ); karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn ); - karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn ); karg->pciInfo.segmentID = pci_domain_nr(pdev->bus); } @@ -2153,7 +2152,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) /* Now wait for the command to complete */ timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT; - timeout = wait_event_interruptible_timeout(mptctl_wait, + timeout = wait_event_timeout(mptctl_wait, ioc->ioctl->wait_done == 1, HZ*timeout); -- cgit v1.2.3 From 5b5ef4f617f1706a23b0433d89a9c02ceb0980a5 Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Thu, 2 Feb 2006 17:19:40 -0700 Subject: [SCSI] fusion - mptctl - Event Log Fix Use the hard coded value MPTCTL_EVENT_LOG_SIZE to fix bug where in certain cases, the ioc->eventLogSize was initialized. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.c | 2 +- drivers/message/fusion/mptctl.c | 5 ++--- drivers/message/fusion/mptscsih.c | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 9a2c7605d49c..a3751d86216e 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -6142,7 +6142,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply if (ioc->events && (ioc->eventTypes & ( 1 << event))) { int idx; - idx = ioc->eventContext % ioc->eventLogSize; + idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE; ioc->events[idx].event = event; ioc->events[idx].eventContext = ioc->eventContext; diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 8e2369ff3322..b603fb8e604b 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -1501,7 +1501,7 @@ mptctl_eventquery (unsigned long arg) return -ENODEV; } - karg.eventEntries = ioc->eventLogSize; + karg.eventEntries = MPTCTL_EVENT_LOG_SIZE; karg.eventTypes = ioc->eventTypes; /* Copy the data from kernel memory to user memory @@ -1551,7 +1551,6 @@ mptctl_eventenable (unsigned long arg) memset(ioc->events, 0, sz); ioc->alloc_total += sz; - ioc->eventLogSize = MPTCTL_EVENT_LOG_SIZE; ioc->eventContext = 0; } @@ -1591,7 +1590,7 @@ mptctl_eventreport (unsigned long arg) maxEvents = numBytes/sizeof(MPT_IOCTL_EVENTS); - max = ioc->eventLogSize < maxEvents ? ioc->eventLogSize : maxEvents; + max = MPTCTL_EVENT_LOG_SIZE < maxEvents ? MPTCTL_EVENT_LOG_SIZE : maxEvents; /* If fewer than 1 event is requested, there must have * been some type of error. diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 05789e505464..4fee6befc93d 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -2489,7 +2489,7 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR int idx; MPT_ADAPTER *ioc = hd->ioc; - idx = ioc->eventContext % ioc->eventLogSize; + idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE; ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE; ioc->events[idx].eventContext = ioc->eventContext; -- cgit v1.2.3 From 5f07e2499d629045f7f8a60a5b442792f08732cb Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Thu, 2 Feb 2006 17:19:44 -0700 Subject: [SCSI] fusion - mptctl -sense width fix Bug fix for correctly setting sense width for the MPTCOMMAND ioctl. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptctl.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index b603fb8e604b..be5fcd8db63b 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -1839,7 +1839,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) goto done_free_mem; } - pScsiReq->MsgFlags = mpt_msg_flags(); + pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH; + pScsiReq->MsgFlags |= mpt_msg_flags(); + /* verify that app has not requested * more sense data than driver @@ -1921,7 +1923,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) int scsidir = MPI_SCSIIO_CONTROL_READ; int dataSize; - pScsiReq->MsgFlags = mpt_msg_flags(); + pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH; + pScsiReq->MsgFlags |= mpt_msg_flags(); + /* verify that app has not requested * more sense data than driver -- cgit v1.2.3 From 592f9c2fc9725b922ba8c4b1d67318ea4a301b59 Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Thu, 2 Feb 2006 17:19:47 -0700 Subject: [SCSI] fusion - mptctl - backplane istwi fix Moving the toolbox call from mptbase.c, over to mptctl.c, and using the mptctl infastructure to issue the call. The existing code is hanging on certain HP platforms when this ioctl is issued, and this patch fix's that. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.c | 113 +-------------------------------------- drivers/message/fusion/mptbase.h | 1 - drivers/message/fusion/mptctl.c | 74 ++++++++++++++++++++----- 3 files changed, 63 insertions(+), 125 deletions(-) (limited to 'drivers') diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index a3751d86216e..642a61b6d0a4 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -452,8 +452,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) } else if (func == MPI_FUNCTION_EVENT_ACK) { dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, EventAck reply received\n", ioc->name)); - } else if (func == MPI_FUNCTION_CONFIG || - func == MPI_FUNCTION_TOOLBOX) { + } else if (func == MPI_FUNCTION_CONFIG) { CONFIGPARMS *pCfg; unsigned long flags; @@ -5326,115 +5325,6 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) return rc; } -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * mpt_toolbox - Generic function to issue toolbox message - * @ioc - Pointer to an adapter structure - * @cfg - Pointer to a toolbox structure. Struct contains - * action, page address, direction, physical address - * and pointer to a configuration page header - * Page header is updated. - * - * Returns 0 for success - * -EPERM if not allowed due to ISR context - * -EAGAIN if no msg frames currently available - * -EFAULT for non-successful reply or no reply (timeout) - */ -int -mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) -{ - ToolboxIstwiReadWriteRequest_t *pReq; - MPT_FRAME_HDR *mf; - struct pci_dev *pdev; - unsigned long flags; - int rc; - u32 flagsLength; - int in_isr; - - /* Prevent calling wait_event() (below), if caller happens - * to be in ISR context, because that is fatal! - */ - in_isr = in_interrupt(); - if (in_isr) { - dcprintk((MYIOC_s_WARN_FMT "toobox request not allowed in ISR context!\n", - ioc->name)); - return -EPERM; - } - - /* Get and Populate a free Frame - */ - if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { - dcprintk((MYIOC_s_WARN_FMT "mpt_toolbox: no msg frames!\n", - ioc->name)); - return -EAGAIN; - } - pReq = (ToolboxIstwiReadWriteRequest_t *)mf; - pReq->Tool = pCfg->action; - pReq->Reserved = 0; - pReq->ChainOffset = 0; - pReq->Function = MPI_FUNCTION_TOOLBOX; - pReq->Reserved1 = 0; - pReq->Reserved2 = 0; - pReq->MsgFlags = 0; - pReq->Flags = pCfg->dir; - pReq->BusNum = 0; - pReq->Reserved3 = 0; - pReq->NumAddressBytes = 0x01; - pReq->Reserved4 = 0; - pReq->DataLength = cpu_to_le16(0x04); - pdev = ioc->pcidev; - if (pdev->devfn & 1) - pReq->DeviceAddr = 0xB2; - else - pReq->DeviceAddr = 0xB0; - pReq->Addr1 = 0; - pReq->Addr2 = 0; - pReq->Addr3 = 0; - pReq->Reserved5 = 0; - - /* Add a SGE to the config request. - */ - - flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | 4; - - mpt_add_sge((char *)&pReq->SGL, flagsLength, pCfg->physAddr); - - dcprintk((MYIOC_s_INFO_FMT "Sending Toolbox request, Tool=%x\n", - ioc->name, pReq->Tool)); - - /* Append pCfg pointer to end of mf - */ - *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg; - - /* Initalize the timer - */ - init_timer(&pCfg->timer); - pCfg->timer.data = (unsigned long) ioc; - pCfg->timer.function = mpt_timer_expired; - pCfg->wait_done = 0; - - /* Set the timer; ensure 10 second minimum */ - if (pCfg->timeout < 10) - pCfg->timer.expires = jiffies + HZ*10; - else - pCfg->timer.expires = jiffies + HZ*pCfg->timeout; - - /* Add to end of Q, set timer and then issue this command */ - spin_lock_irqsave(&ioc->FreeQlock, flags); - list_add_tail(&pCfg->linkage, &ioc->configQ); - spin_unlock_irqrestore(&ioc->FreeQlock, flags); - - add_timer(&pCfg->timer); - mpt_put_msg_frame(mpt_base_index, ioc, mf); - wait_event(mpt_waitq, pCfg->wait_done); - - /* mf has been freed - do not access */ - - rc = pCfg->status; - - return rc; -} - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * mpt_timer_expired - Call back for timer process. @@ -6540,7 +6430,6 @@ EXPORT_SYMBOL(mpt_lan_index); EXPORT_SYMBOL(mpt_stm_index); EXPORT_SYMBOL(mpt_HardResetHandler); EXPORT_SYMBOL(mpt_config); -EXPORT_SYMBOL(mpt_toolbox); EXPORT_SYMBOL(mpt_findImVolumes); EXPORT_SYMBOL(mpt_read_ioc_pg_3); EXPORT_SYMBOL(mpt_alloc_fw_memory); diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index ea2649ecad1f..2e5377309cea 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -1026,7 +1026,6 @@ extern u32 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked); extern void mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buf, int *size, int len, int showlan); extern int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag); extern int mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *cfg); -extern int mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *cfg); extern void mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size); extern void mpt_free_fw_memory(MPT_ADAPTER *ioc); extern int mpt_findImVolumes(MPT_ADAPTER *ioc); diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index be5fcd8db63b..2df3b8756545 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -2271,13 +2271,16 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) hp_host_info_t __user *uarg = (void __user *) arg; MPT_ADAPTER *ioc; struct pci_dev *pdev; - char *pbuf; + char *pbuf=NULL; dma_addr_t buf_dma; hp_host_info_t karg; CONFIGPARMS cfg; ConfigPageHeader_t hdr; int iocnum; int rc, cim_rev; + ToolboxIstwiReadWriteRequest_t *IstwiRWRequest; + MPT_FRAME_HDR *mf = NULL; + MPIHeader_t *mpi_hdr; dctlprintk((": mptctl_hp_hostinfo called.\n")); /* Reset long to int. Should affect IA64 and SPARC only @@ -2413,20 +2416,67 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) } } - cfg.pageAddr = 0; - cfg.action = MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL; - cfg.dir = MPI_TB_ISTWI_FLAGS_READ; - cfg.timeout = 10; + /* + * Gather ISTWI(Industry Standard Two Wire Interface) Data + */ + if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) { + dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n", + ioc->name,__FUNCTION__)); + goto out; + } + + IstwiRWRequest = (ToolboxIstwiReadWriteRequest_t *)mf; + mpi_hdr = (MPIHeader_t *) mf; + memset(IstwiRWRequest,0,sizeof(ToolboxIstwiReadWriteRequest_t)); + IstwiRWRequest->Function = MPI_FUNCTION_TOOLBOX; + IstwiRWRequest->Tool = MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL; + IstwiRWRequest->MsgContext = mpi_hdr->MsgContext; + IstwiRWRequest->Flags = MPI_TB_ISTWI_FLAGS_READ; + IstwiRWRequest->NumAddressBytes = 0x01; + IstwiRWRequest->DataLength = cpu_to_le16(0x04); + if (pdev->devfn & 1) + IstwiRWRequest->DeviceAddr = 0xB2; + else + IstwiRWRequest->DeviceAddr = 0xB0; + pbuf = pci_alloc_consistent(ioc->pcidev, 4, &buf_dma); - if (pbuf) { - cfg.physAddr = buf_dma; - if ((mpt_toolbox(ioc, &cfg)) == 0) { - karg.rsvd = *(u32 *)pbuf; - } - pci_free_consistent(ioc->pcidev, 4, pbuf, buf_dma); - pbuf = NULL; + if (!pbuf) + goto out; + mpt_add_sge((char *)&IstwiRWRequest->SGL, + (MPT_SGE_FLAGS_SSIMPLE_READ|4), buf_dma); + + ioc->ioctl->wait_done = 0; + mpt_put_msg_frame(mptctl_id, ioc, mf); + + rc = wait_event_timeout(mptctl_wait, + ioc->ioctl->wait_done == 1, + HZ*MPT_IOCTL_DEFAULT_TIMEOUT /* 10 sec */); + + if(rc <=0 && (ioc->ioctl->wait_done != 1 )) { + /* + * Now we need to reset the board + */ + mpt_free_msg_frame(ioc, mf); + mptctl_timeout_expired(ioc->ioctl); + goto out; } + /* + *ISTWI Data Definition + * pbuf[0] = FW_VERSION = 0x4 + * pbuf[1] = Bay Count = 6 or 4 or 2, depending on + * the config, you should be seeing one out of these three values + * pbuf[2] = Drive Installed Map = bit pattern depend on which + * bays have drives in them + * pbuf[3] = Checksum (0x100 = (byte0 + byte2 + byte3) + */ + if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) + karg.rsvd = *(u32 *)pbuf; + + out: + if (pbuf) + pci_free_consistent(ioc->pcidev, 4, pbuf, buf_dma); + /* Copy the data from kernel memory to user memory */ if (copy_to_user((char __user *)arg, &karg, sizeof(hp_host_info_t))) { -- cgit v1.2.3 From 946cbf040adb9db05bb895a4b629537fd2d03b0e Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Thu, 2 Feb 2006 17:19:50 -0700 Subject: [SCSI] fusion - mptctl -firmware download fix Fix's firmware download ioctl to work with SAS. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptctl.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 2df3b8756545..fe10cc0fe18e 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -674,22 +674,23 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) u16 iocstat; pFWDownloadReply_t ReplyMsg = NULL; - dctlprintk((KERN_INFO "mptctl_do_fwdl called. mptctl_id = %xh.\n", mptctl_id)); + dctlprintk(("mptctl_do_fwdl called. mptctl_id = %xh.\n", mptctl_id)); - dctlprintk((KERN_INFO "DbG: kfwdl.bufp = %p\n", ufwbuf)); - dctlprintk((KERN_INFO "DbG: kfwdl.fwlen = %d\n", (int)fwlen)); - dctlprintk((KERN_INFO "DbG: kfwdl.ioc = %04xh\n", ioc)); + dctlprintk(("DbG: kfwdl.bufp = %p\n", ufwbuf)); + dctlprintk(("DbG: kfwdl.fwlen = %d\n", (int)fwlen)); + dctlprintk(("DbG: kfwdl.ioc = %04xh\n", ioc)); - if ((ioc = mpt_verify_adapter(ioc, &iocp)) < 0) { - dctlprintk(("%s@%d::_ioctl_fwdl - ioc%d not found!\n", - __FILE__, __LINE__, ioc)); + if (mpt_verify_adapter(ioc, &iocp) < 0) { + dctlprintk(("ioctl_fwdl - ioc%d not found!\n", + ioc)); return -ENODEV; /* (-6) No such device or address */ - } + } else { - /* Valid device. Get a message frame and construct the FW download message. - */ - if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL) - return -EAGAIN; + /* Valid device. Get a message frame and construct the FW download message. + */ + if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL) + return -EAGAIN; + } dlmsg = (FWDownload_t*) mf; ptsge = (FWDownloadTCSGE_t *) &dlmsg->SGL; sgOut = (char *) (ptsge + 1); @@ -702,7 +703,11 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) dlmsg->ChainOffset = 0; dlmsg->Function = MPI_FUNCTION_FW_DOWNLOAD; dlmsg->Reserved1[0] = dlmsg->Reserved1[1] = dlmsg->Reserved1[2] = 0; - dlmsg->MsgFlags = 0; + if (iocp->facts.MsgVersion >= MPI_VERSION_01_05) + dlmsg->MsgFlags = MPI_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT; + else + dlmsg->MsgFlags = 0; + /* Set up the Transaction SGE. */ @@ -754,7 +759,7 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) goto fwdl_out; } - dctlprintk((KERN_INFO "DbG: sgl buffer = %p, sgfrags = %d\n", sgl, numfrags)); + dctlprintk(("DbG: sgl buffer = %p, sgfrags = %d\n", sgl, numfrags)); /* * Parse SG list, copying sgl itself, @@ -803,7 +808,7 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) /* * Finally, perform firmware download. */ - iocp->ioctl->wait_done = 0; + ReplyMsg = NULL; mpt_put_msg_frame(mptctl_id, iocp, mf); /* Now wait for the command to complete */ -- cgit v1.2.3 From ea5a7a82f9d2d8a81f8fa541c34a12b43d390f61 Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Thu, 2 Feb 2006 17:20:01 -0700 Subject: [SCSI] fusion - mptctl -adding asyn event notification support Adding aen support. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.h | 1 + drivers/message/fusion/mptctl.c | 79 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) (limited to 'drivers') diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 2e5377309cea..723d54300953 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -616,6 +616,7 @@ typedef struct _MPT_ADAPTER * increments by 32 bytes */ int errata_flag_1064; + int aen_event_read_flag; /* flag to indicate event log was read*/ u8 FirstWhoInit; u8 upload_fw; /* If set, do a fw upload */ u8 reload_fw; /* Force a FW Reload on next reset */ diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index fe10cc0fe18e..9b64e07400da 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -136,6 +136,12 @@ static void mptctl_free_tm_flags(MPT_ADAPTER *ioc); */ static int mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase); +/* + * Event Handler function + */ +static int mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); +struct fasync_struct *async_queue=NULL; + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * Scatter gather list (SGL) sizes and limits... @@ -471,6 +477,69 @@ mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) return 1; } +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* ASYNC Event Notification Support */ +static int +mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) +{ + u8 event; + + event = le32_to_cpu(pEvReply->Event) & 0xFF; + + dctlprintk(("%s() called\n", __FUNCTION__)); + if(async_queue == NULL) + return 1; + + /* Raise SIGIO for persistent events. + * TODO - this define is not in MPI spec yet, + * but they plan to set it to 0x21 + */ + if (event == 0x21 ) { + ioc->aen_event_read_flag=1; + dctlprintk(("Raised SIGIO to application\n")); + devtprintk(("Raised SIGIO to application\n")); + kill_fasync(&async_queue, SIGIO, POLL_IN); + return 1; + } + + /* This flag is set after SIGIO was raised, and + * remains set until the application has read + * the event log via ioctl=MPTEVENTREPORT + */ + if(ioc->aen_event_read_flag) + return 1; + + /* Signal only for the events that are + * requested for by the application + */ + if (ioc->events && (ioc->eventTypes & ( 1 << event))) { + ioc->aen_event_read_flag=1; + dctlprintk(("Raised SIGIO to application\n")); + devtprintk(("Raised SIGIO to application\n")); + kill_fasync(&async_queue, SIGIO, POLL_IN); + } + return 1; +} + +static int +mptctl_fasync(int fd, struct file *filep, int mode) +{ + MPT_ADAPTER *ioc; + + list_for_each_entry(ioc, &ioc_list, list) + ioc->aen_event_read_flag=0; + + dctlprintk(("%s() called\n", __FUNCTION__)); + return fasync_helper(fd, filep, mode, &async_queue); +} + +static int +mptctl_release(struct inode *inode, struct file *filep) +{ + dctlprintk(("%s() called\n", __FUNCTION__)); + return fasync_helper(-1, filep, 0, &async_queue); +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * MPT ioctl handler @@ -1603,6 +1672,9 @@ mptctl_eventreport (unsigned long arg) if ((max < 1) || !ioc->events) return -ENODATA; + /* reset this flag so SIGIO can restart */ + ioc->aen_event_read_flag=0; + /* Copy the data from kernel memory to user memory */ numBytes = max * sizeof(MPT_IOCTL_EVENTS); @@ -2649,6 +2721,8 @@ mptctl_hp_targetinfo(unsigned long arg) static struct file_operations mptctl_fops = { .owner = THIS_MODULE, .llseek = no_llseek, + .release = mptctl_release, + .fasync = mptctl_fasync, .unlocked_ioctl = mptctl_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = compat_mpctl_ioctl, @@ -2893,6 +2967,11 @@ static int __init mptctl_init(void) /* FIXME! */ } + if (mpt_event_register(mptctl_id, mptctl_event_process) == 0) { + devtprintk((KERN_INFO MYNAM + ": Registered for IOC event notifications\n")); + } + return 0; out_fail: -- cgit v1.2.3 From 122da30223c06cee181044af6d32e88b256d10df Mon Sep 17 00:00:00 2001 From: Joshua Giles Date: Fri, 3 Feb 2006 15:34:17 -0800 Subject: [SCSI] megaraid_sas: register 16 byte CDB capability This patch properly registers the 16 byte command length capability of the megaraid_sas controlled hardware with the scsi midlayer. All megaraid_sas hardware supports 16 byte CDB's. Signed-off-by: Joshua Giles Signed-off-by: Sumant Patro Signed-off-by: James Bottomley --- drivers/scsi/megaraid/megaraid_sas.c | 3 ++- drivers/scsi/megaraid/megaraid_sas.h | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index a487f414960e..0b738243782e 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -10,7 +10,7 @@ * 2 of the License, or (at your option) any later version. * * FILE : megaraid_sas.c - * Version : v00.00.02.02 + * Version : v00.00.02.04 * * Authors: * Sreenivas Bagalkote @@ -1983,6 +1983,7 @@ static int megasas_io_attach(struct megasas_instance *instance) host->max_channel = MEGASAS_MAX_CHANNELS - 1; host->max_id = MEGASAS_MAX_DEV_PER_CHANNEL; host->max_lun = MEGASAS_MAX_LUN; + host->max_cmd_len = 16; /* * Notify the mid-layer about the new controller diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index d6d166c0663f..917326f3770e 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -18,9 +18,9 @@ /** * MegaRAID SAS Driver meta data */ -#define MEGASAS_VERSION "00.00.02.02" -#define MEGASAS_RELDATE "Jan 23, 2006" -#define MEGASAS_EXT_VERSION "Mon Jan 23 14:09:01 PST 2006" +#define MEGASAS_VERSION "00.00.02.04" +#define MEGASAS_RELDATE "Feb 03, 2006" +#define MEGASAS_EXT_VERSION "Fri Feb 03 14:16:25 PST 2006" /* * ===================================== * MegaRAID SAS MFI firmware definitions -- cgit v1.2.3 From f9876f0b67c3f0b04ee2167602df54e7ae139ad7 Mon Sep 17 00:00:00 2001 From: Sumant Patro Date: Fri, 3 Feb 2006 15:34:35 -0800 Subject: [SCSI] megaraid_sas: support for 1078 type controller added This patch adds support for 1078 type controller (device id : 0x60). Signed-off-by: Sumant Patro Signed-off-by: James Bottomley --- drivers/scsi/megaraid/megaraid_sas.c | 98 +++++++++++++++++++++++++++++++++++- drivers/scsi/megaraid/megaraid_sas.h | 49 +++++++++++------- 2 files changed, 129 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 0b738243782e..7de267e14458 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -59,6 +59,12 @@ static struct pci_device_id megasas_pci_table[] = { PCI_ANY_ID, PCI_ANY_ID, }, + { + PCI_VENDOR_ID_LSI_LOGIC, + PCI_DEVICE_ID_LSI_SAS1078R, // ppc IOP + PCI_ANY_ID, + PCI_ANY_ID, + }, { PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5, // xscale IOP @@ -198,6 +204,86 @@ static struct megasas_instance_template megasas_instance_template_xscale = { * to xscale (deviceid : 1064R, PERC5) controllers */ +/** +* The following functions are defined for ppc (deviceid : 0x60) +* controllers +*/ + +/** + * megasas_enable_intr_ppc - Enables interrupts + * @regs: MFI register set + */ +static inline void +megasas_enable_intr_ppc(struct megasas_register_set __iomem * regs) +{ + writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear); + + writel(~0x80000004, &(regs)->outbound_intr_mask); + + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_mask); +} + +/** + * megasas_read_fw_status_reg_ppc - returns the current FW status value + * @regs: MFI register set + */ +static u32 +megasas_read_fw_status_reg_ppc(struct megasas_register_set __iomem * regs) +{ + return readl(&(regs)->outbound_scratch_pad); +} + +/** + * megasas_clear_interrupt_ppc - Check & clear interrupt + * @regs: MFI register set + */ +static int +megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs) +{ + u32 status; + /* + * Check if it is our interrupt + */ + status = readl(®s->outbound_intr_status); + + if (!(status & MFI_REPLY_1078_MESSAGE_INTERRUPT)) { + return 1; + } + + /* + * Clear the interrupt by writing back the same value + */ + writel(status, ®s->outbound_doorbell_clear); + + return 0; +} +/** + * megasas_fire_cmd_ppc - Sends command to the FW + * @frame_phys_addr : Physical address of cmd + * @frame_count : Number of frames for the command + * @regs : MFI register set + */ +static inline void +megasas_fire_cmd_ppc(dma_addr_t frame_phys_addr, u32 frame_count, struct megasas_register_set __iomem *regs) +{ + writel((frame_phys_addr | (frame_count<<1))|1, + &(regs)->inbound_queue_port); +} + +static struct megasas_instance_template megasas_instance_template_ppc = { + + .fire_cmd = megasas_fire_cmd_ppc, + .enable_intr = megasas_enable_intr_ppc, + .clear_intr = megasas_clear_intr_ppc, + .read_fw_status_reg = megasas_read_fw_status_reg_ppc, +}; + +/** +* This is the end of set of functions & definitions +* specific to ppc (deviceid : 0x60) controllers +*/ + /** * megasas_disable_intr - Disables interrupts * @regs: MFI register set @@ -1607,7 +1693,17 @@ static int megasas_init_mfi(struct megasas_instance *instance) reg_set = instance->reg_set; - instance->instancet = &megasas_instance_template_xscale; + switch(instance->pdev->device) + { + case PCI_DEVICE_ID_LSI_SAS1078R: + instance->instancet = &megasas_instance_template_ppc; + break; + case PCI_DEVICE_ID_LSI_SAS1064R: + case PCI_DEVICE_ID_DELL_PERC5: + default: + instance->instancet = &megasas_instance_template_xscale; + break; + } /* * We expect the FW state to be READY diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 917326f3770e..89639f0c38ef 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -20,7 +20,7 @@ */ #define MEGASAS_VERSION "00.00.02.04" #define MEGASAS_RELDATE "Feb 03, 2006" -#define MEGASAS_EXT_VERSION "Fri Feb 03 14:16:25 PST 2006" +#define MEGASAS_EXT_VERSION "Fri Feb 03 14:31:44 PST 2006" /* * ===================================== * MegaRAID SAS MFI firmware definitions @@ -553,31 +553,46 @@ struct megasas_ctrl_info { #define MFI_OB_INTR_STATUS_MASK 0x00000002 #define MFI_POLL_TIMEOUT_SECS 10 +#define MFI_REPLY_1078_MESSAGE_INTERRUPT 0x80000000 +#define PCI_DEVICE_ID_LSI_SAS1078R 0x00000060 + struct megasas_register_set { + u32 reserved_0[4]; /*0000h*/ - u32 reserved_0[4]; /*0000h */ + u32 inbound_msg_0; /*0010h*/ + u32 inbound_msg_1; /*0014h*/ + u32 outbound_msg_0; /*0018h*/ + u32 outbound_msg_1; /*001Ch*/ - u32 inbound_msg_0; /*0010h */ - u32 inbound_msg_1; /*0014h */ - u32 outbound_msg_0; /*0018h */ - u32 outbound_msg_1; /*001Ch */ + u32 inbound_doorbell; /*0020h*/ + u32 inbound_intr_status; /*0024h*/ + u32 inbound_intr_mask; /*0028h*/ - u32 inbound_doorbell; /*0020h */ - u32 inbound_intr_status; /*0024h */ - u32 inbound_intr_mask; /*0028h */ + u32 outbound_doorbell; /*002Ch*/ + u32 outbound_intr_status; /*0030h*/ + u32 outbound_intr_mask; /*0034h*/ - u32 outbound_doorbell; /*002Ch */ - u32 outbound_intr_status; /*0030h */ - u32 outbound_intr_mask; /*0034h */ + u32 reserved_1[2]; /*0038h*/ - u32 reserved_1[2]; /*0038h */ + u32 inbound_queue_port; /*0040h*/ + u32 outbound_queue_port; /*0044h*/ - u32 inbound_queue_port; /*0040h */ - u32 outbound_queue_port; /*0044h */ + u32 reserved_2[22]; /*0048h*/ - u32 reserved_2; /*004Ch */ + u32 outbound_doorbell_clear; /*00A0h*/ - u32 index_registers[1004]; /*0050h */ + u32 reserved_3[3]; /*00A4h*/ + + u32 outbound_scratch_pad ; /*00B0h*/ + + u32 reserved_4[3]; /*00B4h*/ + + u32 inbound_low_queue_port ; /*00C0h*/ + + u32 inbound_high_queue_port ; /*00C4h*/ + + u32 reserved_5; /*00C8h*/ + u32 index_registers[820]; /*00CCh*/ } __attribute__ ((packed)); -- cgit v1.2.3 From 40cdc840dc337cb17d81bcf028b40834e78c1038 Mon Sep 17 00:00:00 2001 From: Jenx Axboe Date: Sun, 5 Feb 2006 16:36:23 +0100 Subject: [SCSI] gdth: don't map zero-length requests Don't map zero-length requests in gdth, zome architectures don't like that in their dma mapping routines. [ I'm pretty sure Jens posted this before, but for some reason it got forgotten --hch ] Signed-off-by: James Bottomley --- drivers/scsi/gdth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index bd3ffdf6c800..62e3cda859af 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -2816,7 +2816,7 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive) } #endif - } else { + } else if (scp->request_bufflen) { scp->SCp.Status = GDTH_MAP_SINGLE; scp->SCp.Message = (read_write == 1 ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); -- cgit v1.2.3 From 62288f105b3cad0b8643526d2a41b5503d0a1476 Mon Sep 17 00:00:00 2001 From: adam radford Date: Sun, 5 Feb 2006 14:51:43 -0800 Subject: [SCSI] 3ware 9000 driver >4GB memory fix The attached patch fixes a bug in the 3ware 9000 series driver: - Fix use_sg == 0 mapping on systems with 4GB or higher. This fixes REPORT_LUNS (0xa0) failing with 3ware 9000 controllers on systems with lots of ram, mentioned in bugzilla # 6009: http://bugzilla.kernel.org/show_bug.cgi?id=6009 Signed-off-by: Adam Radford Signed-off-by: James Bottomley --- drivers/scsi/3w-9xxx.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index 31c497542272..d9152d02088c 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -61,6 +61,7 @@ Add support for embedded firmware error strings. 2.26.02.003 - Correctly handle single sgl's with use_sg=1. 2.26.02.004 - Add support for 9550SX controllers. + 2.26.02.005 - Fix use_sg == 0 mapping on systems with 4GB or higher. */ #include @@ -84,7 +85,7 @@ #include "3w-9xxx.h" /* Globals */ -#define TW_DRIVER_VERSION "2.26.02.004" +#define TW_DRIVER_VERSION "2.26.02.005" static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT]; static unsigned int twa_device_extension_count; static int twa_major = -1; @@ -1408,7 +1409,7 @@ static dma_addr_t twa_map_scsi_single_data(TW_Device_Extension *tw_dev, int requ dma_addr_t mapping; struct scsi_cmnd *cmd = tw_dev->srb[request_id]; struct pci_dev *pdev = tw_dev->tw_pci_dev; - int retval = 0; + dma_addr_t retval = 0; if (cmd->request_bufflen == 0) { retval = 0; @@ -1798,7 +1799,7 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, int i, sg_count; struct scsi_cmnd *srb = NULL; struct scatterlist *sglist = NULL; - u32 buffaddr = 0x0; + dma_addr_t buffaddr = 0x0; int retval = 1; if (tw_dev->srb[request_id]) { -- cgit v1.2.3 From 387f96b4d9391bf3ce6928fb9cd90c9c7df37291 Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Tue, 7 Feb 2006 08:45:45 -0800 Subject: [PATCH] qla2xxx: Close window on race between rport removal and fcport transition. Fcport visibility is recognized during interrupt time, but, rport removal can only occur during a process (sleeping)-context. Return a DID_IMM_RETRY status for commands submitted within this window to insure I/Os do not prematurely run-out of retries. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_os.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 495ccbc7f8cb..9b5a10ac3e25 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -366,6 +366,12 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) goto qc_fail_command; } + /* Close window on fcport/rport state-transitioning. */ + if (!*(fc_port_t **)rport->dd_data) { + cmd->result = DID_IMM_RETRY << 16; + goto qc_fail_command; + } + if (atomic_read(&fcport->state) != FCS_ONLINE) { if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD || atomic_read(&ha->loop_state) == LOOP_DEAD) { @@ -421,6 +427,12 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) goto qc24_fail_command; } + /* Close window on fcport/rport state-transitioning. */ + if (!*(fc_port_t **)rport->dd_data) { + cmd->result = DID_IMM_RETRY << 16; + goto qc24_fail_command; + } + if (atomic_read(&fcport->state) != FCS_ONLINE) { if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD || atomic_read(&ha->loop_state) == LOOP_DEAD) { @@ -1675,11 +1687,13 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *ha, fc_port_t *fcport, spin_lock_irqsave(&fcport->rport_lock, flags); fcport->drport = rport; fcport->rport = NULL; + *(fc_port_t **)rport->dd_data = NULL; spin_unlock_irqrestore(&fcport->rport_lock, flags); set_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags); } else { spin_lock_irqsave(&fcport->rport_lock, flags); fcport->rport = NULL; + *(fc_port_t **)rport->dd_data = NULL; spin_unlock_irqrestore(&fcport->rport_lock, flags); fc_remote_port_delete(rport); } -- cgit v1.2.3 From f7757a5f0fa94a0ce4d6ea55f440845bb3faf712 Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Tue, 7 Feb 2006 08:45:30 -0800 Subject: [PATCH] qla2xxx: Remove bogus debug-code. Commit 854165f4245c4a3b4a8cc363ba2050033151e196 inadvertently added some code meant only for testing -- the driver was ignoring the non-zero function numbers of a multi-port HBA. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_os.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 9b5a10ac3e25..9f91f1a20542 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1283,9 +1283,6 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) fc_port_t *fcport; struct scsi_host_template *sht; -if (PCI_FUNC(pdev->devfn)) - goto probe_out; - if (pci_enable_device(pdev)) goto probe_out; -- cgit v1.2.3 From 247ec457ce108000987be517c83868f6361d9f76 Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Tue, 7 Feb 2006 08:45:40 -0800 Subject: [PATCH] qla2xxx: Pass input-buffer length to Get-ID-List mailbox command. Recent ISP24xx firmwares require that mailbox register 8 be set to the maximum number of bytes to transfer during DMA copying of the list. We safely set this value to zero (infinite), since the call is *only* made in FCAL topologies. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_mbx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 49ce197876b4..363dfdd042b0 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -1873,7 +1873,8 @@ qla2x00_get_id_list(scsi_qla_host_t *ha, void *id_list, dma_addr_t id_list_dma, mcp->mb[3] = LSW(id_list_dma); mcp->mb[6] = MSW(MSD(id_list_dma)); mcp->mb[7] = LSW(MSD(id_list_dma)); - mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2; + mcp->mb[8] = 0; + mcp->out_mb |= MBX_8|MBX_7|MBX_6|MBX_3|MBX_2; } else { mcp->mb[1] = MSW(id_list_dma); mcp->mb[2] = LSW(id_list_dma); -- cgit v1.2.3 From 0d4be1240b2668b6a3ffadb15eb660baf52f8377 Mon Sep 17 00:00:00 2001 From: "andrew.vasquez@qlogic.com" Date: Tue, 7 Feb 2006 08:45:35 -0800 Subject: [PATCH] qla2xxx: Correct lun assignment during IOCB submission. 4gb products require an IOCB's FCP-LUN to be formatted in wire-format prior to submission. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_iocb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 7ec0b8d6f07b..6544b6d0891d 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -814,6 +814,7 @@ qla24xx_start_scsi(srb_t *sp) cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain; int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun); + host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun)); /* Load SCSI command packet. */ memcpy(cmd_pkt->fcp_cdb, cmd->cmnd, cmd->cmd_len); -- cgit v1.2.3 From 479a079663bd4c5f3d2714643b1b8c406aaba3e0 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 7 Feb 2006 16:37:08 -0800 Subject: IPoIB: Don't start send-only joins while multicast thread is stopped Fix the following race scenario: - Device is up. - Port event or set mcast list triggers ipoib_mcast_stop_thread, this cancels the query and waits on mcast "done" completion. - Completion is called and "done" is set. - Meanwhile, ipoib_mcast_send arrives and starts a new query, re-initializing "done". Fix this by adding a "multicast started" bit and checking it before starting a send-only join. Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib.h | 1 + drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index e0a5412b7e68..2f85a9a831b1 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h @@ -78,6 +78,7 @@ enum { IPOIB_FLAG_SUBINTERFACE = 4, IPOIB_MCAST_RUN = 5, IPOIB_STOP_REAPER = 6, + IPOIB_MCAST_STARTED = 7, IPOIB_MAX_BACKOFF_SECONDS = 16, diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index ccaa0c387076..1c7148208ce8 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -601,6 +601,10 @@ int ipoib_mcast_start_thread(struct net_device *dev) queue_work(ipoib_workqueue, &priv->mcast_task); mutex_unlock(&mcast_mutex); + spin_lock_irq(&priv->lock); + set_bit(IPOIB_MCAST_STARTED, &priv->flags); + spin_unlock_irq(&priv->lock); + return 0; } @@ -611,6 +615,10 @@ int ipoib_mcast_stop_thread(struct net_device *dev, int flush) ipoib_dbg_mcast(priv, "stopping multicast thread\n"); + spin_lock_irq(&priv->lock); + clear_bit(IPOIB_MCAST_STARTED, &priv->flags); + spin_unlock_irq(&priv->lock); + mutex_lock(&mcast_mutex); clear_bit(IPOIB_MCAST_RUN, &priv->flags); cancel_delayed_work(&priv->mcast_task); @@ -693,6 +701,12 @@ void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid, */ spin_lock(&priv->lock); + if (!test_bit(IPOIB_MCAST_STARTED, &priv->flags)) { + ++priv->stats.tx_dropped; + dev_kfree_skb_any(skb); + goto unlock; + } + mcast = __ipoib_mcast_find(dev, mgid); if (!mcast) { /* Let's create a new send only group now */ @@ -754,6 +768,7 @@ out: ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN); } +unlock: spin_unlock(&priv->lock); } -- cgit v1.2.3 From 7bcb974ef6a0ae903888272c92c66ea779388c01 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 7 Feb 2006 16:39:26 -0800 Subject: IPoIB: Fix another send-only join race Further, there's an additional issue that I saw in testing: ipoib_mcast_send may get called when priv->broadcast is NULL (e.g. if the device was downed and then upped internally because of a port event). If this happends and the send-only join request gets completed before priv->broadcast is set, we get an oops. Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 1c7148208ce8..932bf139a65d 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -701,7 +701,7 @@ void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid, */ spin_lock(&priv->lock); - if (!test_bit(IPOIB_MCAST_STARTED, &priv->flags)) { + if (!test_bit(IPOIB_MCAST_STARTED, &priv->flags) || !priv->broadcast) { ++priv->stats.tx_dropped; dev_kfree_skb_any(skb); goto unlock; -- cgit v1.2.3 From f823bcae2b9f194cfc164b8cbb87d71695dec563 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Sun, 5 Feb 2006 20:37:53 -0700 Subject: [PARISC] Convert ccio-dma.c to use seq_file Gut ccio-dma.c of the ugly proc append and snprintf cruft and just use seq_printf instead. Tested on a K-class. Signed-off-by: Kyle McMartin --- drivers/parisc/ccio-dma.c | 160 +++++++++++++++++++++------------------------- 1 file changed, 74 insertions(+), 86 deletions(-) (limited to 'drivers') diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index f46e8438e0d2..93f8a8fa8890 100644 --- a/drivers/parisc/ccio-dma.c +++ b/drivers/parisc/ccio-dma.c @@ -40,6 +40,8 @@ #include #include #include +#include +#include #include #include /* for L1_CACHE_BYTES */ @@ -1019,62 +1021,33 @@ static struct hppa_dma_ops ccio_ops = { }; #ifdef CONFIG_PROC_FS -static int proc_append(char *src, int len, char **dst, off_t *offset, int *max) -{ - if (len < *offset) { - *offset -= len; - return 0; - } - if (*offset > 0) { - src += *offset; - len -= *offset; - *offset = 0; - } - if (len > *max) { - len = *max; - } - memcpy(*dst, src, len); - *dst += len; - *max -= len; - return (*max == 0); -} - -static int ccio_proc_info(char *buf, char **start, off_t offset, int count, - int *eof, void *data) +static int ccio_proc_info(struct seq_file *m, void *p) { - int max = count; - char tmp[80]; /* width of an ANSI-standard terminal */ + int len = 0; struct ioc *ioc = ioc_list; while (ioc != NULL) { unsigned int total_pages = ioc->res_size << 3; unsigned long avg = 0, min, max; - int j, len; + int j; - len = sprintf(tmp, "%s\n", ioc->name); - if (proc_append(tmp, len, &buf, &offset, &count)) - break; + len += seq_printf(m, "%s\n", ioc->name); - len = sprintf(tmp, "Cujo 2.0 bug : %s\n", - (ioc->cujo20_bug ? "yes" : "no")); - if (proc_append(tmp, len, &buf, &offset, &count)) - break; + len += seq_printf(m, "Cujo 2.0 bug : %s\n", + (ioc->cujo20_bug ? "yes" : "no")); - len = sprintf(tmp, "IO PDIR size : %d bytes (%d entries)\n", - total_pages * 8, total_pages); - if (proc_append(tmp, len, &buf, &offset, &count)) - break; + len += seq_printf(m, "IO PDIR size : %d bytes (%d entries)\n", + total_pages * 8, total_pages); + #ifdef CCIO_MAP_STATS - len = sprintf(tmp, "IO PDIR entries : %ld free %ld used (%d%%)\n", - total_pages - ioc->used_pages, ioc->used_pages, - (int)(ioc->used_pages * 100 / total_pages)); - if (proc_append(tmp, len, &buf, &offset, &count)) - break; + len += seq_printf(m, "IO PDIR entries : %ld free %ld used (%d%%)\n", + total_pages - ioc->used_pages, ioc->used_pages, + (int)(ioc->used_pages * 100 / total_pages)); #endif - len = sprintf(tmp, "Resource bitmap : %d bytes (%d pages)\n", - ioc->res_size, total_pages); - if (proc_append(tmp, len, &buf, &offset, &count)) - break; + + len += seq_printf(m, "Resource bitmap : %d bytes (%d pages)\n", + ioc->res_size, total_pages); + #ifdef CCIO_SEARCH_TIME min = max = ioc->avg_search[0]; for(j = 0; j < CCIO_SEARCH_SAMPLE; ++j) { @@ -1085,70 +1058,83 @@ static int ccio_proc_info(char *buf, char **start, off_t offset, int count, min = ioc->avg_search[j]; } avg /= CCIO_SEARCH_SAMPLE; - len = sprintf(tmp, " Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n", - min, avg, max); - if (proc_append(tmp, len, &buf, &offset, &count)) - break; + len += seq_printf(m, " Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n", + min, avg, max); #endif #ifdef CCIO_MAP_STATS - len = sprintf(tmp, "pci_map_single(): %8ld calls %8ld pages (avg %d/1000)\n", - ioc->msingle_calls, ioc->msingle_pages, - (int)((ioc->msingle_pages * 1000)/ioc->msingle_calls)); - if (proc_append(tmp, len, &buf, &offset, &count)) - break; - + len += seq_printf(m, "pci_map_single(): %8ld calls %8ld pages (avg %d/1000)\n", + ioc->msingle_calls, ioc->msingle_pages, + (int)((ioc->msingle_pages * 1000)/ioc->msingle_calls)); /* KLUGE - unmap_sg calls unmap_single for each mapped page */ min = ioc->usingle_calls - ioc->usg_calls; max = ioc->usingle_pages - ioc->usg_pages; - len = sprintf(tmp, "pci_unmap_single: %8ld calls %8ld pages (avg %d/1000)\n", - min, max, (int)((max * 1000)/min)); - if (proc_append(tmp, len, &buf, &offset, &count)) - break; + len += seq_printf(m, "pci_unmap_single: %8ld calls %8ld pages (avg %d/1000)\n", + min, max, (int)((max * 1000)/min)); - len = sprintf(tmp, "pci_map_sg() : %8ld calls %8ld pages (avg %d/1000)\n", - ioc->msg_calls, ioc->msg_pages, - (int)((ioc->msg_pages * 1000)/ioc->msg_calls)); - if (proc_append(tmp, len, &buf, &offset, &count)) - break; - len = sprintf(tmp, "pci_unmap_sg() : %8ld calls %8ld pages (avg %d/1000)\n\n\n", - ioc->usg_calls, ioc->usg_pages, - (int)((ioc->usg_pages * 1000)/ioc->usg_calls)); - if (proc_append(tmp, len, &buf, &offset, &count)) - break; + len += seq_printf(m, "pci_map_sg() : %8ld calls %8ld pages (avg %d/1000)\n", + ioc->msg_calls, ioc->msg_pages, + (int)((ioc->msg_pages * 1000)/ioc->msg_calls)); + + len += seq_printf(m, "pci_unmap_sg() : %8ld calls %8ld pages (avg %d/1000)\n\n\n", + ioc->usg_calls, ioc->usg_pages, + (int)((ioc->usg_pages * 1000)/ioc->usg_calls)); #endif /* CCIO_MAP_STATS */ + ioc = ioc->next; } - if (count == 0) { - *eof = 1; - } - return (max - count); + return 0; +} + +static int ccio_proc_info_open(struct inode *inode, struct file *file) +{ + return single_open(file, &ccio_proc_info, NULL); } -static int ccio_resource_map(char *buf, char **start, off_t offset, int len, - int *eof, void *data) +static struct file_operations ccio_proc_info_fops = { + .owner = THIS_MODULE, + .open = ccio_proc_info_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int ccio_proc_bitmap_info(struct seq_file *m, void *p) { + int len = 0; struct ioc *ioc = ioc_list; - buf[0] = '\0'; while (ioc != NULL) { u32 *res_ptr = (u32 *)ioc->res_map; int j; for (j = 0; j < (ioc->res_size / sizeof(u32)); j++) { if ((j & 7) == 0) - strcat(buf,"\n "); - sprintf(buf, "%s %08x", buf, *res_ptr); + len += seq_puts(m, "\n "); + len += seq_printf(m, "%08x", *res_ptr); res_ptr++; } - strcat(buf, "\n\n"); + len += seq_puts(m, "\n\n"); ioc = ioc->next; break; /* XXX - remove me */ } - return strlen(buf); + return 0; } + +static int ccio_proc_bitmap_open(struct inode *inode, struct file *file) +{ + return single_open(file, &ccio_proc_bitmap_info, NULL); +} + +static struct file_operations ccio_proc_bitmap_fops = { + .owner = THIS_MODULE, + .open = ccio_proc_bitmap_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; #endif /** @@ -1556,6 +1542,7 @@ static int ccio_probe(struct parisc_device *dev) { int i; struct ioc *ioc, **ioc_p = &ioc_list; + struct proc_dir_entry *info_entry, *bitmap_entry; ioc = kzalloc(sizeof(struct ioc), GFP_KERNEL); if (ioc == NULL) { @@ -1583,13 +1570,14 @@ static int ccio_probe(struct parisc_device *dev) BUG_ON(dev->dev.platform_data == NULL); HBA_DATA(dev->dev.platform_data)->iommu = ioc; - if (ioc_count == 0) { - /* FIXME: Create separate entries for each ioc */ - create_proc_read_entry(MODULE_NAME, S_IRWXU, proc_runway_root, - ccio_proc_info, NULL); - create_proc_read_entry(MODULE_NAME"-bitmap", S_IRWXU, - proc_runway_root, ccio_resource_map, NULL); + info_entry = create_proc_entry(MODULE_NAME, 0, proc_runway_root); + if (info_entry) + info_entry->proc_fops = &ccio_proc_info_fops; + + bitmap_entry = create_proc_entry(MODULE_NAME"-bitmap", 0, proc_runway_root); + if (bitmap_entry) + bitmap_entry->proc_fops = &ccio_proc_bitmap_fops; } ioc_count++; -- cgit v1.2.3 From 7ec14e49b72da20d7212c707f226271525aee4ae Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Mon, 6 Feb 2006 10:10:15 -0700 Subject: [PARISC] Convert sba_iommu.c to use seq_file Use seq_file interface for proc output in sba_iommu. Also clean up the bus root assignment, and give the proc files a more logical name. Tested on my J6000. Signed-off-by: Kyle McMartin --- drivers/parisc/sba_iommu.c | 125 ++++++++++++++++++++++++++++----------------- 1 file changed, 78 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index 52f265e97729..5d47c5965c51 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -37,6 +37,8 @@ #include /* for register_parisc_driver() stuff */ #include +#include + #include /* for proc_runway_root */ #include /* for PDC_MODEL_* */ #include /* for is_pdc_pat() */ @@ -1892,46 +1894,43 @@ sba_common_init(struct sba_device *sba_dev) } #ifdef CONFIG_PROC_FS -static int sba_proc_info(char *buf, char **start, off_t offset, int len) +static int sba_proc_info(struct seq_file *m, void *p) { struct sba_device *sba_dev = sba_list; struct ioc *ioc = &sba_dev->ioc[0]; /* FIXME: Multi-IOC support! */ int total_pages = (int) (ioc->res_size << 3); /* 8 bits per byte */ - unsigned long i; #ifdef SBA_COLLECT_STATS unsigned long avg = 0, min, max; #endif + int i, len = 0; - sprintf(buf, "%s rev %d.%d\n", + len += seq_printf(m, "%s rev %d.%d\n", sba_dev->name, (sba_dev->hw_rev & 0x7) + 1, (sba_dev->hw_rev & 0x18) >> 3 ); - sprintf(buf, "%sIO PDIR size : %d bytes (%d entries)\n", - buf, + len += seq_printf(m, "IO PDIR size : %d bytes (%d entries)\n", (int) ((ioc->res_size << 3) * sizeof(u64)), /* 8 bits/byte */ total_pages); - sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n", - buf, ioc->res_size, ioc->res_size << 3); /* 8 bits per byte */ + len += seq_printf(m, "Resource bitmap : %d bytes (%d pages)\n", + ioc->res_size, ioc->res_size << 3); /* 8 bits per byte */ - sprintf(buf, "%sLMMIO_BASE/MASK/ROUTE %08x %08x %08x\n", - buf, + len += seq_printf(m, "LMMIO_BASE/MASK/ROUTE %08x %08x %08x\n", READ_REG32(sba_dev->sba_hpa + LMMIO_DIST_BASE), READ_REG32(sba_dev->sba_hpa + LMMIO_DIST_MASK), READ_REG32(sba_dev->sba_hpa + LMMIO_DIST_ROUTE) ); for (i=0; i<4; i++) - sprintf(buf, "%sDIR%ld_BASE/MASK/ROUTE %08x %08x %08x\n", - buf, i, + len += seq_printf(m, "DIR%d_BASE/MASK/ROUTE %08x %08x %08x\n", i, READ_REG32(sba_dev->sba_hpa + LMMIO_DIRECT0_BASE + i*0x18), READ_REG32(sba_dev->sba_hpa + LMMIO_DIRECT0_MASK + i*0x18), READ_REG32(sba_dev->sba_hpa + LMMIO_DIRECT0_ROUTE + i*0x18) ); #ifdef SBA_COLLECT_STATS - sprintf(buf, "%sIO PDIR entries : %ld free %ld used (%d%%)\n", buf, + len += seq_printf(m, "IO PDIR entries : %ld free %ld used (%d%%)\n", total_pages - ioc->used_pages, ioc->used_pages, (int) (ioc->used_pages * 100 / total_pages)); @@ -1942,53 +1941,76 @@ static int sba_proc_info(char *buf, char **start, off_t offset, int len) if (ioc->avg_search[i] < min) min = ioc->avg_search[i]; } avg /= SBA_SEARCH_SAMPLE; - sprintf(buf, "%s Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n", - buf, min, avg, max); + len += seq_printf(m, " Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n", + min, avg, max); - sprintf(buf, "%spci_map_single(): %12ld calls %12ld pages (avg %d/1000)\n", - buf, ioc->msingle_calls, ioc->msingle_pages, + len += seq_printf(m, "pci_map_single(): %12ld calls %12ld pages (avg %d/1000)\n", + ioc->msingle_calls, ioc->msingle_pages, (int) ((ioc->msingle_pages * 1000)/ioc->msingle_calls)); /* KLUGE - unmap_sg calls unmap_single for each mapped page */ min = ioc->usingle_calls; max = ioc->usingle_pages - ioc->usg_pages; - sprintf(buf, "%spci_unmap_single: %12ld calls %12ld pages (avg %d/1000)\n", - buf, min, max, - (int) ((max * 1000)/min)); + len += seq_printf(m, "pci_unmap_single: %12ld calls %12ld pages (avg %d/1000)\n", + min, max, (int) ((max * 1000)/min)); - sprintf(buf, "%spci_map_sg() : %12ld calls %12ld pages (avg %d/1000)\n", - buf, ioc->msg_calls, ioc->msg_pages, + len += seq_printf(m, "pci_map_sg() : %12ld calls %12ld pages (avg %d/1000)\n", + ioc->msg_calls, ioc->msg_pages, (int) ((ioc->msg_pages * 1000)/ioc->msg_calls)); - sprintf(buf, "%spci_unmap_sg() : %12ld calls %12ld pages (avg %d/1000)\n", - buf, ioc->usg_calls, ioc->usg_pages, + len += seq_printf(m, "pci_unmap_sg() : %12ld calls %12ld pages (avg %d/1000)\n", + ioc->usg_calls, ioc->usg_pages, (int) ((ioc->usg_pages * 1000)/ioc->usg_calls)); #endif - return strlen(buf); + return 0; } -#if 0 -/* XXX too much output - exceeds 4k limit and needs to be re-written */ static int -sba_resource_map(char *buf, char **start, off_t offset, int len) +sba_proc_open(struct inode *i, struct file *f) +{ + return single_open(f, &sba_proc_info, NULL); +} + +static struct file_operations sba_proc_fops = { + .owner = THIS_MODULE, + .open = sba_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int +sba_proc_bitmap_info(struct seq_file *m, void *p) { struct sba_device *sba_dev = sba_list; - struct ioc *ioc = &sba_dev->ioc[0]; /* FIXME: Mutli-IOC suppoer! */ + struct ioc *ioc = &sba_dev->ioc[0]; /* FIXME: Multi-IOC support! */ unsigned int *res_ptr = (unsigned int *)ioc->res_map; - int i; + int i, len = 0; - buf[0] = '\0'; - for(i = 0; i < (ioc->res_size / sizeof(unsigned int)); ++i, ++res_ptr) { + for (i = 0; i < (ioc->res_size/sizeof(unsigned int)); ++i, ++res_ptr) { if ((i & 7) == 0) - strcat(buf,"\n "); - sprintf(buf, "%s %08x", buf, *res_ptr); + len += seq_printf(m, "\n "); + len += seq_printf(m, " %08x", *res_ptr); } - strcat(buf, "\n"); + len += seq_printf(m, "\n"); - return strlen(buf); + return 0; } -#endif /* 0 */ + +static int +sba_proc_bitmap_open(struct inode *i, struct file *f) +{ + return single_open(f, &sba_proc_bitmap_info, NULL); +} + +static struct file_operations sba_proc_bitmap_fops = { + .owner = THIS_MODULE, + .open = sba_proc_bitmap_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; #endif /* CONFIG_PROC_FS */ static struct parisc_device_id sba_tbl[] = { @@ -2021,6 +2043,7 @@ sba_driver_callback(struct parisc_device *dev) int i; char *version; void __iomem *sba_addr = ioremap(dev->hpa.start, SBA_FUNC_SIZE); + struct proc_dir_entry *info_entry, *bitmap_entry, *root; sba_dump_ranges(sba_addr); @@ -2088,19 +2111,27 @@ sba_driver_callback(struct parisc_device *dev) hppa_dma_ops = &sba_ops; #ifdef CONFIG_PROC_FS - if (IS_ASTRO(&dev->id)) { - create_proc_info_entry("Astro", 0, proc_runway_root, sba_proc_info); - } else if (IS_IKE(&dev->id)) { - create_proc_info_entry("Ike", 0, proc_runway_root, sba_proc_info); - } else if (IS_PLUTO(&dev->id)) { - create_proc_info_entry("Pluto", 0, proc_mckinley_root, sba_proc_info); - } else { - create_proc_info_entry("Reo", 0, proc_runway_root, sba_proc_info); + switch (dev->id.hversion) { + case PLUTO_MCKINLEY_PORT: + root = proc_mckinley_root; + break; + case ASTRO_RUNWAY_PORT: + case IKE_MERCED_PORT: + default: + root = proc_runway_root; + break; } -#if 0 - create_proc_info_entry("bitmap", 0, proc_runway_root, sba_resource_map); -#endif + + info_entry = create_proc_entry("sba_iommu", 0, root); + bitmap_entry = create_proc_entry("sba_iommu-bitmap", 0, root); + + if (info_entry) + info_entry->proc_fops = &sba_proc_fops; + + if (bitmap_entry) + bitmap_entry->proc_fops = &sba_proc_bitmap_fops; #endif + parisc_vmerge_boundary = IOVP_SIZE; parisc_vmerge_max_size = IOVP_SIZE * BITS_PER_LONG; parisc_has_iommu(); -- cgit v1.2.3 From afcd024183d8a6eae7e489ce50b2485c5ae4f662 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Fri, 10 Feb 2006 01:51:03 -0800 Subject: [PATCH] wrong firmware location in IPW2100 Kconfig entry Firmware should go into /lib/firmware, not /etc/firmware. Found by Alejandro Bonilla. Signed-off-by: Jesper Juhl Signed-off-by: Adrian Bunk Acked-by: Zhu Yi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/wireless/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 233a4f608084..ef85d76575a2 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -148,7 +148,7 @@ config IPW2100 In order to use this driver, you will need a firmware image for it. You can obtain the firmware from . Once you have the firmware image, you - will need to place it in /etc/firmware. + will need to place it in /lib/firmware. You will also very likely need the Wireless Tools in order to configure your card: -- cgit v1.2.3 From 8977d929e49021d9a6e031310aab01fa72f849c2 Mon Sep 17 00:00:00 2001 From: Paul Fulghum Date: Fri, 10 Feb 2006 01:51:14 -0800 Subject: [PATCH] tty buffering stall fix Prevent stalled processing of received data when a driver allocates tty buffer space but does not immediately follow the allocation with more data and a call to schedule receive tty processing. (example: hvc_console) This bug was introduced by the first locking patch for the new tty buffering. Signed-off-by: Paul Fulghum Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/tty_io.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 076e07c1da38..a23816d3e9a1 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -268,6 +268,8 @@ static struct tty_buffer *tty_buffer_alloc(size_t size) p->size = size; p->next = NULL; p->active = 0; + p->commit = 0; + p->read = 0; p->char_buf_ptr = (char *)(p->data); p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size; /* printk("Flip create %p\n", p); */ @@ -298,6 +300,8 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size) *tbh = t->next; t->next = NULL; t->used = 0; + t->commit = 0; + t->read = 0; /* DEBUG ONLY */ memset(t->data, '*', size); /* printk("Flip recycle %p\n", t); */ @@ -335,6 +339,7 @@ int tty_buffer_request_room(struct tty_struct *tty, size_t size) if (b != NULL) { b->next = n; b->active = 0; + b->commit = b->used; } else tty->buf.head = n; tty->buf.tail = n; @@ -2752,6 +2757,9 @@ static void flush_to_ldisc(void *private_) unsigned long flags; struct tty_ldisc *disc; struct tty_buffer *tbuf; + int count; + char *char_buf; + unsigned char *flag_buf; disc = tty_ldisc_ref(tty); if (disc == NULL) /* !TTY_LDISC */ @@ -2765,16 +2773,20 @@ static void flush_to_ldisc(void *private_) goto out; } spin_lock_irqsave(&tty->buf.lock, flags); - while((tbuf = tty->buf.head) != NULL && !tbuf->active) { + while((tbuf = tty->buf.head) != NULL) { + while ((count = tbuf->commit - tbuf->read) != 0) { + char_buf = tbuf->char_buf_ptr + tbuf->read; + flag_buf = tbuf->flag_buf_ptr + tbuf->read; + tbuf->read += count; + spin_unlock_irqrestore(&tty->buf.lock, flags); + disc->receive_buf(tty, char_buf, flag_buf, count); + spin_lock_irqsave(&tty->buf.lock, flags); + } + if (tbuf->active) + break; tty->buf.head = tbuf->next; if (tty->buf.head == NULL) tty->buf.tail = NULL; - spin_unlock_irqrestore(&tty->buf.lock, flags); - /* printk("Process buffer %p for %d\n", tbuf, tbuf->used); */ - disc->receive_buf(tty, tbuf->char_buf_ptr, - tbuf->flag_buf_ptr, - tbuf->used); - spin_lock_irqsave(&tty->buf.lock, flags); tty_buffer_free(tty, tbuf); } spin_unlock_irqrestore(&tty->buf.lock, flags); @@ -2871,8 +2883,10 @@ void tty_flip_buffer_push(struct tty_struct *tty) { unsigned long flags; spin_lock_irqsave(&tty->buf.lock, flags); - if (tty->buf.tail != NULL) + if (tty->buf.tail != NULL) { tty->buf.tail->active = 0; + tty->buf.tail->commit = tty->buf.tail->used; + } spin_unlock_irqrestore(&tty->buf.lock, flags); if (tty->low_latency) -- cgit v1.2.3 From fd401aee6273e869e2711de498e28f5208184797 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 10 Feb 2006 21:50:43 +0000 Subject: [SERIAL] Remove incorrect code from ioc4 serial driver Serial drivers in general should not write uart_info->flags - they're private to serial_core. Serial drivers have no need to fiddle with tty->alt_speed, nor manipulate TTY_IO_ERROR in tty->flags. Fix the ioc4 serial driver for both these points by simply removing the offending code. Acked-by: pfg@sgi.com Signed-off-by: Russell King --- drivers/serial/ioc4_serial.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c index 1d85533d46d2..f3763d2ccb86 100644 --- a/drivers/serial/ioc4_serial.c +++ b/drivers/serial/ioc4_serial.c @@ -1717,11 +1717,9 @@ ioc4_change_speed(struct uart_port *the_port, } if (cflag & CRTSCTS) { - info->flags |= ASYNC_CTS_FLOW; port->ip_sscr |= IOC4_SSCR_HFC_EN; } else { - info->flags &= ~ASYNC_CTS_FLOW; port->ip_sscr &= ~IOC4_SSCR_HFC_EN; } writel(port->ip_sscr, &port->ip_serial_regs->sscr); @@ -1760,18 +1758,6 @@ static inline int ic4_startup_local(struct uart_port *the_port) info = the_port->info; - if (info->tty) { - set_bit(TTY_IO_ERROR, &info->tty->flags); - clear_bit(TTY_IO_ERROR, &info->tty->flags); - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - info->tty->alt_speed = 57600; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - info->tty->alt_speed = 115200; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - info->tty->alt_speed = 230400; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - info->tty->alt_speed = 460800; - } local_open(port); /* set the speed of the serial port */ -- cgit v1.2.3 From f295c79b6766b25fe8c1aad88211c54d1caa7e0b Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Fri, 10 Feb 2006 18:02:44 -0800 Subject: IB/mthca: Don't print debugging info until we have all values When debugging is enabled, the mthca_QUERY_DEV_LIM() firmware command function prints out some of the device limits that it queries. However the debugging prints happen before all of the fields are extracted from the firmware response, so some of the values that get printed are uninitialized junk. Move the prints to the end of the function to fix this. Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_cmd.c | 38 ++++++++++++++++----------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index f9b9b93dc501..2825615ce81c 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c @@ -1029,25 +1029,6 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev, MTHCA_GET(size, outbox, QUERY_DEV_LIM_UAR_ENTRY_SZ_OFFSET); dev_lim->uar_scratch_entry_sz = size; - mthca_dbg(dev, "Max QPs: %d, reserved QPs: %d, entry size: %d\n", - dev_lim->max_qps, dev_lim->reserved_qps, dev_lim->qpc_entry_sz); - mthca_dbg(dev, "Max SRQs: %d, reserved SRQs: %d, entry size: %d\n", - dev_lim->max_srqs, dev_lim->reserved_srqs, dev_lim->srq_entry_sz); - mthca_dbg(dev, "Max CQs: %d, reserved CQs: %d, entry size: %d\n", - dev_lim->max_cqs, dev_lim->reserved_cqs, dev_lim->cqc_entry_sz); - mthca_dbg(dev, "Max EQs: %d, reserved EQs: %d, entry size: %d\n", - dev_lim->max_eqs, dev_lim->reserved_eqs, dev_lim->eqc_entry_sz); - mthca_dbg(dev, "reserved MPTs: %d, reserved MTTs: %d\n", - dev_lim->reserved_mrws, dev_lim->reserved_mtts); - mthca_dbg(dev, "Max PDs: %d, reserved PDs: %d, reserved UARs: %d\n", - dev_lim->max_pds, dev_lim->reserved_pds, dev_lim->reserved_uars); - mthca_dbg(dev, "Max QP/MCG: %d, reserved MGMs: %d\n", - dev_lim->max_pds, dev_lim->reserved_mgms); - mthca_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n", - dev_lim->max_cq_sz, dev_lim->max_qp_sz, dev_lim->max_srq_sz); - - mthca_dbg(dev, "Flags: %08x\n", dev_lim->flags); - if (mthca_is_memfree(dev)) { MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SRQ_SZ_OFFSET); dev_lim->max_srq_sz = 1 << field; @@ -1093,6 +1074,25 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev, dev_lim->mpt_entry_sz = MTHCA_MPT_ENTRY_SIZE; } + mthca_dbg(dev, "Max QPs: %d, reserved QPs: %d, entry size: %d\n", + dev_lim->max_qps, dev_lim->reserved_qps, dev_lim->qpc_entry_sz); + mthca_dbg(dev, "Max SRQs: %d, reserved SRQs: %d, entry size: %d\n", + dev_lim->max_srqs, dev_lim->reserved_srqs, dev_lim->srq_entry_sz); + mthca_dbg(dev, "Max CQs: %d, reserved CQs: %d, entry size: %d\n", + dev_lim->max_cqs, dev_lim->reserved_cqs, dev_lim->cqc_entry_sz); + mthca_dbg(dev, "Max EQs: %d, reserved EQs: %d, entry size: %d\n", + dev_lim->max_eqs, dev_lim->reserved_eqs, dev_lim->eqc_entry_sz); + mthca_dbg(dev, "reserved MPTs: %d, reserved MTTs: %d\n", + dev_lim->reserved_mrws, dev_lim->reserved_mtts); + mthca_dbg(dev, "Max PDs: %d, reserved PDs: %d, reserved UARs: %d\n", + dev_lim->max_pds, dev_lim->reserved_pds, dev_lim->reserved_uars); + mthca_dbg(dev, "Max QP/MCG: %d, reserved MGMs: %d\n", + dev_lim->max_pds, dev_lim->reserved_mgms); + mthca_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n", + dev_lim->max_cq_sz, dev_lim->max_qp_sz, dev_lim->max_srq_sz); + + mthca_dbg(dev, "Flags: %08x\n", dev_lim->flags); + out: mthca_free_mailbox(dev, mailbox); return err; -- cgit v1.2.3 From 20b83382d1c5d4d1a73fc5671261db5239d1dbb3 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Sat, 11 Feb 2006 12:22:12 -0800 Subject: IPoIB: Yet another fix for send-only joins Even after the last fix, it's still possible for a send-only join to start before the join for the broadcast group has finished. This could cause us to create a multicast group using attributes from the broadcast group that haven't been initialized yet, so we would use garbage for the Q_Key, etc. Fix this by waiting until the broadcast group's attached flag is set before starting send-only joins. Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 932bf139a65d..a2408d7ec598 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -533,8 +533,10 @@ void ipoib_mcast_join_task(void *dev_ptr) } if (!priv->broadcast) { - priv->broadcast = ipoib_mcast_alloc(dev, 1); - if (!priv->broadcast) { + struct ipoib_mcast *broadcast; + + broadcast = ipoib_mcast_alloc(dev, 1); + if (!broadcast) { ipoib_warn(priv, "failed to allocate broadcast group\n"); mutex_lock(&mcast_mutex); if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) @@ -544,10 +546,11 @@ void ipoib_mcast_join_task(void *dev_ptr) return; } - memcpy(priv->broadcast->mcmember.mgid.raw, priv->dev->broadcast + 4, + spin_lock_irq(&priv->lock); + memcpy(broadcast->mcmember.mgid.raw, priv->dev->broadcast + 4, sizeof (union ib_gid)); + priv->broadcast = broadcast; - spin_lock_irq(&priv->lock); __ipoib_mcast_add(dev, priv->broadcast); spin_unlock_irq(&priv->lock); } @@ -701,7 +704,9 @@ void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid, */ spin_lock(&priv->lock); - if (!test_bit(IPOIB_MCAST_STARTED, &priv->flags) || !priv->broadcast) { + if (!test_bit(IPOIB_MCAST_STARTED, &priv->flags) || + !priv->broadcast || + !test_bit(IPOIB_MCAST_FLAG_ATTACHED, &priv->broadcast->flags)) { ++priv->stats.tx_dropped; dev_kfree_skb_any(skb); goto unlock; -- cgit v1.2.3 From c48d865c50e8626372a52094385fb1f5a2d2a7fd Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Sat, 11 Feb 2006 17:55:57 -0800 Subject: [PATCH] s390: fix locking in __chp_add() and s390_subchannel_remove_chpid() Fix locking in __chp_add() and s390_subchannel_remove_chpid(): Need to disable/enable because they are always called from a thread (and not directly from a machine check...) Signed-off-by: Cornelia Huck Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/cio/chsc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 92be75d99a56..8cf9905d484b 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -232,7 +232,7 @@ s390_subchannel_remove_chpid(struct device *dev, void *data) return 0; mask = 0x80 >> j; - spin_lock(&sch->lock); + spin_lock_irq(&sch->lock); stsch(sch->schid, &schib); if (!schib.pmcw.dnv) @@ -281,10 +281,10 @@ s390_subchannel_remove_chpid(struct device *dev, void *data) if (sch->driver && sch->driver->verify) sch->driver->verify(&sch->dev); out_unlock: - spin_unlock(&sch->lock); + spin_unlock_irq(&sch->lock); return 0; out_unreg: - spin_unlock(&sch->lock); + spin_unlock_irq(&sch->lock); sch->lpm = 0; if (css_enqueue_subchannel_slow(sch->schid)) { css_clear_subchannel_slow_list(); @@ -652,7 +652,7 @@ __chp_add(struct subchannel_id schid, void *data) if (!sch) /* Check if the subchannel is now available. */ return __chp_add_new_sch(schid); - spin_lock(&sch->lock); + spin_lock_irq(&sch->lock); for (i=0; i<8; i++) if (sch->schib.pmcw.chpid[i] == chp->id) { if (stsch(sch->schid, &sch->schib) != 0) { @@ -674,7 +674,7 @@ __chp_add(struct subchannel_id schid, void *data) if (sch->driver && sch->driver->verify) sch->driver->verify(&sch->dev); - spin_unlock(&sch->lock); + spin_unlock_irq(&sch->lock); put_device(&sch->dev); return 0; } -- cgit v1.2.3 From 25fab9ebac445d57b656f5faabac5a195bed2f82 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Sat, 11 Feb 2006 17:55:59 -0800 Subject: [PATCH] s390: fix sclp memory corruption in tty pages list When the sclp interface takes very long to serve a request, the sclp core driver will report a failed request to the sclp tty driver even though the request is still being processed by the sclp interface. Eventually the sclp interface completes the request and updates some fields in the request buffer which leads to a corrupted tty pages list. The next time function sclp_tty_write_room is called, the corrupted list will be traversed, resulting in an oops. To avoid this remove the busy retry limit and increase retry intervals. Signed-off-by: Peter Oberparleiter Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/char/sclp.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index ceb0e474fde4..4138564402b8 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c @@ -85,11 +85,10 @@ static volatile enum sclp_mask_state_t { /* Maximum retry counts */ #define SCLP_INIT_RETRY 3 #define SCLP_MASK_RETRY 3 -#define SCLP_REQUEST_RETRY 3 /* Timeout intervals in seconds.*/ -#define SCLP_BUSY_INTERVAL 2 -#define SCLP_RETRY_INTERVAL 5 +#define SCLP_BUSY_INTERVAL 10 +#define SCLP_RETRY_INTERVAL 15 static void sclp_process_queue(void); static int sclp_init_mask(int calculate); @@ -153,11 +152,9 @@ __sclp_start_request(struct sclp_req *req) if (sclp_running_state != sclp_running_state_idle) return 0; del_timer(&sclp_request_timer); - if (req->start_count <= SCLP_REQUEST_RETRY) { - rc = service_call(req->command, req->sccb); - req->start_count++; - } else - rc = -EIO; + rc = service_call(req->command, req->sccb); + req->start_count++; + if (rc == 0) { /* Sucessfully started request */ req->status = SCLP_REQ_RUNNING; -- cgit v1.2.3 From 1d30883942cfe8a1e3f88f8b7f4c292aeba3db5a Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 11 Feb 2006 17:56:05 -0800 Subject: [PATCH] tipar fixes - tipar_open(): fix unsigned comparison - tipar_open(): don't permit NULL pardevice (probably unneeded given the above fix). - tipar_init_module(): handle the situation where parport_register_driver() failed to register any devices (parport_register_driver() drops the ->attach return value on the floor). This probably makes fixes #1 and #2 unneeded. - tipar_init_module(): fix various error-path resource leaks. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/tipar.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c index 41a94bc79f67..eb2eb3e12d6a 100644 --- a/drivers/char/tipar.c +++ b/drivers/char/tipar.c @@ -250,12 +250,17 @@ tipar_open(struct inode *inode, struct file *file) { unsigned int minor = iminor(inode) - TIPAR_MINOR; - if (minor > tp_count - 1) + if (tp_count == 0 || minor > tp_count - 1) return -ENXIO; if (test_and_set_bit(minor, &opened)) return -EBUSY; + if (!table[minor].dev) { + printk(KERN_ERR "%s: NULL device for minor %u\n", + __FUNCTION__, minor); + return -ENXIO; + } parport_claim_or_block(table[minor].dev); init_ti_parallel(minor); parport_release(table[minor].dev); @@ -510,16 +515,20 @@ tipar_init_module(void) err = PTR_ERR(tipar_class); goto out_chrdev; } - if (parport_register_driver(&tipar_driver)) { + if (parport_register_driver(&tipar_driver) || tp_count == 0) { printk(KERN_ERR "tipar: unable to register with parport\n"); err = -EIO; - goto out; + goto out_class; } err = 0; goto out; +out_class: + class_destroy(tipar_class); + out_chrdev: + devfs_remove("ticables/par"); unregister_chrdev(TIPAR_MAJOR, "tipar"); out: return err; -- cgit v1.2.3 From 891e5e5edaf13216f9f4c2710aebd066b1d98583 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 11 Feb 2006 17:56:05 -0800 Subject: [PATCH] drivers/video/Kconfig: remove unused BUS_I2C option The BUS_I2C option is neither available (since there is no VISWS option in the kernel) nor does it have any effect - so why not remove it? Based on a report by Jean-Luc Leger . Signed-off-by: Adrian Bunk Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/Kconfig | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 3e153d313bb0..e64ed16bd42f 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -525,11 +525,6 @@ config FB_GBE_MEM This is the amount of memory reserved for the framebuffer, which can be any value between 1MB and 8MB. -config BUS_I2C - bool - depends on (FB = y) && VISWS - default y - config FB_SUN3 bool "Sun3 framebuffer support" depends on (FB = y) && (SUN3 || SUN3X) && BROKEN -- cgit v1.2.3 From bc7fc0601b3eb2254f080492f3fd69e319ed32d0 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Sat, 11 Feb 2006 17:56:07 -0800 Subject: [PATCH] nvidiafb: Add support for Geforce4 MX 4000 Add support for Geforce4 MX 4000 (0x185) Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/nvidia/nvidia.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index dbcb8962e57d..a7c4e5e8ead6 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -138,6 +138,8 @@ static struct pci_device_id nvidiafb_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420_8X, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_4000, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_448_GO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_488_GO, -- cgit v1.2.3 From bc6d7fdf460ec5292d66bb551dbfa49ca682bebf Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 11 Feb 2006 17:56:08 -0800 Subject: [PATCH] fbdev: video_setup() warning fix drivers/video/fbmem.c:1567: warning: 'video_setup' defined but not used Acked-by: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/fbmem.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index d2dede6ed3e5..996c7b58564e 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1550,6 +1550,7 @@ int fb_get_options(char *name, char **option) return retval; } +#ifndef MODULE /** * video_setup - process command line options * @options: string of options @@ -1593,6 +1594,7 @@ static int __init video_setup(char *options) return 0; } __setup("video=", video_setup); +#endif /* * Visible symbols for modules -- cgit v1.2.3 From 3a69e5791379a7c7d23c531a7679428300bb5072 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Mon, 7 Nov 2005 10:21:24 +0000 Subject: [WATCHDOG] sa1100_wdt.c sparse clean (2) The following makes drivers/char/watchdog/sa1100_wdt.c sparse clean. (similar to the other watchdog drivers) Signed-off-by: Ian Campbell Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/sa1100_wdt.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c index b474ea52d6e8..522a9370db94 100644 --- a/drivers/char/watchdog/sa1100_wdt.c +++ b/drivers/char/watchdog/sa1100_wdt.c @@ -93,23 +93,25 @@ static int sa1100dog_ioctl(struct inode *inode, struct file *file, { int ret = -ENOIOCTLCMD; int time; + void __user *argp = (void __user *)arg; + int __user *p = argp; switch (cmd) { case WDIOC_GETSUPPORT: - ret = copy_to_user((struct watchdog_info __user *)arg, &ident, + ret = copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; break; case WDIOC_GETSTATUS: - ret = put_user(0, (int __user *)arg); + ret = put_user(0, p); break; case WDIOC_GETBOOTSTATUS: - ret = put_user(boot_status, (int __user *)arg); + ret = put_user(boot_status, p); break; case WDIOC_SETTIMEOUT: - ret = get_user(time, (int __user *)arg); + ret = get_user(time, p); if (ret) break; @@ -123,7 +125,7 @@ static int sa1100dog_ioctl(struct inode *inode, struct file *file, /*fall through*/ case WDIOC_GETTIMEOUT: - ret = put_user(pre_margin / OSCR_FREQ, (int __user *)arg); + ret = put_user(pre_margin / OSCR_FREQ, p); break; case WDIOC_KEEPALIVE: -- cgit v1.2.3 From fd41fa616f21efc36eb80696475ceb33ea047a6a Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Sat, 10 Dec 2005 14:22:37 +0100 Subject: [WATCHDOG] pcwd.c add comments + tabs add extra comments for the include files changes spaces by tabs where it is appropriate. Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/pcwd.c | 71 +++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c index 37c9e13ad3ac..85c94b205df1 100644 --- a/drivers/char/watchdog/pcwd.c +++ b/drivers/char/watchdog/pcwd.c @@ -49,27 +49,30 @@ * More info available at http://www.berkprod.com/ or http://www.pcwatchdog.com/ */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include /* For CONFIG_WATCHDOG_NOWAYOUT/... */ +#include /* For module specific items */ +#include /* For new moduleparam's */ +#include /* For standard types (like size_t) */ +#include /* For the -ENODEV/... values */ +#include /* For printk/panic/... */ +#include /* For mdelay function */ +#include /* For timer related operations */ +#include /* For jiffies stuff */ +#include /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */ +#include /* For the watchdog specific items */ +#include /* For notifier support */ +#include /* For reboot_notifier stuff */ +#include /* For __init/__exit/... */ +#include /* For file operations */ +#include /* For io-port access */ +#include /* For spin_lock/spin_unlock/... */ #include /* TASK_INTERRUPTIBLE, set_current_state() and friends */ -#include -#include +#include /* For kmalloc */ +#include /* For copy_to_user/put_user/... */ +#include /* For inb/outb/... */ + +/* Module and version information */ #define WD_VER "1.16 (06/12/2004)" #define PFX "pcwd: " @@ -84,7 +87,7 @@ #define PCWD_REVISION_C 2 /* - * These are the defines that describe the control status bits for the + * These are the defines that describe the control status #1 bits for the * PC Watchdog card, revision A. */ #define WD_WDRST 0x01 /* Previously reset state */ @@ -94,7 +97,7 @@ #define WD_SRLY2 0x80 /* Software external relay triggered */ /* - * These are the defines that describe the control status bits for the + * These are the defines that describe the control status #1 bits for the * PC Watchdog card, revision C. */ #define WD_REVC_WTRP 0x01 /* Watchdog Trip status */ @@ -106,15 +109,15 @@ #define ISA_COMMAND_TIMEOUT 1000 /* Watchdog's internal commands */ -#define CMD_ISA_IDLE 0x00 -#define CMD_ISA_VERSION_INTEGER 0x01 -#define CMD_ISA_VERSION_TENTH 0x02 -#define CMD_ISA_VERSION_HUNDRETH 0x03 -#define CMD_ISA_VERSION_MINOR 0x04 -#define CMD_ISA_SWITCH_SETTINGS 0x05 -#define CMD_ISA_DELAY_TIME_2SECS 0x0A -#define CMD_ISA_DELAY_TIME_4SECS 0x0B -#define CMD_ISA_DELAY_TIME_8SECS 0x0C +#define CMD_ISA_IDLE 0x00 +#define CMD_ISA_VERSION_INTEGER 0x01 +#define CMD_ISA_VERSION_TENTH 0x02 +#define CMD_ISA_VERSION_HUNDRETH 0x03 +#define CMD_ISA_VERSION_MINOR 0x04 +#define CMD_ISA_SWITCH_SETTINGS 0x05 +#define CMD_ISA_DELAY_TIME_2SECS 0x0A +#define CMD_ISA_DELAY_TIME_4SECS 0x0B +#define CMD_ISA_DELAY_TIME_8SECS 0x0C /* * We are using an kernel timer to do the pinging of the watchdog @@ -767,10 +770,10 @@ static int __devinit pcwatchdog_init(int base_addr) printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n"); /* Check that the heartbeat value is within it's range ; if not reset to the default */ - if (pcwd_set_heartbeat(heartbeat)) { - pcwd_set_heartbeat(WATCHDOG_HEARTBEAT); - printk(KERN_INFO PFX "heartbeat value must be 2<=heartbeat<=7200, using %d\n", - WATCHDOG_HEARTBEAT); + if (pcwd_set_heartbeat(heartbeat)) { + pcwd_set_heartbeat(WATCHDOG_HEARTBEAT); + printk(KERN_INFO PFX "heartbeat value must be 2<=heartbeat<=7200, using %d\n", + WATCHDOG_HEARTBEAT); } ret = register_reboot_notifier(&pcwd_notifier); -- cgit v1.2.3 From f1c3a0567aa5086e755e58385740f9ece911c06e Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Sat, 10 Dec 2005 14:36:24 +0100 Subject: [WATCHDOG] pcwd.c card_found-- fix. When doing a __devexit from a card we should also decrement the cards_found counter. Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/pcwd.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c index 85c94b205df1..3329cbffdb34 100644 --- a/drivers/char/watchdog/pcwd.c +++ b/drivers/char/watchdog/pcwd.c @@ -828,6 +828,7 @@ static void __devexit pcwatchdog_exit(void) unregister_reboot_notifier(&pcwd_notifier); release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4); current_readport = 0x0000; + cards_found--; } /* -- cgit v1.2.3 From a2be8786006ec0d21dcb1d322fc480b85ea82c66 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Mon, 9 Jan 2006 21:53:33 +0100 Subject: [WATCHDOG] pcwd.c private data struct patch more private data of the card to one struct. Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/pcwd.c | 206 ++++++++++++++++++++++--------------------- 1 file changed, 104 insertions(+), 102 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c index 3329cbffdb34..1112ec8e61f3 100644 --- a/drivers/char/watchdog/pcwd.c +++ b/drivers/char/watchdog/pcwd.c @@ -73,7 +73,7 @@ #include /* For inb/outb/... */ /* Module and version information */ -#define WD_VER "1.16 (06/12/2004)" +#define WD_VER "1.16 (03/01/2006)" #define PFX "pcwd: " /* @@ -133,15 +133,17 @@ static int cards_found; /* internal variables */ static atomic_t open_allowed = ATOMIC_INIT(1); static char expect_close; -static struct timer_list timer; -static unsigned long next_heartbeat; static int temp_panic; -static int revision; /* The card's revision */ -static int supports_temp; /* Wether or not the card has a temperature device */ -static int command_mode; /* Wether or not the card is in command mode */ -static int initial_status; /* The card's boot status */ -static int current_readport; /* The cards I/O address */ -static spinlock_t io_lock; +static struct { /* this is private data for each ISA-PC watchdog card */ + int revision; /* The card's revision */ + int supports_temp; /* Wether or not the card has a temperature device */ + int command_mode; /* Wether or not the card is in command mode */ + int boot_status; /* The card's boot status */ + int io_addr; /* The cards I/O address */ + spinlock_t io_lock; /* the lock for io operations */ + struct timer_list timer; /* The timer that pings the watchdog */ + unsigned long next_heartbeat; /* the next_heartbeat for the timer */ +} pcwd_private; /* module parameters */ #define WATCHDOG_HEARTBEAT 60 /* 60 sec default heartbeat */ @@ -165,13 +167,13 @@ static int send_isa_command(int cmd) /* The WCMD bit must be 1 and the command is only 4 bits in size */ control_status = (cmd & 0x0F) | 0x80; - outb_p(control_status, current_readport + 2); + outb_p(control_status, pcwd_private.io_addr + 2); udelay(ISA_COMMAND_TIMEOUT); - port0 = inb_p(current_readport); + port0 = inb_p(pcwd_private.io_addr); for (i = 0; i < 25; ++i) { last_port0 = port0; - port0 = inb_p(current_readport); + port0 = inb_p(pcwd_private.io_addr); if (port0 == last_port0) break; /* Data is stable */ @@ -187,7 +189,7 @@ static int set_command_mode(void) int i, found=0, count=0; /* Set the card into command mode */ - spin_lock(&io_lock); + spin_lock(&pcwd_private.io_lock); while ((!found) && (count < 3)) { i = send_isa_command(CMD_ISA_IDLE); @@ -195,15 +197,15 @@ static int set_command_mode(void) found = 1; else if (i == 0xF3) { /* Card does not like what we've done to it */ - outb_p(0x00, current_readport + 2); + outb_p(0x00, pcwd_private.io_addr + 2); udelay(1200); /* Spec says wait 1ms */ - outb_p(0x00, current_readport + 2); + outb_p(0x00, pcwd_private.io_addr + 2); udelay(ISA_COMMAND_TIMEOUT); } count++; } - spin_unlock(&io_lock); - command_mode = found; + spin_unlock(&pcwd_private.io_lock); + pcwd_private.command_mode = found; return(found); } @@ -211,12 +213,12 @@ static int set_command_mode(void) static void unset_command_mode(void) { /* Set the card into normal mode */ - spin_lock(&io_lock); - outb_p(0x00, current_readport + 2); + spin_lock(&pcwd_private.io_lock); + outb_p(0x00, pcwd_private.io_addr + 2); udelay(ISA_COMMAND_TIMEOUT); - spin_unlock(&io_lock); + spin_unlock(&pcwd_private.io_lock); - command_mode = 0; + pcwd_private.command_mode = 0; } static void pcwd_timer_ping(unsigned long data) @@ -225,25 +227,25 @@ static void pcwd_timer_ping(unsigned long data) /* If we got a heartbeat pulse within the WDT_INTERVAL * we agree to ping the WDT */ - if(time_before(jiffies, next_heartbeat)) { + if(time_before(jiffies, pcwd_private.next_heartbeat)) { /* Ping the watchdog */ - spin_lock(&io_lock); - if (revision == PCWD_REVISION_A) { + spin_lock(&pcwd_private.io_lock); + if (pcwd_private.revision == PCWD_REVISION_A) { /* Rev A cards are reset by setting the WD_WDRST bit in register 1 */ - wdrst_stat = inb_p(current_readport); + wdrst_stat = inb_p(pcwd_private.io_addr); wdrst_stat &= 0x0F; wdrst_stat |= WD_WDRST; - outb_p(wdrst_stat, current_readport + 1); + outb_p(wdrst_stat, pcwd_private.io_addr + 1); } else { /* Re-trigger watchdog by writing to port 0 */ - outb_p(0x00, current_readport); + outb_p(0x00, pcwd_private.io_addr); } /* Re-set the timer interval */ - mod_timer(&timer, jiffies + WDT_INTERVAL); + mod_timer(&pcwd_private.timer, jiffies + WDT_INTERVAL); - spin_unlock(&io_lock); + spin_unlock(&pcwd_private.io_lock); } else { printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n"); } @@ -253,18 +255,18 @@ static int pcwd_start(void) { int stat_reg; - next_heartbeat = jiffies + (heartbeat * HZ); + pcwd_private.next_heartbeat = jiffies + (heartbeat * HZ); /* Start the timer */ - mod_timer(&timer, jiffies + WDT_INTERVAL); + mod_timer(&pcwd_private.timer, jiffies + WDT_INTERVAL); /* Enable the port */ - if (revision == PCWD_REVISION_C) { - spin_lock(&io_lock); - outb_p(0x00, current_readport + 3); + if (pcwd_private.revision == PCWD_REVISION_C) { + spin_lock(&pcwd_private.io_lock); + outb_p(0x00, pcwd_private.io_addr + 3); udelay(ISA_COMMAND_TIMEOUT); - stat_reg = inb_p(current_readport + 2); - spin_unlock(&io_lock); + stat_reg = inb_p(pcwd_private.io_addr + 2); + spin_unlock(&pcwd_private.io_lock); if (stat_reg & 0x10) { printk(KERN_INFO PFX "Could not start watchdog\n"); return -EIO; @@ -278,17 +280,17 @@ static int pcwd_stop(void) int stat_reg; /* Stop the timer */ - del_timer(&timer); + del_timer(&pcwd_private.timer); /* Disable the board */ - if (revision == PCWD_REVISION_C) { - spin_lock(&io_lock); - outb_p(0xA5, current_readport + 3); + if (pcwd_private.revision == PCWD_REVISION_C) { + spin_lock(&pcwd_private.io_lock); + outb_p(0xA5, pcwd_private.io_addr + 3); udelay(ISA_COMMAND_TIMEOUT); - outb_p(0xA5, current_readport + 3); + outb_p(0xA5, pcwd_private.io_addr + 3); udelay(ISA_COMMAND_TIMEOUT); - stat_reg = inb_p(current_readport + 2); - spin_unlock(&io_lock); + stat_reg = inb_p(pcwd_private.io_addr + 2); + spin_unlock(&pcwd_private.io_lock); if ((stat_reg & 0x10) == 0) { printk(KERN_INFO PFX "Could not stop watchdog\n"); return -EIO; @@ -300,7 +302,7 @@ static int pcwd_stop(void) static int pcwd_keepalive(void) { /* user land ping */ - next_heartbeat = jiffies + (heartbeat * HZ); + pcwd_private.next_heartbeat = jiffies + (heartbeat * HZ); return 0; } @@ -318,23 +320,23 @@ static int pcwd_get_status(int *status) int card_status; *status=0; - spin_lock(&io_lock); - if (revision == PCWD_REVISION_A) + spin_lock(&pcwd_private.io_lock); + if (pcwd_private.revision == PCWD_REVISION_A) /* Rev A cards return status information from * the base register, which is used for the * temperature in other cards. */ - card_status = inb(current_readport); + card_status = inb(pcwd_private.io_addr); else { /* Rev C cards return card status in the base * address + 1 register. And use different bits * to indicate a card initiated reset, and an * over-temperature condition. And the reboot * status can be reset. */ - card_status = inb(current_readport + 1); + card_status = inb(pcwd_private.io_addr + 1); } - spin_unlock(&io_lock); + spin_unlock(&pcwd_private.io_lock); - if (revision == PCWD_REVISION_A) { + if (pcwd_private.revision == PCWD_REVISION_A) { if (card_status & WD_WDRST) *status |= WDIOF_CARDRESET; @@ -363,10 +365,10 @@ static int pcwd_get_status(int *status) static int pcwd_clear_status(void) { - if (revision == PCWD_REVISION_C) { - spin_lock(&io_lock); - outb_p(0x00, current_readport + 1); /* clear reset status */ - spin_unlock(&io_lock); + if (pcwd_private.revision == PCWD_REVISION_C) { + spin_lock(&pcwd_private.io_lock); + outb_p(0x00, pcwd_private.io_addr + 1); /* clear reset status */ + spin_unlock(&pcwd_private.io_lock); } return 0; } @@ -374,20 +376,20 @@ static int pcwd_clear_status(void) static int pcwd_get_temperature(int *temperature) { /* check that port 0 gives temperature info and no command results */ - if (command_mode) + if (pcwd_private.command_mode) return -1; *temperature = 0; - if (!supports_temp) + if (!pcwd_private.supports_temp) return -ENODEV; /* * Convert celsius to fahrenheit, since this was * the decided 'standard' for this return value. */ - spin_lock(&io_lock); - *temperature = ((inb(current_readport)) * 9 / 5) + 32; - spin_unlock(&io_lock); + spin_lock(&pcwd_private.io_lock); + *temperature = ((inb(pcwd_private.io_addr)) * 9 / 5) + 32; + spin_unlock(&pcwd_private.io_lock); return 0; } @@ -428,7 +430,7 @@ static int pcwd_ioctl(struct inode *inode, struct file *file, return put_user(status, argp); case WDIOC_GETBOOTSTATUS: - return put_user(initial_status, argp); + return put_user(pcwd_private.boot_status, argp); case WDIOC_GETTEMP: if (pcwd_get_temperature(&temperature)) @@ -437,7 +439,7 @@ static int pcwd_ioctl(struct inode *inode, struct file *file, return put_user(temperature, argp); case WDIOC_SETOPTIONS: - if (revision == PCWD_REVISION_C) + if (pcwd_private.revision == PCWD_REVISION_C) { if(copy_from_user(&rv, argp, sizeof(int))) return -EFAULT; @@ -553,7 +555,7 @@ static ssize_t pcwd_temp_read(struct file *file, char __user *buf, size_t count, static int pcwd_temp_open(struct inode *inode, struct file *file) { - if (!supports_temp) + if (!pcwd_private.supports_temp) return -ENODEV; return nonseekable_open(inode, file); @@ -621,21 +623,21 @@ static struct notifier_block pcwd_notifier = { static inline void get_support(void) { - if (inb(current_readport) != 0xF0) - supports_temp = 1; + if (inb(pcwd_private.io_addr) != 0xF0) + pcwd_private.supports_temp = 1; } static inline int get_revision(void) { int r = PCWD_REVISION_C; - spin_lock(&io_lock); + spin_lock(&pcwd_private.io_lock); /* REV A cards use only 2 io ports; test * presumes a floating bus reads as 0xff. */ - if ((inb(current_readport + 2) == 0xFF) || - (inb(current_readport + 3) == 0xFF)) + if ((inb(pcwd_private.io_addr + 2) == 0xFF) || + (inb(pcwd_private.io_addr + 3) == 0xFF)) r=PCWD_REVISION_A; - spin_unlock(&io_lock); + spin_unlock(&pcwd_private.io_lock); return r; } @@ -695,32 +697,32 @@ static int __devinit pcwatchdog_init(int base_addr) printk(KERN_ERR PFX "No I/O-Address for card detected\n"); return -ENODEV; } - current_readport = base_addr; + pcwd_private.io_addr = base_addr; /* Check card's revision */ - revision = get_revision(); + pcwd_private.revision = get_revision(); - if (!request_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4, "PCWD")) { + if (!request_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4, "PCWD")) { printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", - current_readport); - current_readport = 0x0000; + pcwd_private.io_addr); + pcwd_private.io_addr = 0x0000; return -EIO; } /* Initial variables */ - supports_temp = 0; + pcwd_private.supports_temp = 0; temp_panic = 0; - initial_status = 0x0000; + pcwd_private.boot_status = 0x0000; /* get the boot_status */ - pcwd_get_status(&initial_status); + pcwd_get_status(&pcwd_private.boot_status); /* clear the "card caused reboot" flag */ pcwd_clear_status(); - init_timer(&timer); - timer.function = pcwd_timer_ping; - timer.data = 0; + init_timer(&pcwd_private.timer); + pcwd_private.timer.function = pcwd_timer_ping; + pcwd_private.timer.data = 0; /* Disable the board */ pcwd_stop(); @@ -729,12 +731,12 @@ static int __devinit pcwatchdog_init(int base_addr) get_support(); /* Get some extra info from the hardware (in command/debug/diag mode) */ - if (revision == PCWD_REVISION_A) - printk(KERN_INFO PFX "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n", current_readport); - else if (revision == PCWD_REVISION_C) { + if (pcwd_private.revision == PCWD_REVISION_A) + printk(KERN_INFO PFX "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n", pcwd_private.io_addr); + else if (pcwd_private.revision == PCWD_REVISION_C) { firmware = get_firmware(); printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n", - current_readport, firmware); + pcwd_private.io_addr, firmware); kfree(firmware); option_switches = get_option_switches(); printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n", @@ -750,23 +752,23 @@ static int __devinit pcwatchdog_init(int base_addr) } else { /* Should NEVER happen, unless get_revision() fails. */ printk(KERN_INFO PFX "Unable to get revision\n"); - release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4); - current_readport = 0x0000; + release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4); + pcwd_private.io_addr = 0x0000; return -1; } - if (supports_temp) + if (pcwd_private.supports_temp) printk(KERN_INFO PFX "Temperature Option Detected\n"); - if (initial_status & WDIOF_CARDRESET) + if (pcwd_private.boot_status & WDIOF_CARDRESET) printk(KERN_INFO PFX "Previous reboot was caused by the card\n"); - if (initial_status & WDIOF_OVERHEAT) { + if (pcwd_private.boot_status & WDIOF_OVERHEAT) { printk(KERN_EMERG PFX "Card senses a CPU Overheat. Panicking!\n"); printk(KERN_EMERG PFX "CPU Overheat\n"); } - if (initial_status == 0) + if (pcwd_private.boot_status == 0) printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n"); /* Check that the heartbeat value is within it's range ; if not reset to the default */ @@ -780,19 +782,19 @@ static int __devinit pcwatchdog_init(int base_addr) if (ret) { printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret); - release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4); - current_readport = 0x0000; + release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4); + pcwd_private.io_addr = 0x0000; return ret; } - if (supports_temp) { + if (pcwd_private.supports_temp) { ret = misc_register(&temp_miscdev); if (ret) { printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", TEMP_MINOR, ret); unregister_reboot_notifier(&pcwd_notifier); - release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4); - current_readport = 0x0000; + release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4); + pcwd_private.io_addr = 0x0000; return ret; } } @@ -801,11 +803,11 @@ static int __devinit pcwatchdog_init(int base_addr) if (ret) { printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", WATCHDOG_MINOR, ret); - if (supports_temp) + if (pcwd_private.supports_temp) misc_deregister(&temp_miscdev); unregister_reboot_notifier(&pcwd_notifier); - release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4); - current_readport = 0x0000; + release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4); + pcwd_private.io_addr = 0x0000; return ret; } @@ -823,11 +825,11 @@ static void __devexit pcwatchdog_exit(void) /* Deregister */ misc_deregister(&pcwd_miscdev); - if (supports_temp) + if (pcwd_private.supports_temp) misc_deregister(&temp_miscdev); unregister_reboot_notifier(&pcwd_notifier); - release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4); - current_readport = 0x0000; + release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4); + pcwd_private.io_addr = 0x0000; cards_found--; } @@ -891,7 +893,7 @@ static int __init pcwd_init_module(void) { int i, found = 0; - spin_lock_init(&io_lock); + spin_lock_init(&pcwd_private.io_lock); for (i = 0; pcwd_ioports[i] != 0; i++) { if (pcwd_checkcard(pcwd_ioports[i])) { @@ -910,7 +912,7 @@ static int __init pcwd_init_module(void) static void __exit pcwd_cleanup_module(void) { - if (current_readport) + if (pcwd_private.io_addr) pcwatchdog_exit(); return; } -- cgit v1.2.3 From 8f0235dccc3f7bffc32abcef2aec3d1b15c61927 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Mon, 9 Jan 2006 21:56:09 +0100 Subject: [WATCHDOG] pcwd.c Control Status #2 patch Add Control Status #2 bits (with defines) Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/pcwd.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c index 1112ec8e61f3..0635cd724365 100644 --- a/drivers/char/watchdog/pcwd.c +++ b/drivers/char/watchdog/pcwd.c @@ -87,22 +87,24 @@ #define PCWD_REVISION_C 2 /* - * These are the defines that describe the control status #1 bits for the - * PC Watchdog card, revision A. - */ + * These are the defines that describe the control status bits for the + * PCI-PC Watchdog card. +*/ +/* Port 1 : Control Status #1 for the PC Watchdog card, revision A. */ #define WD_WDRST 0x01 /* Previously reset state */ #define WD_T110 0x02 /* Temperature overheat sense */ #define WD_HRTBT 0x04 /* Heartbeat sense */ #define WD_RLY2 0x08 /* External relay triggered */ #define WD_SRLY2 0x80 /* Software external relay triggered */ - -/* - * These are the defines that describe the control status #1 bits for the - * PC Watchdog card, revision C. - */ +/* Port 1 : Control Status #1 for the PC Watchdog card, revision C. */ #define WD_REVC_WTRP 0x01 /* Watchdog Trip status */ #define WD_REVC_HRBT 0x02 /* Watchdog Heartbeat */ #define WD_REVC_TTRP 0x04 /* Temperature Trip status */ +/* Port 2 : Control Status #2 */ +#define WD_WDIS 0x10 /* Watchdog Disabled */ +#define WD_ENTP 0x20 /* Watchdog Enable Temperature Trip */ +#define WD_SSEL 0x40 /* Watchdog Switch Select (1:SW1 <-> 0:SW2) */ +#define WD_WCMD 0x80 /* Watchdog Command Mode */ /* max. time we give an ISA watchdog card to process a command */ /* 500ms for each 4 bit response (according to spec.) */ @@ -166,7 +168,7 @@ static int send_isa_command(int cmd) int port0, last_port0; /* Double read for stabilising */ /* The WCMD bit must be 1 and the command is only 4 bits in size */ - control_status = (cmd & 0x0F) | 0x80; + control_status = (cmd & 0x0F) | WD_WCMD; outb_p(control_status, pcwd_private.io_addr + 2); udelay(ISA_COMMAND_TIMEOUT); @@ -267,7 +269,7 @@ static int pcwd_start(void) udelay(ISA_COMMAND_TIMEOUT); stat_reg = inb_p(pcwd_private.io_addr + 2); spin_unlock(&pcwd_private.io_lock); - if (stat_reg & 0x10) { + if (stat_reg & WD_WDIS) { printk(KERN_INFO PFX "Could not start watchdog\n"); return -EIO; } @@ -291,7 +293,7 @@ static int pcwd_stop(void) udelay(ISA_COMMAND_TIMEOUT); stat_reg = inb_p(pcwd_private.io_addr + 2); spin_unlock(&pcwd_private.io_lock); - if ((stat_reg & 0x10) == 0) { + if ((stat_reg & WD_WDIS) == 0) { printk(KERN_INFO PFX "Could not stop watchdog\n"); return -EIO; } -- cgit v1.2.3 From 85875211acc94ecb76fe04fbebc6aca12b6da60d Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Mon, 9 Jan 2006 21:59:39 +0100 Subject: [WATCHDOG] pcwd.c move get_support to pcwd_check_temperature_support Rename get_support function to pcwd_check_temperature_support so that it is clearer what the function does. Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/pcwd.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c index 0635cd724365..0549b2e89966 100644 --- a/drivers/char/watchdog/pcwd.c +++ b/drivers/char/watchdog/pcwd.c @@ -223,6 +223,12 @@ static void unset_command_mode(void) pcwd_private.command_mode = 0; } +static inline void pcwd_check_temperature_support(void) +{ + if (inb(pcwd_private.io_addr) != 0xF0) + pcwd_private.supports_temp = 1; +} + static void pcwd_timer_ping(unsigned long data) { int wdrst_stat; @@ -623,12 +629,6 @@ static struct notifier_block pcwd_notifier = { * Init & exit routines */ -static inline void get_support(void) -{ - if (inb(pcwd_private.io_addr) != 0xF0) - pcwd_private.supports_temp = 1; -} - static inline int get_revision(void) { int r = PCWD_REVISION_C; @@ -730,7 +730,7 @@ static int __devinit pcwatchdog_init(int base_addr) pcwd_stop(); /* Check whether or not the card supports the temperature device */ - get_support(); + pcwd_check_temperature_support(); /* Get some extra info from the hardware (in command/debug/diag mode) */ if (pcwd_private.revision == PCWD_REVISION_A) -- cgit v1.2.3 From af3b38d99d7d52340cf59a06ff90d90e0fa25b6d Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Mon, 9 Jan 2006 22:03:41 +0100 Subject: [WATCHDOG] pcwd.c show card info patch Put all code for showing the card's boot info in one sub-routine. Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/pcwd.c | 157 ++++++++++++++++++++++--------------------- 1 file changed, 79 insertions(+), 78 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c index 0549b2e89966..f8f80d52d4de 100644 --- a/drivers/char/watchdog/pcwd.c +++ b/drivers/char/watchdog/pcwd.c @@ -229,6 +229,83 @@ static inline void pcwd_check_temperature_support(void) pcwd_private.supports_temp = 1; } +static inline char *get_firmware(void) +{ + int one, ten, hund, minor; + char *ret; + + ret = kmalloc(6, GFP_KERNEL); + if(ret == NULL) + return NULL; + + if (set_command_mode()) { + one = send_isa_command(CMD_ISA_VERSION_INTEGER); + ten = send_isa_command(CMD_ISA_VERSION_TENTH); + hund = send_isa_command(CMD_ISA_VERSION_HUNDRETH); + minor = send_isa_command(CMD_ISA_VERSION_MINOR); + sprintf(ret, "%c.%c%c%c", one, ten, hund, minor); + } + else + sprintf(ret, "ERROR"); + + unset_command_mode(); + return(ret); +} + +static inline int pcwd_get_option_switches(void) +{ + int option_switches=0; + + if (set_command_mode()) { + /* Get switch settings */ + option_switches = send_isa_command(CMD_ISA_SWITCH_SETTINGS); + } + + unset_command_mode(); + return(option_switches); +} + +static void pcwd_show_card_info(void) +{ + char *firmware; + int option_switches; + + /* Get some extra info from the hardware (in command/debug/diag mode) */ + if (pcwd_private.revision == PCWD_REVISION_A) + printk(KERN_INFO PFX "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n", pcwd_private.io_addr); + else if (pcwd_private.revision == PCWD_REVISION_C) { + firmware = get_firmware(); + printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n", + pcwd_private.io_addr, firmware); + kfree(firmware); + option_switches = pcwd_get_option_switches(); + printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n", + option_switches, + ((option_switches & 0x10) ? "ON" : "OFF"), + ((option_switches & 0x08) ? "ON" : "OFF")); + + /* Reprogram internal heartbeat to 2 seconds */ + if (set_command_mode()) { + send_isa_command(CMD_ISA_DELAY_TIME_2SECS); + unset_command_mode(); + } + } + + if (pcwd_private.supports_temp) + printk(KERN_INFO PFX "Temperature Option Detected\n"); + + if (pcwd_private.boot_status & WDIOF_CARDRESET) + printk(KERN_INFO PFX "Previous reboot was caused by the card\n"); + + if (pcwd_private.boot_status & WDIOF_OVERHEAT) { + printk(KERN_EMERG PFX "Card senses a CPU Overheat. Panicking!\n"); + printk(KERN_EMERG PFX "CPU Overheat\n"); + } + + if (pcwd_private.boot_status == 0) + printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n"); +} + static void pcwd_timer_ping(unsigned long data) { int wdrst_stat; @@ -644,47 +721,9 @@ static inline int get_revision(void) return r; } -static inline char *get_firmware(void) -{ - int one, ten, hund, minor; - char *ret; - - ret = kmalloc(6, GFP_KERNEL); - if(ret == NULL) - return NULL; - - if (set_command_mode()) { - one = send_isa_command(CMD_ISA_VERSION_INTEGER); - ten = send_isa_command(CMD_ISA_VERSION_TENTH); - hund = send_isa_command(CMD_ISA_VERSION_HUNDRETH); - minor = send_isa_command(CMD_ISA_VERSION_MINOR); - sprintf(ret, "%c.%c%c%c", one, ten, hund, minor); - } - else - sprintf(ret, "ERROR"); - - unset_command_mode(); - return(ret); -} - -static inline int get_option_switches(void) -{ - int rv=0; - - if (set_command_mode()) { - /* Get switch settings */ - rv = send_isa_command(CMD_ISA_SWITCH_SETTINGS); - } - - unset_command_mode(); - return(rv); -} - static int __devinit pcwatchdog_init(int base_addr) { int ret; - char *firmware; - int option_switches; cards_found++; if (cards_found == 1) @@ -732,46 +771,8 @@ static int __devinit pcwatchdog_init(int base_addr) /* Check whether or not the card supports the temperature device */ pcwd_check_temperature_support(); - /* Get some extra info from the hardware (in command/debug/diag mode) */ - if (pcwd_private.revision == PCWD_REVISION_A) - printk(KERN_INFO PFX "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n", pcwd_private.io_addr); - else if (pcwd_private.revision == PCWD_REVISION_C) { - firmware = get_firmware(); - printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n", - pcwd_private.io_addr, firmware); - kfree(firmware); - option_switches = get_option_switches(); - printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n", - option_switches, - ((option_switches & 0x10) ? "ON" : "OFF"), - ((option_switches & 0x08) ? "ON" : "OFF")); - - /* Reprogram internal heartbeat to 2 seconds */ - if (set_command_mode()) { - send_isa_command(CMD_ISA_DELAY_TIME_2SECS); - unset_command_mode(); - } - } else { - /* Should NEVER happen, unless get_revision() fails. */ - printk(KERN_INFO PFX "Unable to get revision\n"); - release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4); - pcwd_private.io_addr = 0x0000; - return -1; - } - - if (pcwd_private.supports_temp) - printk(KERN_INFO PFX "Temperature Option Detected\n"); - - if (pcwd_private.boot_status & WDIOF_CARDRESET) - printk(KERN_INFO PFX "Previous reboot was caused by the card\n"); - - if (pcwd_private.boot_status & WDIOF_OVERHEAT) { - printk(KERN_EMERG PFX "Card senses a CPU Overheat. Panicking!\n"); - printk(KERN_EMERG PFX "CPU Overheat\n"); - } - - if (pcwd_private.boot_status == 0) - printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n"); + /* Show info about the card itself */ + pcwd_show_card_info(); /* Check that the heartbeat value is within it's range ; if not reset to the default */ if (pcwd_set_heartbeat(heartbeat)) { -- cgit v1.2.3 From a7122f916978a6cd58b765949cb315aabcddf151 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Mon, 9 Jan 2006 22:07:22 +0100 Subject: [WATCHDOG] pcwd.c - update module version info Update the module version defines. Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/pcwd.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c index f8f80d52d4de..8d6b249ad66b 100644 --- a/drivers/char/watchdog/pcwd.c +++ b/drivers/char/watchdog/pcwd.c @@ -73,8 +73,13 @@ #include /* For inb/outb/... */ /* Module and version information */ -#define WD_VER "1.16 (03/01/2006)" -#define PFX "pcwd: " +#define WATCHDOG_VERSION "1.16" +#define WATCHDOG_DATE "03 Jan 2006" +#define WATCHDOG_DRIVER_NAME "ISA-PC Watchdog" +#define WATCHDOG_NAME "pcwd" +#define PFX WATCHDOG_NAME ": " +#define DRIVER_VERSION WATCHDOG_DRIVER_NAME " driver, v" WATCHDOG_VERSION " (" WATCHDOG_DATE ")\n" +#define WD_VER WATCHDOG_VERSION " (" WATCHDOG_DATE ")" /* * It should be noted that PCWD_REVISION_B was removed because A and B -- cgit v1.2.3 From 4733804c9f62fbc17ba69e8654a5fdf465f5bc41 Mon Sep 17 00:00:00 2001 From: Brian King Date: Wed, 8 Feb 2006 20:57:42 -0600 Subject: [SCSI] ipr: Fix adapter initialization failure Since scsi core is always sending scatterlists now, remove some code which was written with the bad assumption that a small transfer would not be sent down in a scatterlist. Without this fix, the ipr driver ends up sending garbage data to the adapter following a reset, causing it to fail the reset and take the adapter offline. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 49 +++++-------------------------------------------- drivers/scsi/ipr.h | 5 ++--- 2 files changed, 7 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 27acf78cf8d8..2bba5e55d7bc 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -4235,35 +4235,6 @@ static void ipr_scsi_done(struct ipr_cmnd *ipr_cmd) ipr_erp_start(ioa_cfg, ipr_cmd); } -/** - * ipr_save_ioafp_mode_select - Save adapters mode select data - * @ioa_cfg: ioa config struct - * @scsi_cmd: scsi command struct - * - * This function saves mode select data for the adapter to - * use following an adapter reset. - * - * Return value: - * 0 on success / SCSI_MLQUEUE_HOST_BUSY on failure - **/ -static int ipr_save_ioafp_mode_select(struct ipr_ioa_cfg *ioa_cfg, - struct scsi_cmnd *scsi_cmd) -{ - if (!ioa_cfg->saved_mode_pages) { - ioa_cfg->saved_mode_pages = kmalloc(sizeof(struct ipr_mode_pages), - GFP_ATOMIC); - if (!ioa_cfg->saved_mode_pages) { - dev_err(&ioa_cfg->pdev->dev, - "IOA mode select buffer allocation failed\n"); - return SCSI_MLQUEUE_HOST_BUSY; - } - } - - memcpy(ioa_cfg->saved_mode_pages, scsi_cmd->buffer, scsi_cmd->cmnd[4]); - ioa_cfg->saved_mode_page_len = scsi_cmd->cmnd[4]; - return 0; -} - /** * ipr_queuecommand - Queue a mid-layer request * @scsi_cmd: scsi command struct @@ -4338,9 +4309,6 @@ static int ipr_queuecommand(struct scsi_cmnd *scsi_cmd, (!ipr_is_gscsi(res) || scsi_cmd->cmnd[0] == IPR_QUERY_RSRC_STATE)) ioarcb->cmd_pkt.request_type = IPR_RQTYPE_IOACMD; - if (ipr_is_ioa_resource(res) && scsi_cmd->cmnd[0] == MODE_SELECT) - rc = ipr_save_ioafp_mode_select(ioa_cfg, scsi_cmd); - if (likely(rc == 0)) rc = ipr_build_ioadl(ioa_cfg, ipr_cmd); @@ -4829,17 +4797,11 @@ static int ipr_ioafp_mode_select_page28(struct ipr_cmnd *ipr_cmd) int length; ENTER; - if (ioa_cfg->saved_mode_pages) { - memcpy(mode_pages, ioa_cfg->saved_mode_pages, - ioa_cfg->saved_mode_page_len); - length = ioa_cfg->saved_mode_page_len; - } else { - ipr_scsi_bus_speed_limit(ioa_cfg); - ipr_check_term_power(ioa_cfg, mode_pages); - ipr_modify_ioafp_mode_page_28(ioa_cfg, mode_pages); - length = mode_pages->hdr.length + 1; - mode_pages->hdr.length = 0; - } + ipr_scsi_bus_speed_limit(ioa_cfg); + ipr_check_term_power(ioa_cfg, mode_pages); + ipr_modify_ioafp_mode_page_28(ioa_cfg, mode_pages); + length = mode_pages->hdr.length + 1; + mode_pages->hdr.length = 0; ipr_build_mode_select(ipr_cmd, cpu_to_be32(IPR_IOA_RES_HANDLE), 0x11, ioa_cfg->vpd_cbs_dma + offsetof(struct ipr_misc_cbs, mode_pages), @@ -5969,7 +5931,6 @@ static void ipr_free_mem(struct ipr_ioa_cfg *ioa_cfg) } ipr_free_dump(ioa_cfg); - kfree(ioa_cfg->saved_mode_pages); kfree(ioa_cfg->trace); } diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index b639332131f1..fd360bfe56dd 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -36,8 +36,8 @@ /* * Literals */ -#define IPR_DRIVER_VERSION "2.1.1" -#define IPR_DRIVER_DATE "(November 15, 2005)" +#define IPR_DRIVER_VERSION "2.1.2" +#define IPR_DRIVER_DATE "(February 8, 2006)" /* * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding @@ -1000,7 +1000,6 @@ struct ipr_ioa_cfg { struct Scsi_Host *host; struct pci_dev *pdev; struct ipr_sglist *ucode_sglist; - struct ipr_mode_pages *saved_mode_pages; u8 saved_mode_page_len; struct work_struct work_q; -- cgit v1.2.3 From 3542adcb354fea4fca792d36b91cb44d0da147e5 Mon Sep 17 00:00:00 2001 From: "Ju, Seokmann" Date: Thu, 9 Feb 2006 12:32:59 -0700 Subject: [SCSI] megaraid_legacy: kobject_register failure Attached patch fixes problem that cause kobject_register failure during loading. Kobject_register would fail when there are more than 1 module with same module name. This patch will change module name of megaraid_legacy from 'megaraid' to 'megaraid_legacy'. Signed-Off-by: Seokmann Ju Signed-off-by: James Bottomley --- drivers/scsi/megaraid.c | 2 +- drivers/scsi/megaraid.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index d101a8a6f4e8..7144674bc8e6 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -5049,7 +5049,7 @@ static struct pci_device_id megaraid_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, megaraid_pci_tbl); static struct pci_driver megaraid_pci_driver = { - .name = "megaraid", + .name = "megaraid_legacy", .id_table = megaraid_pci_tbl, .probe = megaraid_probe_one, .remove = __devexit_p(megaraid_remove_one), diff --git a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h index 4b3e0d6e5afa..4b75fe619d9c 100644 --- a/drivers/scsi/megaraid.h +++ b/drivers/scsi/megaraid.h @@ -5,7 +5,7 @@ #include #define MEGARAID_VERSION \ - "v2.00.3 (Release Date: Wed Feb 19 08:51:30 EST 2003)\n" + "v2.00.4 (Release Date: Thu Feb 9 08:51:30 EST 2006)\n" /* * Driver features - change the values to enable or disable features in the -- cgit v1.2.3 From c8024eb549f0c701e6d1c46c32e997f06f05d76d Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Sat, 11 Feb 2006 01:40:11 +0100 Subject: [SCSI] zfcp: get rid of physical_wwpn and physical_s_id Remove all remainders of obsolete zfcp adapter attributes physical_wwpn and physical_s_id. Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_def.h | 2 -- drivers/s390/scsi/zfcp_sysfs_adapter.c | 4 ---- 2 files changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index e260d19fa717..7dac56c49ade 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -915,8 +915,6 @@ struct zfcp_adapter { wwn_t peer_wwnn; /* P2P peer WWNN */ wwn_t peer_wwpn; /* P2P peer WWPN */ u32 peer_d_id; /* P2P peer D_ID */ - wwn_t physical_wwpn; /* WWPN of physical port */ - u32 physical_s_id; /* local FC port ID */ struct ccw_device *ccw_device; /* S/390 ccw device */ u8 fc_service_class; u32 hydra_version; /* Hydra version */ diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c index dfc07370f412..b29ac25e07f3 100644 --- a/drivers/s390/scsi/zfcp_sysfs_adapter.c +++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c @@ -55,8 +55,6 @@ ZFCP_DEFINE_ADAPTER_ATTR(status, "0x%08x\n", atomic_read(&adapter->status)); ZFCP_DEFINE_ADAPTER_ATTR(peer_wwnn, "0x%016llx\n", adapter->peer_wwnn); ZFCP_DEFINE_ADAPTER_ATTR(peer_wwpn, "0x%016llx\n", adapter->peer_wwpn); ZFCP_DEFINE_ADAPTER_ATTR(peer_d_id, "0x%06x\n", adapter->peer_d_id); -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(hardware_version, "0x%08x\n", @@ -241,8 +239,6 @@ static struct attribute *zfcp_adapter_attrs[] = { &dev_attr_peer_wwnn.attr, &dev_attr_peer_wwpn.attr, &dev_attr_peer_d_id.attr, - &dev_attr_physical_wwpn.attr, - &dev_attr_physical_s_id.attr, &dev_attr_card_version.attr, &dev_attr_lic_version.attr, &dev_attr_status.attr, -- cgit v1.2.3 From 2f8f3ed5fc566700cf45d422f4cf1624bd123d93 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Sat, 11 Feb 2006 01:41:50 +0100 Subject: [SCSI] zfcp: fix adapter erp when link is unplugged Remove endless polling for replug of the local link. Just wait for link up notification. Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_def.h | 5 --- drivers/s390/scsi/zfcp_erp.c | 80 ++++++++++++++++---------------------------- drivers/s390/scsi/zfcp_fsf.c | 74 ++++++++++++++++++++++------------------ 3 files changed, 69 insertions(+), 90 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 7dac56c49ade..f031199c7414 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -152,11 +152,6 @@ typedef u32 scsi_lun_t; #define ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP 100 #define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES 7 -/* Retry 5 times every 2 second, then every minute */ -#define ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES 5 -#define ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP 200 -#define ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP 6000 - /* timeout value for "default timer" for fsf requests */ #define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ); diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index da947e662031..8ed6fcb41653 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -2246,15 +2246,6 @@ zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action) { int retval; - if ((atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, - &erp_action->adapter->status)) && - (erp_action->adapter->adapter_features & - FSF_FEATURE_HBAAPI_MANAGEMENT)) { - zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); - atomic_set(&erp_action->adapter->erp_counter, 0); - return ZFCP_ERP_FAILED; - } - retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action); if (retval == ZFCP_ERP_FAILED) return ZFCP_ERP_FAILED; @@ -2266,13 +2257,6 @@ zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action) return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action); } -/* - * function: - * - * purpose: - * - * returns: - */ static int zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action) { @@ -2350,48 +2334,40 @@ static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action) { int ret; - int retries; - int sleep; - struct zfcp_adapter *adapter = erp_action->adapter; + struct zfcp_adapter *adapter; + adapter = erp_action->adapter; atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); - retries = 0; - do { - write_lock(&adapter->erp_lock); - zfcp_erp_action_to_running(erp_action); - write_unlock(&adapter->erp_lock); - zfcp_erp_timeout_init(erp_action); - ret = zfcp_fsf_exchange_port_data(erp_action, adapter, NULL); - if (ret == -EOPNOTSUPP) { - debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp"); - return ZFCP_ERP_SUCCEEDED; - } else if (ret) { - debug_text_event(adapter->erp_dbf, 3, "a_xport_failed"); - return ZFCP_ERP_FAILED; - } - debug_text_event(adapter->erp_dbf, 6, "a_xport_ok"); + write_lock(&adapter->erp_lock); + zfcp_erp_action_to_running(erp_action); + write_unlock(&adapter->erp_lock); - down(&adapter->erp_ready_sem); - if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) { - ZFCP_LOG_INFO("error: exchange of port data " - "for adapter %s timed out\n", - zfcp_get_busid_by_adapter(adapter)); - break; - } - if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, - &adapter->status)) - break; + zfcp_erp_timeout_init(erp_action); + ret = zfcp_fsf_exchange_port_data(erp_action, adapter, NULL); + if (ret == -EOPNOTSUPP) { + debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp"); + return ZFCP_ERP_SUCCEEDED; + } else if (ret) { + debug_text_event(adapter->erp_dbf, 3, "a_xport_failed"); + return ZFCP_ERP_FAILED; + } + debug_text_event(adapter->erp_dbf, 6, "a_xport_ok"); - if (retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES) { - sleep = ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP; - retries++; - } else - sleep = ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP; - schedule_timeout(sleep); - } while (1); + ret = ZFCP_ERP_SUCCEEDED; + down(&adapter->erp_ready_sem); + if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) { + ZFCP_LOG_INFO("error: exchange port data timed out (adapter " + "%s)\n", zfcp_get_busid_by_adapter(adapter)); + ret = ZFCP_ERP_FAILED; + } + if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status)) { + ZFCP_LOG_INFO("error: exchange port data failed (adapter " + "%s\n", zfcp_get_busid_by_adapter(adapter)); + ret = ZFCP_ERP_FAILED; + } - return ZFCP_ERP_SUCCEEDED; + return ret; } /* diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 9f0cb3d820c0..bd8cd4d46134 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -388,6 +388,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req) case FSF_PROT_LINK_DOWN: zfcp_fsf_link_down_info_eval(adapter, &prot_status_qual->link_down_info); + zfcp_erp_adapter_reopen(adapter, 0); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -558,10 +559,8 @@ zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter, atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status); - if (link_down == NULL) { - zfcp_erp_adapter_reopen(adapter, 0); - return; - } + if (link_down == NULL) + goto out; switch (link_down->error_code) { case FSF_PSQ_LINK_NO_LIGHT: @@ -643,16 +642,8 @@ zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter, link_down->explanation_code, link_down->vendor_specific_code); - switch (link_down->error_code) { - case FSF_PSQ_LINK_NO_LIGHT: - case FSF_PSQ_LINK_WRAP_PLUG: - case FSF_PSQ_LINK_NO_FCP: - case FSF_PSQ_LINK_FIRMWARE_UPDATE: - zfcp_erp_adapter_reopen(adapter, 0); - break; - default: - zfcp_erp_adapter_failed(adapter); - } + out: + zfcp_erp_adapter_failed(adapter); } /* @@ -2304,6 +2295,35 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action, return retval; } +/** + * zfcp_fsf_exchange_port_evaluate + * @fsf_req: fsf_req which belongs to xchg port data request + * @xchg_ok: specifies if xchg port data was incomplete or complete (0/1) + */ +static void +zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) +{ + struct zfcp_adapter *adapter; + struct fsf_qtcb *qtcb; + struct fsf_qtcb_bottom_port *bottom, *data; + struct Scsi_Host *shost; + + adapter = fsf_req->adapter; + qtcb = fsf_req->qtcb; + bottom = &qtcb->bottom.port; + shost = adapter->scsi_host; + + 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) + 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; +} /** * zfcp_fsf_exchange_port_data_handler - handler for exchange_port_data request @@ -2312,38 +2332,26 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action, static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req) { - struct zfcp_adapter *adapter = fsf_req->adapter; - struct Scsi_Host *shost = adapter->scsi_host; - struct fsf_qtcb *qtcb = fsf_req->qtcb; - struct fsf_qtcb_bottom_port *bottom, *data; + struct zfcp_adapter *adapter; + struct fsf_qtcb *qtcb; + + adapter = fsf_req->adapter; + qtcb = fsf_req->qtcb; if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) return; switch (qtcb->header.fsf_status) { case FSF_GOOD: + zfcp_fsf_exchange_port_evaluate(fsf_req, 1); atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); - - bottom = &qtcb->bottom.port; - 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) - 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: + zfcp_fsf_exchange_port_evaluate(fsf_req, 0); atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); - zfcp_fsf_link_down_info_eval(adapter, &qtcb->header.fsf_status_qual.link_down_info); break; - default: debug_text_event(adapter->erp_dbf, 0, "xchg-port-ng"); debug_event(adapter->erp_dbf, 0, -- cgit v1.2.3 From ed829ad607a9c334cea490d3a8c0f874153fb42d Mon Sep 17 00:00:00 2001 From: Maxim Shchetynin Date: Sat, 11 Feb 2006 01:42:58 +0100 Subject: [SCSI] zfcp: fix logging during device reset Avoid access to old fsf_requests if device reset is logged. Signed-off-by: Maxim Shchetynin Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_dbf.c | 76 +++++++++++++++++-------------------------- drivers/s390/scsi/zfcp_def.h | 6 +--- drivers/s390/scsi/zfcp_ext.h | 5 +-- drivers/s390/scsi/zfcp_fsf.c | 6 ++-- drivers/s390/scsi/zfcp_scsi.c | 15 ++++++--- 5 files changed, 47 insertions(+), 61 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index 4d7d47cf2394..a5f2ba9a8fdb 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -710,10 +710,9 @@ static inline void _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level, struct zfcp_adapter *adapter, struct scsi_cmnd *scsi_cmnd, - struct zfcp_fsf_req *new_fsf_req) + struct zfcp_fsf_req *fsf_req, + struct zfcp_fsf_req *old_fsf_req) { - struct zfcp_fsf_req *fsf_req = - (struct zfcp_fsf_req *)scsi_cmnd->host_scribble; struct zfcp_scsi_dbf_record *rec = &adapter->scsi_dbf_buf; struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec; unsigned long flags; @@ -727,19 +726,20 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level, if (offset == 0) { strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE); strncpy(rec->tag2, tag2, ZFCP_DBF_TAG_SIZE); - if (scsi_cmnd->device) { - rec->scsi_id = scsi_cmnd->device->id; - rec->scsi_lun = scsi_cmnd->device->lun; + if (scsi_cmnd != NULL) { + if (scsi_cmnd->device) { + rec->scsi_id = scsi_cmnd->device->id; + rec->scsi_lun = scsi_cmnd->device->lun; + } + rec->scsi_result = scsi_cmnd->result; + rec->scsi_cmnd = (unsigned long)scsi_cmnd; + rec->scsi_serial = scsi_cmnd->serial_number; + memcpy(rec->scsi_opcode, &scsi_cmnd->cmnd, + min((int)scsi_cmnd->cmd_len, + ZFCP_DBF_SCSI_OPCODE)); + rec->scsi_retries = scsi_cmnd->retries; + rec->scsi_allowed = scsi_cmnd->allowed; } - rec->scsi_result = scsi_cmnd->result; - rec->scsi_cmnd = (unsigned long)scsi_cmnd; - rec->scsi_serial = scsi_cmnd->serial_number; - memcpy(rec->scsi_opcode, - &scsi_cmnd->cmnd, - min((int)scsi_cmnd->cmd_len, - ZFCP_DBF_SCSI_OPCODE)); - rec->scsi_retries = scsi_cmnd->retries; - rec->scsi_allowed = scsi_cmnd->allowed; if (fsf_req != NULL) { fcp_rsp = (struct fcp_rsp_iu *) &(fsf_req->qtcb->bottom.io.fcp_rsp); @@ -772,15 +772,8 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level, rec->fsf_seqno = fsf_req->seq_no; rec->fsf_issued = fsf_req->issued; } - if (new_fsf_req != NULL) { - rec->type.new_fsf_req.fsf_reqid = - (unsigned long) - new_fsf_req; - rec->type.new_fsf_req.fsf_seqno = - new_fsf_req->seq_no; - rec->type.new_fsf_req.fsf_issued = - new_fsf_req->issued; - } + rec->type.old_fsf_reqid = + (unsigned long) old_fsf_req; } else { strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE); dump->total_size = buflen; @@ -801,19 +794,21 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level, inline void zfcp_scsi_dbf_event_result(const char *tag, int level, struct zfcp_adapter *adapter, - struct scsi_cmnd *scsi_cmnd) + struct scsi_cmnd *scsi_cmnd, + struct zfcp_fsf_req *fsf_req) { - _zfcp_scsi_dbf_event_common("rslt", - tag, level, adapter, scsi_cmnd, NULL); + _zfcp_scsi_dbf_event_common("rslt", tag, level, + adapter, scsi_cmnd, fsf_req, NULL); } inline void zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter, struct scsi_cmnd *scsi_cmnd, - struct zfcp_fsf_req *new_fsf_req) + struct zfcp_fsf_req *new_fsf_req, + struct zfcp_fsf_req *old_fsf_req) { - _zfcp_scsi_dbf_event_common("abrt", - tag, 1, adapter, scsi_cmnd, new_fsf_req); + _zfcp_scsi_dbf_event_common("abrt", tag, 1, + adapter, scsi_cmnd, new_fsf_req, old_fsf_req); } inline void @@ -823,7 +818,7 @@ zfcp_scsi_dbf_event_devreset(const char *tag, u8 flag, struct zfcp_unit *unit, struct zfcp_adapter *adapter = unit->port->adapter; _zfcp_scsi_dbf_event_common(flag == FCP_TARGET_RESET ? "trst" : "lrst", - tag, 1, adapter, scsi_cmnd, NULL); + tag, 1, adapter, scsi_cmnd, NULL, NULL); } static int @@ -856,6 +851,10 @@ zfcp_scsi_dbf_view_format(debug_info_t * id, struct debug_view *view, rec->scsi_retries); len += zfcp_dbf_view(out_buf + len, "scsi_allowed", "0x%02x", rec->scsi_allowed); + if (strncmp(rec->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0) { + len += zfcp_dbf_view(out_buf + len, "old_fsf_reqid", "0x%0Lx", + rec->type.old_fsf_reqid); + } len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx", rec->fsf_reqid); len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x", @@ -883,21 +882,6 @@ zfcp_scsi_dbf_view_format(debug_info_t * id, struct debug_view *view, min((int)rec->type.fcp.sns_info_len, ZFCP_DBF_SCSI_FCP_SNS_INFO), 0, rec->type.fcp.sns_info_len); - } else if (strncmp(rec->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0) { - len += zfcp_dbf_view(out_buf + len, "fsf_reqid_abort", "0x%0Lx", - rec->type.new_fsf_req.fsf_reqid); - len += zfcp_dbf_view(out_buf + len, "fsf_seqno_abort", "0x%08x", - rec->type.new_fsf_req.fsf_seqno); - len += zfcp_dbf_stck(out_buf + len, "fsf_issued", - rec->type.new_fsf_req.fsf_issued); - } else if ((strncmp(rec->tag, "trst", ZFCP_DBF_TAG_SIZE) == 0) || - (strncmp(rec->tag, "lrst", ZFCP_DBF_TAG_SIZE) == 0)) { - len += zfcp_dbf_view(out_buf + len, "fsf_reqid_reset", "0x%0Lx", - rec->type.new_fsf_req.fsf_reqid); - len += zfcp_dbf_view(out_buf + len, "fsf_seqno_reset", "0x%08x", - rec->type.new_fsf_req.fsf_seqno); - len += zfcp_dbf_stck(out_buf + len, "fsf_issued", - rec->type.new_fsf_req.fsf_issued); } len += sprintf(out_buf + len, "\n"); diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index f031199c7414..7f551d66f47f 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -424,11 +424,7 @@ struct zfcp_scsi_dbf_record { u32 fsf_seqno; u64 fsf_issued; union { - struct { - u64 fsf_reqid; - u32 fsf_seqno; - u64 fsf_issued; - } new_fsf_req; + u64 old_fsf_reqid; struct { u8 rsp_validity; u8 rsp_scsi_status; diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index c1ba7cf1b496..700f5402a978 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -194,9 +194,10 @@ extern void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *); extern void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *); extern void zfcp_scsi_dbf_event_result(const char *, int, struct zfcp_adapter *, - struct scsi_cmnd *); + struct scsi_cmnd *, + struct zfcp_fsf_req *); extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *, - struct scsi_cmnd *, + struct scsi_cmnd *, struct zfcp_fsf_req *, struct zfcp_fsf_req *); extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *, struct scsi_cmnd *); diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index bd8cd4d46134..662ec571d73b 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -4211,11 +4211,11 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req) ZFCP_LOG_DEBUG("scpnt->result =0x%x\n", scpnt->result); if (scpnt->result != 0) - zfcp_scsi_dbf_event_result("erro", 3, fsf_req->adapter, scpnt); + zfcp_scsi_dbf_event_result("erro", 3, fsf_req->adapter, scpnt, fsf_req); else if (scpnt->retries > 0) - zfcp_scsi_dbf_event_result("retr", 4, fsf_req->adapter, scpnt); + zfcp_scsi_dbf_event_result("retr", 4, fsf_req->adapter, scpnt, fsf_req); else - zfcp_scsi_dbf_event_result("norm", 6, fsf_req->adapter, scpnt); + zfcp_scsi_dbf_event_result("norm", 6, fsf_req->adapter, scpnt, fsf_req); /* cleanup pointer (need this especially for abort) */ scpnt->host_scribble = NULL; diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index e0803757c0fa..9f6b4d7a46f3 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -242,7 +242,7 @@ zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result) if ((scpnt->device != NULL) && (scpnt->device->host != NULL)) zfcp_scsi_dbf_event_result("fail", 4, (struct zfcp_adapter*) scpnt->device->host->hostdata[0], - scpnt); + scpnt, NULL); /* return directly */ scpnt->scsi_done(scpnt); } @@ -446,7 +446,7 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) old_fsf_req = (struct zfcp_fsf_req *) scpnt->host_scribble; if (!old_fsf_req) { write_unlock_irqrestore(&adapter->abort_lock, flags); - zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, new_fsf_req); + zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, NULL); retval = SUCCESS; goto out; } @@ -460,6 +460,8 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) adapter, unit, 0); if (!new_fsf_req) { ZFCP_LOG_INFO("error: initiation of Abort FCP Cmnd failed\n"); + zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL, + old_fsf_req); retval = FAILED; goto out; } @@ -470,13 +472,16 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) /* status should be valid since signals were not permitted */ if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) { - zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, new_fsf_req); + zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, new_fsf_req, + NULL); retval = SUCCESS; } else if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) { - zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, new_fsf_req); + zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, new_fsf_req, + NULL); retval = SUCCESS; } else { - zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, new_fsf_req); + zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, new_fsf_req, + NULL); retval = FAILED; } zfcp_fsf_req_free(new_fsf_req); -- cgit v1.2.3 From 61c41823c50302ca6cd455c48a1395f944c61f8f Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Sat, 11 Feb 2006 01:43:55 +0100 Subject: [SCSI] zfcp: fix: avoid race between fc_remote_port_add and scsi_add_device Flush workqueue of a scsi host after a remote port for that host is registered at the fc transport class. Otherwise immediate registration of a scsi device on that host is racy. Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_erp.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 8ed6fcb41653..e3c4bdd29a60 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -3415,6 +3415,8 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter, "(adapter %s, wwpn=0x%016Lx)\n", zfcp_get_busid_by_port(port), port->wwpn); + else + scsi_flush_work(adapter->scsi_host); } zfcp_port_put(port); break; -- cgit v1.2.3 From e2230eac17486e2ee07091d54d898eb40bcd0fdd Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Sun, 12 Feb 2006 09:28:19 -0700 Subject: [SCSI] sym2: Mask off opcode from RBC pm->sg.size is set from the Residual Byte Count register. However, the upper byte of the RBC is the opcode of the instruction that was executing, so we need to mask it off. This fixes some spurious rejects of IGNORE WIDE RESIDUE messages. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley --- drivers/scsi/sym53c8xx_2/sym_hipd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index 8260f040d39c..f4854c33f48d 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -3588,7 +3588,7 @@ static int sym_evaluate_dp(struct sym_hcb *np, struct sym_ccb *cp, u32 scr, int if (pm) { dp_scr = scr_to_cpu(pm->ret); - dp_ofs -= scr_to_cpu(pm->sg.size); + dp_ofs -= scr_to_cpu(pm->sg.size) & 0x00ffffff; } /* -- cgit v1.2.3 From 8f6da52aeff1fd7272ff5082552a39c050565b57 Mon Sep 17 00:00:00 2001 From: Jesse Allen Date: Sun, 12 Feb 2006 14:34:56 -0800 Subject: [PATCH] orinoco: support smc2532w The orinoco wireless driver can support the SMC 2532W-B PC Card, so add the id for it. Signed-off-by: Jesse Allen Cc: Pavel Roskin Cc: David Gibson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/wireless/orinoco_cs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index 3c128b692bce..ec6f2a48895b 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c @@ -590,6 +590,7 @@ static struct pcmcia_device_id orinoco_cs_ids[] = { PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9), PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26), PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b), + PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2532W-B EliteConnect Wireless Adapter", 0xc4f8b18b, 0x196bd757), PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a), PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e), PCMCIA_DEVICE_PROD_ID123("The Linksys Group, Inc.", "Instant Wireless Network PC Card", "ISL37300P", 0xa5f472c2, 0x590eb502, 0xc9049a39), -- cgit v1.2.3 From 9225806386e398eeba46958a7befa017bda73f58 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 13 Feb 2006 11:40:07 +0100 Subject: [Bluetooth] Fix firmware loading problem of BT3C driver Before the PCMCIA subsystem was fully integrated into the device and driver model, the BT3C driver had to workaround this when loading the firmware. This workaround is broken and makes the driver oops when loading the firmware. This patch removes this workaround and uses now the provided device structure from the PCMCIA subsystem. Signed-off-by: Marcel Holtmann --- drivers/bluetooth/bt3c_cs.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index e522d19ad886..7e21b1ff27c4 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -474,18 +474,6 @@ static int bt3c_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long /* ======================== Card services HCI interaction ======================== */ -static struct device *bt3c_device(void) -{ - static struct device dev = { - .bus_id = "pcmcia", - }; - kobject_set_name(&dev.kobj, "bt3c"); - kobject_init(&dev.kobj); - - return &dev; -} - - static int bt3c_load_firmware(bt3c_info_t *info, unsigned char *firmware, int count) { char *ptr = (char *) firmware; @@ -574,6 +562,7 @@ static int bt3c_open(bt3c_info_t *info) { const struct firmware *firmware; struct hci_dev *hdev; + client_handle_t handle; int err; spin_lock_init(&(info->lock)); @@ -605,8 +594,10 @@ static int bt3c_open(bt3c_info_t *info) hdev->owner = THIS_MODULE; + handle = info->link.handle; + /* Load firmware */ - err = request_firmware(&firmware, "BT3CPCC.bin", bt3c_device()); + err = request_firmware(&firmware, "BT3CPCC.bin", &handle_to_dev(handle)); if (err < 0) { BT_ERR("Firmware request failed"); goto error; -- cgit v1.2.3 From 75c0141ca2fdae7c332d8f17412fbe0939dd005f Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 13 Feb 2006 12:46:58 -0500 Subject: [PATCH] Remove "RV370 5B60 [Radeon X300 (PCIE)]" from DRI list I get a machine check exception, triple fault, or NMI watchdog lockup when DRI gets enabled on this card. (And Mauro Tassinari reports hung kernels too in http://lkml.org/lkml/2006/1/26/97) [ Adrian Bunk also states that this is the only RV350 entry for an RV370 in our lists, which implies that it's just buggy ] Cc: Adrian Bunk Cc: Dave Jones Cc: Mauro Tassinari Cc: Dave Airlie Signed-off-by: Linus Torvalds --- drivers/char/drm/drm_pciids.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h index 8fd6357a48da..2c17e88a8847 100644 --- a/drivers/char/drm/drm_pciids.h +++ b/drivers/char/drm/drm_pciids.h @@ -85,7 +85,6 @@ {0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ {0x1002, 0x596A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ {0x1002, 0x596B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ - {0x1002, 0x5b60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ {0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \ {0x1002, 0x5c62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ {0x1002, 0x5c63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \ -- cgit v1.2.3 From 7d2babc4874825027848db04d11784070da4456d Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 13 Feb 2006 12:19:44 -0800 Subject: IB/mthca: bump driver version and release date Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_dev.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h index 2a165fd06e57..e481037288d6 100644 --- a/drivers/infiniband/hw/mthca/mthca_dev.h +++ b/drivers/infiniband/hw/mthca/mthca_dev.h @@ -53,8 +53,8 @@ #define DRV_NAME "ib_mthca" #define PFX DRV_NAME ": " -#define DRV_VERSION "0.06" -#define DRV_RELDATE "June 23, 2005" +#define DRV_VERSION "0.07" +#define DRV_RELDATE "February 13, 2006" enum { MTHCA_FLAG_DDR_HIDDEN = 1 << 1, -- cgit v1.2.3 From 72fb630dad170084026bda6728b8d8f21ed48ff1 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 13 Feb 2006 15:53:41 -0800 Subject: [APPLETALK]: warning fix drivers/net/appletalk/cops.c: In function `cops_load': drivers/net/appletalk/cops.c:539: warning: assignment discards qualifiers from pointer target type drivers/net/appletalk/cops.c:547: warning: assignment discards qualifiers from pointer target type Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/net/appletalk/cops.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/appletalk/cops.h b/drivers/net/appletalk/cops.h index c68ba9c2ef46..fd2750b269c8 100644 --- a/drivers/net/appletalk/cops.h +++ b/drivers/net/appletalk/cops.h @@ -51,7 +51,7 @@ struct ltfirmware { unsigned int length; - unsigned char * data; + const unsigned char *data; }; #define DAYNA 1 -- cgit v1.2.3 From a38408cd8d6bc0e5d16e609d4b1fdf9ba2e099ce Mon Sep 17 00:00:00 2001 From: David Brownell Date: Thu, 9 Feb 2006 16:35:31 -0500 Subject: [PATCH] USB: fix up the usb early handoff logic for EHCI Disable some dubious "early" USB handoff code that allegedly works around bugs on some systems (we don't know which ones) but rudely breaks some others. Also make the kernel warnings reporting BIOS handoff problems be more useful, reporting the register whose value displays the trouble. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/pci-quirks.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index e9e5bc178cef..118288d94423 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -191,8 +191,9 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) } if (wait_time <= 0) printk(KERN_WARNING "%s %s: BIOS handoff " - "failed (BIOS bug ?)\n", - pdev->dev.bus_id, "OHCI"); + "failed (BIOS bug ?) %08x\n", + pdev->dev.bus_id, "OHCI", + readl(base + OHCI_CONTROL)); /* reset controller, preserving RWC */ writel(control & OHCI_CTRL_RWC, base + OHCI_CONTROL); @@ -243,6 +244,12 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) pr_debug("%s %s: BIOS handoff\n", pdev->dev.bus_id, "EHCI"); +#if 0 +/* aleksey_gorelov@phoenix.com reports that some systems need SMI forced on, + * but that seems dubious in general (the BIOS left it off intentionally) + * and is known to prevent some systems from booting. so we won't do this + * unless maybe we can determine when we're on a system that needs SMI forced. + */ /* BIOS workaround (?): be sure the * pre-Linux code receives the SMI */ @@ -252,6 +259,7 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) pci_write_config_dword(pdev, offset + EHCI_USBLEGCTLSTS, val | EHCI_USBLEGCTLSTS_SOOE); +#endif } /* always say Linux will own the hardware @@ -274,8 +282,8 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) * it down, and hope nothing goes too wrong */ printk(KERN_WARNING "%s %s: BIOS handoff " - "failed (BIOS bug ?)\n", - pdev->dev.bus_id, "EHCI"); + "failed (BIOS bug ?) %08x\n", + pdev->dev.bus_id, "EHCI", cap); pci_write_config_byte(pdev, offset + 2, 0); } -- cgit v1.2.3 From ba3e66e94b9fb8c2a370a90729e068314845549d Mon Sep 17 00:00:00 2001 From: Michael Hund Date: Thu, 2 Feb 2006 09:36:43 +0100 Subject: [PATCH] USB: add new device ids to ldusb Signed-off-by: Michael Hund Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/hid-core.c | 50 +++++++++++++++++++++----------------- drivers/usb/misc/ldusb.c | 57 +++++++++++++++++++++++++------------------- 2 files changed, 60 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 6f7a684c3e07..772478086bd3 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -1435,17 +1435,20 @@ void hid_init_reports(struct hid_device *hid) #define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004 #define USB_VENDOR_ID_LD 0x0f11 -#define USB_DEVICE_ID_CASSY 0x1000 -#define USB_DEVICE_ID_POCKETCASSY 0x1010 -#define USB_DEVICE_ID_MOBILECASSY 0x1020 -#define USB_DEVICE_ID_JWM 0x1080 -#define USB_DEVICE_ID_DMMP 0x1081 -#define USB_DEVICE_ID_UMIP 0x1090 -#define USB_DEVICE_ID_VIDEOCOM 0x1200 -#define USB_DEVICE_ID_COM3LAB 0x2000 -#define USB_DEVICE_ID_TELEPORT 0x2010 -#define USB_DEVICE_ID_NETWORKANALYSER 0x2020 -#define USB_DEVICE_ID_POWERCONTROL 0x2030 +#define USB_DEVICE_ID_LD_CASSY 0x1000 +#define USB_DEVICE_ID_LD_POCKETCASSY 0x1010 +#define USB_DEVICE_ID_LD_MOBILECASSY 0x1020 +#define USB_DEVICE_ID_LD_JWM 0x1080 +#define USB_DEVICE_ID_LD_DMMP 0x1081 +#define USB_DEVICE_ID_LD_UMIP 0x1090 +#define USB_DEVICE_ID_LD_XRAY1 0x1100 +#define USB_DEVICE_ID_LD_XRAY2 0x1101 +#define USB_DEVICE_ID_LD_VIDEOCOM 0x1200 +#define USB_DEVICE_ID_LD_COM3LAB 0x2000 +#define USB_DEVICE_ID_LD_TELEPORT 0x2010 +#define USB_DEVICE_ID_LD_NETWORKANALYSER 0x2020 +#define USB_DEVICE_ID_LD_POWERCONTROL 0x2030 +#define USB_DEVICE_ID_LD_MACHINETEST 0x2040 #define USB_VENDOR_ID_APPLE 0x05ac #define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304 @@ -1491,17 +1494,20 @@ static const struct hid_blacklist { { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_LD, USB_DEVICE_ID_CASSY, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_LD, USB_DEVICE_ID_POCKETCASSY, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_LD, USB_DEVICE_ID_MOBILECASSY, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_LD, USB_DEVICE_ID_JWM, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_LD, USB_DEVICE_ID_DMMP, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_LD, USB_DEVICE_ID_UMIP, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_LD, USB_DEVICE_ID_VIDEOCOM, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_LD, USB_DEVICE_ID_COM3LAB, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_LD, USB_DEVICE_ID_TELEPORT, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_LD, USB_DEVICE_ID_NETWORKANALYSER, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_LD, USB_DEVICE_ID_POWERCONTROL, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY1, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY2, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_VIDEOCOM, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_COM3LAB, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_TELEPORT, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_NETWORKANALYSER, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERCONTROL, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE }, diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index 331d4ae949ed..e2d1198623eb 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c @@ -24,6 +24,7 @@ * V0.1 (mh) Initial version * V0.11 (mh) Added raw support for HID 1.0 devices (no interrupt out endpoint) * V0.12 (mh) Added kmalloc check for string buffer + * V0.13 (mh) Added support for LD X-Ray and Machine Test System */ #include @@ -40,17 +41,20 @@ /* Define these values to match your devices */ #define USB_VENDOR_ID_LD 0x0f11 /* USB Vendor ID of LD Didactic GmbH */ -#define USB_DEVICE_ID_CASSY 0x1000 /* USB Product ID for all CASSY-S modules */ -#define USB_DEVICE_ID_POCKETCASSY 0x1010 /* USB Product ID for Pocket-CASSY */ -#define USB_DEVICE_ID_MOBILECASSY 0x1020 /* USB Product ID for Mobile-CASSY */ -#define USB_DEVICE_ID_JWM 0x1080 /* USB Product ID for Joule and Wattmeter */ -#define USB_DEVICE_ID_DMMP 0x1081 /* USB Product ID for Digital Multimeter P (reserved) */ -#define USB_DEVICE_ID_UMIP 0x1090 /* USB Product ID for UMI P */ -#define USB_DEVICE_ID_VIDEOCOM 0x1200 /* USB Product ID for VideoCom */ -#define USB_DEVICE_ID_COM3LAB 0x2000 /* USB Product ID for COM3LAB */ -#define USB_DEVICE_ID_TELEPORT 0x2010 /* USB Product ID for Terminal Adapter */ -#define USB_DEVICE_ID_NETWORKANALYSER 0x2020 /* USB Product ID for Network Analyser */ -#define USB_DEVICE_ID_POWERCONTROL 0x2030 /* USB Product ID for Controlling device for Power Electronics */ +#define USB_DEVICE_ID_LD_CASSY 0x1000 /* USB Product ID of CASSY-S */ +#define USB_DEVICE_ID_LD_POCKETCASSY 0x1010 /* USB Product ID of Pocket-CASSY */ +#define USB_DEVICE_ID_LD_MOBILECASSY 0x1020 /* USB Product ID of Mobile-CASSY */ +#define USB_DEVICE_ID_LD_JWM 0x1080 /* USB Product ID of Joule and Wattmeter */ +#define USB_DEVICE_ID_LD_DMMP 0x1081 /* USB Product ID of Digital Multimeter P (reserved) */ +#define USB_DEVICE_ID_LD_UMIP 0x1090 /* USB Product ID of UMI P */ +#define USB_DEVICE_ID_LD_XRAY1 0x1100 /* USB Product ID of X-Ray Apparatus */ +#define USB_DEVICE_ID_LD_XRAY2 0x1101 /* USB Product ID of X-Ray Apparatus */ +#define USB_DEVICE_ID_LD_VIDEOCOM 0x1200 /* USB Product ID of VideoCom */ +#define USB_DEVICE_ID_LD_COM3LAB 0x2000 /* USB Product ID of COM3LAB */ +#define USB_DEVICE_ID_LD_TELEPORT 0x2010 /* USB Product ID of Terminal Adapter */ +#define USB_DEVICE_ID_LD_NETWORKANALYSER 0x2020 /* USB Product ID of Network Analyser */ +#define USB_DEVICE_ID_LD_POWERCONTROL 0x2030 /* USB Product ID of Converter Control Unit */ +#define USB_DEVICE_ID_LD_MACHINETEST 0x2040 /* USB Product ID of Machine Test System */ #define USB_VENDOR_ID_VERNIER 0x08f7 #define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 @@ -67,17 +71,20 @@ /* table of devices that work with this driver */ static struct usb_device_id ld_usb_table [] = { - { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_CASSY) }, - { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_POCKETCASSY) }, - { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_MOBILECASSY) }, - { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_JWM) }, - { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_DMMP) }, - { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_UMIP) }, - { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_VIDEOCOM) }, - { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_COM3LAB) }, - { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_TELEPORT) }, - { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_NETWORKANALYSER) }, - { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_POWERCONTROL) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY1) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY2) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_VIDEOCOM) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_COM3LAB) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_TELEPORT) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_NETWORKANALYSER) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERCONTROL) }, + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST) }, { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO) }, { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP) }, { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) }, @@ -85,7 +92,7 @@ static struct usb_device_id ld_usb_table [] = { { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, ld_usb_table); -MODULE_VERSION("V0.12"); +MODULE_VERSION("V0.13"); MODULE_AUTHOR("Michael Hund "); MODULE_DESCRIPTION("LD USB Driver"); MODULE_LICENSE("GPL"); @@ -632,8 +639,8 @@ static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id * /* workaround for early firmware versions on fast computers */ if ((le16_to_cpu(udev->descriptor.idVendor) == USB_VENDOR_ID_LD) && - ((le16_to_cpu(udev->descriptor.idProduct) == USB_DEVICE_ID_CASSY) || - (le16_to_cpu(udev->descriptor.idProduct) == USB_DEVICE_ID_COM3LAB)) && + ((le16_to_cpu(udev->descriptor.idProduct) == USB_DEVICE_ID_LD_CASSY) || + (le16_to_cpu(udev->descriptor.idProduct) == USB_DEVICE_ID_LD_COM3LAB)) && (le16_to_cpu(udev->descriptor.bcdDevice) <= 0x103)) { buffer = kmalloc(256, GFP_KERNEL); if (buffer == NULL) { -- cgit v1.2.3 From 343a65cadb3a6a102f08513d9c64eb7e317478f0 Mon Sep 17 00:00:00 2001 From: Michael Hund Date: Thu, 2 Feb 2006 09:37:02 +0100 Subject: [PATCH] USB: change ldusb's experimental state Signed-off-by: Michael Hund Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index 6649531fa824..8ba6a701e9c1 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -141,7 +141,7 @@ source "drivers/usb/misc/sisusbvga/Kconfig" config USB_LD tristate "USB LD driver" - depends on USB && EXPERIMENTAL + depends on USB help This driver is for generic USB devices that use interrupt transfers, like LD Didactic's USB devices. -- cgit v1.2.3 From c6c27721a42b991965bb792d5c196b8331d008d5 Mon Sep 17 00:00:00 2001 From: Christian Lindner Date: Wed, 1 Feb 2006 14:10:52 +0100 Subject: [PATCH] USB: PL2303: Leadtek 9531 GPS-Mouse The patch adds the USB ID (0413:2101) for the Leadtek GPS-Mouse 9531 to the driver pl2303. Signed-off-by: Christian Lindner Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/pl2303.c | 5 +++-- drivers/usb/serial/pl2303.h | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index e8e575e037c1..37c81c08faad 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -73,9 +73,10 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) }, { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X75) }, { USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) }, - { USB_DEVICE(NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID ) }, - { USB_DEVICE(CA_42_CA42_VENDOR_ID, CA_42_CA42_PRODUCT_ID ) }, + { USB_DEVICE(NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID) }, + { USB_DEVICE(CA_42_CA42_VENDOR_ID, CA_42_CA42_PRODUCT_ID) }, { USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_PRODUCT_ID) }, + { USB_DEVICE(LEADTEK_VENDOR_ID, LEADTEK_9531_PRODUCT_ID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index 1807087a76e3..9bc4755162ad 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -71,3 +71,7 @@ #define SAGEM_VENDOR_ID 0x079b #define SAGEM_PRODUCT_ID 0x0027 + +/* Leadtek GPS 9531 (ID 0413:2101) */ +#define LEADTEK_VENDOR_ID 0x0413 +#define LEADTEK_9531_PRODUCT_ID 0x2101 -- cgit v1.2.3 From a0c53f1dca10acc93462339cbd0bf24b10d60a13 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 6 Feb 2006 12:15:15 -0800 Subject: [PATCH] USB: sl811_cs needs platform_device conversion too The switchover to "platform_driver" from "device_driver" missed one rather essential usage, which broke the sl811_cs driver ... this resolves the omission. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/sl811_cs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c index 466384d7c79f..134d2000128a 100644 --- a/drivers/usb/host/sl811_cs.c +++ b/drivers/usb/host/sl811_cs.c @@ -101,7 +101,7 @@ static struct resource resources[] = { }, }; -extern struct device_driver sl811h_driver; +extern struct platform_driver sl811h_driver; static struct platform_device platform_dev = { .id = -1, @@ -132,7 +132,7 @@ static int sl811_hc_init(struct device *parent, ioaddr_t base_addr, int irq) * initialized already because of the link order dependency created * by referencing "sl811h_driver". */ - platform_dev.name = sl811h_driver.name; + platform_dev.name = sl811h_driver.driver.name; return platform_device_register(&platform_dev); } -- cgit v1.2.3 From a2149bce2535047371a1309f032f0320b05db791 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 2 Feb 2006 09:52:45 -0500 Subject: [PATCH] usb-storage: new unusual_devs entry This patch (as631) for unusual_devs.h fixes bugzilla entry 5913. Signed-off-by: Alan Stern Signed-off-by: Phil Dibowitz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index ee958f986eb8..c5d6d84b9b2b 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1162,6 +1162,13 @@ UNUSUAL_DEV( 0x55aa, 0xa103, 0x0000, 0x9999, US_FL_SINGLE_LUN), #endif +/* Reported by Andrew Simmons */ +UNUSUAL_DEV( 0xed06, 0x4500, 0x0001, 0x0001, + "DataStor", + "USB4500 FW1.04", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY), + /* Control/Bulk transport for all SubClass values */ USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR), USUAL_DEV(US_SC_8020, US_PR_CB, USB_US_TYPE_STOR), -- cgit v1.2.3 From ba3e93ad3c6e511f68c1b3e46954feff6cdd5a62 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 30 Jan 2006 10:19:43 -0500 Subject: [PATCH] usb-storage: unusual_devs entry Here is a new entry for unusual_devs.h (as630). Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index c5d6d84b9b2b..6e326159c2dd 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -946,6 +946,12 @@ UNUSUAL_DEV( 0x084d, 0x0011, 0x0110, 0x0110, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_BULK32), +/* Submitted by Jan De Luyck */ +UNUSUAL_DEV( 0x08bd, 0x1100, 0x0000, 0x0000, + "CITIZEN", + "X1DE-USB", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_SINGLE_LUN), /* Entry needed for flags. Moreover, all devices with this ID use * bulk-only transport, but _some_ falsely report Control/Bulk instead. -- cgit v1.2.3 From 1d614a4b0d2613d83f7bf0978e213ba29aebc44f Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 13 Feb 2006 10:15:22 -0500 Subject: [PATCH] USB: unusual_devs.h entry: TrekStor i.Beat A new unusual_devs.h entry (as651). Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 6e326159c2dd..1d8a739ccc96 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -106,6 +106,13 @@ UNUSUAL_DEV( 0x0411, 0x001c, 0x0113, 0x0113, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), +/* Reported by Christian Leber */ +UNUSUAL_DEV( 0x0419, 0xaaf5, 0x0100, 0x0100, + "TrekStor", + "i.Beat 115 2.0", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE | US_FL_NOT_LOCKABLE ), + /* Reported by Stefan Werner */ UNUSUAL_DEV( 0x0419, 0xaaf6, 0x0100, 0x0100, "TrekStor", -- cgit v1.2.3 From 982db2a127b29c9e1f5896d2ba691e84446cc858 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 13 Feb 2006 10:16:04 -0500 Subject: [PATCH] USB: unusual_devs.h entry: iAUDIO M5 Another unusual_devs.h entry (as652). Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 1d8a739ccc96..7e1cb03c2ed7 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1098,6 +1098,13 @@ UNUSUAL_DEV( 0x0dda, 0x0301, 0x0012, 0x0012, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), +/* Reported by Jim McCloskey */ +UNUSUAL_DEV( 0x0e21, 0x0520, 0x0100, 0x0100, + "Cowon Systems", + "iAUDIO M5", + US_SC_DEVICE, US_PR_BULK, NULL, + 0 ), + /* Submitted by Antoine Mairesse */ UNUSUAL_DEV( 0x0ed1, 0x6660, 0x0100, 0x0300, "USB", -- cgit v1.2.3 From 16f05be7be0bf121491d83bd97337fe179b3b323 Mon Sep 17 00:00:00 2001 From: Phil Dibowitz Date: Mon, 13 Feb 2006 15:59:42 -0800 Subject: [PATCH] USB: unusual-devs bugfix The following patch looks good to me. It adds an unusual_devs entry as well as fixing an ordering bug. Please apply. From: Bohdan Linda Signed-off-by: Phil Dibowitz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 7e1cb03c2ed7..e71c5ca1a07b 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -134,6 +134,14 @@ UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100, US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ), #endif +/* Patch submitted by Daniel Drake + * Device reports nonsense bInterfaceProtocol 6 when connected over USB2 */ +UNUSUAL_DEV( 0x0451, 0x5416, 0x0100, 0x0100, + "Neuros Audio", + "USB 2.0 HD 2.5", + US_SC_DEVICE, US_PR_BULK, NULL, + US_FL_NEED_OVERRIDE ), + /* * Pete Zaitcev , from Patrick C. F. Ernzer, bz#162559. * The key does not actually break, but it returns zero sense which @@ -144,13 +152,16 @@ UNUSUAL_DEV( 0x0457, 0x0150, 0x0100, 0x0100, "USB Mass Storage Device", US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ), -/* Patch submitted by Daniel Drake - * Device reports nonsense bInterfaceProtocol 6 when connected over USB2 */ -UNUSUAL_DEV( 0x0451, 0x5416, 0x0100, 0x0100, - "Neuros Audio", - "USB 2.0 HD 2.5", - US_SC_DEVICE, US_PR_BULK, NULL, - US_FL_NEED_OVERRIDE ), +/* +* Bohdan Linda +* 1GB USB sticks MyFlash High Speed. I have restricted +* the revision to my model only +*/ +UNUSUAL_DEV( 0x0457, 0x0151, 0x0100, 0x0100, + "USB 2.0", + "Flash Disk", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_NOT_LOCKABLE ), UNUSUAL_DEV( 0x045a, 0x5210, 0x0101, 0x0101, "Rio", -- cgit v1.2.3 From e3efa5a7392e07471b5d0ef7e7cd7ab862f70284 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 5 Feb 2006 23:11:16 +0100 Subject: [PATCH] vt8231: Fix sysfs temperature interface The VT8231 low temperature limits are actually hysteresis temperatures to the high limits. Signed-off-by: Jean Delvare Cc: Roger Lucas Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/vt8231.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c index 3eb08f004c0f..271e9cb9532c 100644 --- a/drivers/hwmon/vt8231.c +++ b/drivers/hwmon/vt8231.c @@ -437,12 +437,12 @@ static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ show_temp, NULL, offset - 1); \ static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ show_temp_max, set_temp_max, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ +static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \ show_temp_min, set_temp_min, offset - 1) static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp0, NULL); static DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp0_max, set_temp0_max); -static DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR, show_temp0_min, set_temp0_min); +static DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp0_min, set_temp0_min); define_temperature_sysfs(2); define_temperature_sysfs(3); @@ -451,7 +451,7 @@ define_temperature_sysfs(5); define_temperature_sysfs(6); #define CFG_INFO_TEMP(id) { &sensor_dev_attr_temp##id##_input.dev_attr, \ - &sensor_dev_attr_temp##id##_min.dev_attr, \ + &sensor_dev_attr_temp##id##_max_hyst.dev_attr, \ &sensor_dev_attr_temp##id##_max.dev_attr } #define CFG_INFO_VOLT(id) { &sensor_dev_attr_in##id##_input.dev_attr, \ &sensor_dev_attr_in##id##_min.dev_attr, \ @@ -464,7 +464,7 @@ struct str_device_attr_table { }; static struct str_device_attr_table cfg_info_temp[] = { - { &dev_attr_temp1_input, &dev_attr_temp1_min, &dev_attr_temp1_max }, + { &dev_attr_temp1_input, &dev_attr_temp1_max_hyst, &dev_attr_temp1_max }, CFG_INFO_TEMP(2), CFG_INFO_TEMP(3), CFG_INFO_TEMP(4), -- cgit v1.2.3 From c7f5d7edd8b3fa4204389efc4c9081cc90a811d2 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 5 Feb 2006 23:13:48 +0100 Subject: [PATCH] w83781d: Use real-time status registers Use the real-time status registers of the Winbond W83782D, W83783S and W83627HF chips, instead of the interrupt status registers. Interrupts cannot be trusted at least for voltage inputs, as they are two-times triggers (as opposed to comparator mode, which we want.) The w83627hf driver was fixed in a similar way some times ago. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/w83781d.c | 43 +++++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index 557114872f3c..64c1f8af5bb2 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -95,11 +95,16 @@ MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization"); (0x39))) #define W83781D_REG_CONFIG 0x40 + +/* Interrupt status (W83781D, AS99127F) */ #define W83781D_REG_ALARM1 0x41 #define W83781D_REG_ALARM2 0x42 -#define W83781D_REG_ALARM3 0x450 /* not on W83781D */ -#define W83781D_REG_IRQ 0x4C +/* Real-time status (W83782D, W83783S, W83627HF) */ +#define W83782D_REG_ALARM1 0x459 +#define W83782D_REG_ALARM2 0x45A +#define W83782D_REG_ALARM3 0x45B + #define W83781D_REG_BEEP_CONFIG 0x4D #define W83781D_REG_BEEP_INTS1 0x56 #define W83781D_REG_BEEP_INTS2 0x57 @@ -1513,15 +1518,6 @@ w83781d_init_client(struct i2c_client *client) W83781D_REG_TEMP3_CONFIG, tmp & 0xfe); } } - - if (type != w83781d) { - /* enable comparator mode for temp2 and temp3 so - alarm indication will work correctly */ - i = w83781d_read_value(client, W83781D_REG_IRQ); - if (!(i & 0x40)) - w83781d_write_value(client, W83781D_REG_IRQ, - i | 0x40); - } } /* Start monitoring */ @@ -1612,14 +1608,25 @@ static struct w83781d_data *w83781d_update_device(struct device *dev) data->fan_div[1] |= (i >> 4) & 0x04; data->fan_div[2] |= (i >> 5) & 0x04; } - data->alarms = - w83781d_read_value(client, - W83781D_REG_ALARM1) + - (w83781d_read_value(client, W83781D_REG_ALARM2) << 8); if ((data->type == w83782d) || (data->type == w83627hf)) { - data->alarms |= - w83781d_read_value(client, - W83781D_REG_ALARM3) << 16; + data->alarms = w83781d_read_value(client, + W83782D_REG_ALARM1) + | (w83781d_read_value(client, + W83782D_REG_ALARM2) << 8) + | (w83781d_read_value(client, + W83782D_REG_ALARM3) << 16); + } else if (data->type == w83783s) { + data->alarms = w83781d_read_value(client, + W83782D_REG_ALARM1) + | (w83781d_read_value(client, + W83782D_REG_ALARM2) << 8); + } else { + /* No real-time status registers, fall back to + interrupt status registers */ + data->alarms = w83781d_read_value(client, + W83781D_REG_ALARM1) + | (w83781d_read_value(client, + W83781D_REG_ALARM2) << 8); } i = w83781d_read_value(client, W83781D_REG_BEEP_INTS2); data->beep_enable = i >> 7; -- cgit v1.2.3 From be79c383254cd3eb50953d8c0a7cacdbf6db31c0 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 7 Feb 2006 17:53:32 +0100 Subject: [PATCH] it87: Fix oops on removal Fix an oops on it87 module removal when no supported hardware was found. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/it87.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index e87d52c59940..d7a9401600bb 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -1186,7 +1186,8 @@ static int __init sm_it87_init(void) static void __exit sm_it87_exit(void) { - i2c_isa_del_driver(&it87_isa_driver); + if (isa_address) + i2c_isa_del_driver(&it87_isa_driver); i2c_del_driver(&it87_driver); } -- cgit v1.2.3 From 41d9c98fe76298cebc5907bcebfb2db28017a277 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 8 Feb 2006 20:38:29 +0100 Subject: [PATCH] i2c: Drop outdated probe/remove code in i2c-isa Probe and remove methods are now defined at bus level. No more need to redefine them at driver level in i2c-isa. This lets us get rid of these annoying messages: Driver 'it87-isa' needs updating - please use bus_type methods Thanks to Nicolas Mailhot for reporting the problem and testing the fix. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-isa.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c index 9f2ffef4d812..4344ae6b1fcb 100644 --- a/drivers/i2c/busses/i2c-isa.c +++ b/drivers/i2c/busses/i2c-isa.c @@ -72,16 +72,6 @@ static ssize_t show_adapter_name(struct device *dev, } static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL); -static int i2c_isa_device_probe(struct device *dev) -{ - return -ENODEV; -} - -static int i2c_isa_device_remove(struct device *dev) -{ - return 0; -} - /* We implement an interface which resembles i2c_{add,del}_driver, but for i2c-isa drivers. We don't have to remember and handle lists @@ -93,8 +83,6 @@ int i2c_isa_add_driver(struct i2c_driver *driver) /* Add the driver to the list of i2c drivers in the driver core */ driver->driver.bus = &i2c_bus_type; - driver->driver.probe = i2c_isa_device_probe; - driver->driver.remove = i2c_isa_device_remove; res = driver_register(&driver->driver); if (res) return res; -- cgit v1.2.3 From faead26d7a06605add627f29aee73ba654ce11f9 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 14 Feb 2006 10:42:07 -0600 Subject: [PATCH] add scsi_execute_in_process_context() API We have several points in the SCSI stack (primarily for our device functions) where we need to guarantee process context, but (given the place where the last reference was released) we cannot guarantee this. This API gets around the issue by executing the function directly if the caller has process context, but scheduling a workqueue to execute in process context if the caller doesn't have it. Unfortunately, it requires memory allocation in interrupt context, but it's better than what we have previously. The true solution will require a bit of re-engineering, so isn't appropriate for 2.6.16. Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 4a602853a98e..4362dcde74af 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -2248,3 +2249,61 @@ scsi_target_unblock(struct device *dev) device_for_each_child(dev, NULL, target_unblock); } EXPORT_SYMBOL_GPL(scsi_target_unblock); + + +struct work_queue_work { + struct work_struct work; + void (*fn)(void *); + void *data; +}; + +static void execute_in_process_context_work(void *data) +{ + void (*fn)(void *data); + struct work_queue_work *wqw = data; + + fn = wqw->fn; + data = wqw->data; + + kfree(wqw); + + fn(data); +} + +/** + * scsi_execute_in_process_context - reliably execute the routine with user context + * @fn: the function to execute + * @data: data to pass to the function + * + * Executes the function immediately if process context is available, + * otherwise schedules the function for delayed execution. + * + * Returns: 0 - function was executed + * 1 - function was scheduled for execution + * <0 - error + */ +int scsi_execute_in_process_context(void (*fn)(void *data), void *data) +{ + struct work_queue_work *wqw; + + if (!in_interrupt()) { + fn(data); + return 0; + } + + wqw = kmalloc(sizeof(struct work_queue_work), GFP_ATOMIC); + + if (unlikely(!wqw)) { + printk(KERN_ERR "Failed to allocate memory\n"); + WARN_ON(1); + return -ENOMEM; + } + + INIT_WORK(&wqw->work, execute_in_process_context_work, wqw); + wqw->fn = fn; + wqw->data = data; + schedule_work(&wqw->work); + + return 1; +} +EXPORT_SYMBOL_GPL(scsi_execute_in_process_context); -- cgit v1.2.3 From 65110b2168950a19cc78b5027ed18cb811fbdae8 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 14 Feb 2006 10:48:46 -0600 Subject: [SCSI] fix wrong context bugs in SCSI There's a bug in releasing scsi_device where the release function actually frees the block queue. However, the block queue release calls flush_work(), which requires process context (the scsi_device structure may release from irq context). Update the release function to invoke via the execute_in_process_context() API. Also clean up the scsi_target structure releasing via this API. Signed-off-by: James Bottomley --- drivers/scsi/scsi_scan.c | 26 ++++---------------------- drivers/scsi/scsi_sysfs.c | 9 ++++++++- 2 files changed, 12 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 752fb5da3de4..5acb83ca5ae5 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -387,19 +387,12 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, return found_target; } -struct work_queue_wrapper { - struct work_struct work; - struct scsi_target *starget; -}; - -static void scsi_target_reap_work(void *data) { - struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data; - struct scsi_target *starget = wqw->starget; +static void scsi_target_reap_usercontext(void *data) +{ + struct scsi_target *starget = data; struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); unsigned long flags; - kfree(wqw); - spin_lock_irqsave(shost->host_lock, flags); if (--starget->reap_ref == 0 && list_empty(&starget->devices)) { @@ -428,18 +421,7 @@ static void scsi_target_reap_work(void *data) { */ void scsi_target_reap(struct scsi_target *starget) { - struct work_queue_wrapper *wqw = - kzalloc(sizeof(struct work_queue_wrapper), GFP_ATOMIC); - - if (!wqw) { - starget_printk(KERN_ERR, starget, - "Failed to allocate memory in scsi_reap_target()\n"); - return; - } - - INIT_WORK(&wqw->work, scsi_target_reap_work, wqw); - wqw->starget = starget; - schedule_work(&wqw->work); + scsi_execute_in_process_context(scsi_target_reap_usercontext, starget); } /** diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index a77b32deaf8f..902a5def8e62 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -217,8 +217,9 @@ static void scsi_device_cls_release(struct class_device *class_dev) put_device(&sdev->sdev_gendev); } -static void scsi_device_dev_release(struct device *dev) +static void scsi_device_dev_release_usercontext(void *data) { + struct device *dev = data; struct scsi_device *sdev; struct device *parent; struct scsi_target *starget; @@ -237,6 +238,7 @@ static void scsi_device_dev_release(struct device *dev) if (sdev->request_queue) { sdev->request_queue->queuedata = NULL; + /* user context needed to free queue */ scsi_free_queue(sdev->request_queue); /* temporary expedient, try to catch use of queue lock * after free of sdev */ @@ -252,6 +254,11 @@ static void scsi_device_dev_release(struct device *dev) put_device(parent); } +static void scsi_device_dev_release(struct device *dev) +{ + scsi_execute_in_process_context(scsi_device_dev_release_usercontext, dev); +} + static struct class sdev_class = { .name = "scsi_device", .release = scsi_device_cls_release, -- cgit v1.2.3 From 5552c28f6937d2a2b873d06c6d09b96204722dd0 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 14 Feb 2006 17:50:54 +0000 Subject: [PATCH] Fix locking error in esp Noted by Al Viro. Also remove unused tmp_buf Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/esp.c | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/char/esp.c b/drivers/char/esp.c index 57539d8f9f7c..09dc4b01232c 100644 --- a/drivers/char/esp.c +++ b/drivers/char/esp.c @@ -150,17 +150,6 @@ static void rs_wait_until_sent(struct tty_struct *, int); /* Standard COM flags (except for COM4, because of the 8514 problem) */ #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) -/* - * tmp_buf is used as a temporary buffer by serial_write. We need to - * lock it in case the memcpy_fromfs blocks while swapping in a page, - * and some other program tries to do a serial write at the same time. - * Since the lock will only come under contention when the system is - * swapping and available memory is low, it makes sense to share one - * buffer across all the serial ports, since it significantly saves - * memory if large numbers of serial ports are open. - */ -static unsigned char *tmp_buf; - static inline int serial_paranoia_check(struct esp_struct *info, char *name, const char *routine) { @@ -1267,7 +1256,7 @@ static int rs_write(struct tty_struct * tty, if (serial_paranoia_check(info, tty->name, "rs_write")) return 0; - if (!tty || !info->xmit_buf || !tmp_buf) + if (!tty || !info->xmit_buf) return 0; while (1) { @@ -2291,11 +2280,7 @@ static int esp_open(struct tty_struct *tty, struct file * filp) tty->driver_data = info; info->tty = tty; - if (!tmp_buf) { - tmp_buf = (unsigned char *) get_zeroed_page(GFP_KERNEL); - if (!tmp_buf) - return -ENOMEM; - } + spin_unlock_irqrestore(&info->lock, flags); /* * Start up serial port @@ -2602,9 +2587,6 @@ static void __exit espserial_exit(void) free_pages((unsigned long)dma_buffer, get_order(DMA_BUFFER_SZ)); - if (tmp_buf) - free_page((unsigned long)tmp_buf); - while (free_pio_buf) { pio_buf = free_pio_buf->next; kfree(free_pio_buf); -- cgit v1.2.3 From 61a34937982cace51853b5dc88f86380e31998c0 Mon Sep 17 00:00:00 2001 From: Peter Osterlund Date: Tue, 14 Feb 2006 13:52:54 -0800 Subject: [PATCH] pktcdvd: Don't spam the kernel log when nothing is wrong Change some messages that don't indicate an error so that they are only printed when debugging is enabled. Signed-off-by: Peter Osterlund Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/pktcdvd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 4e7dbcc425ff..73999762582e 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -1548,7 +1548,7 @@ static int pkt_good_disc(struct pktcdvd_device *pd, disc_information *di) case 0x12: /* DVD-RAM */ return 0; default: - printk("pktcdvd: Wrong disc profile (%x)\n", pd->mmc3_profile); + VPRINTK("pktcdvd: Wrong disc profile (%x)\n", pd->mmc3_profile); return 1; } @@ -1894,7 +1894,7 @@ static int pkt_open_write(struct pktcdvd_device *pd) unsigned int write_speed, media_write_speed, read_speed; if ((ret = pkt_probe_settings(pd))) { - DPRINTK("pktcdvd: %s failed probe\n", pd->name); + VPRINTK("pktcdvd: %s failed probe\n", pd->name); return -EIO; } @@ -2440,7 +2440,7 @@ static int pkt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u return blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg); default: - printk("pktcdvd: Unknown ioctl for %s (%x)\n", pd->name, cmd); + VPRINTK("pktcdvd: Unknown ioctl for %s (%x)\n", pd->name, cmd); return -ENOTTY; } -- cgit v1.2.3 From 01fd9fda2ce462b44bafdac2fe6aacacf23531f2 Mon Sep 17 00:00:00 2001 From: Peter Osterlund Date: Tue, 14 Feb 2006 13:52:55 -0800 Subject: [PATCH] pktcdvd: Allow non-writable media to be mounted If opening for write fails, the open method should return -EROFS. This makes "mount" try again with a read-only mount, instead of just giving up. Signed-off-by: Peter Osterlund Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/pktcdvd.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 73999762582e..edf6bf29002e 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -1895,7 +1895,7 @@ static int pkt_open_write(struct pktcdvd_device *pd) if ((ret = pkt_probe_settings(pd))) { VPRINTK("pktcdvd: %s failed probe\n", pd->name); - return -EIO; + return -EROFS; } if ((ret = pkt_set_write_settings(pd))) { @@ -2053,10 +2053,9 @@ static int pkt_open(struct inode *inode, struct file *file) goto out_dec; } } else { - if (pkt_open_dev(pd, file->f_mode & FMODE_WRITE)) { - ret = -EIO; + ret = pkt_open_dev(pd, file->f_mode & FMODE_WRITE); + if (ret) goto out_dec; - } /* * needed here as well, since ext2 (among others) may change * the blocksize at mount time -- cgit v1.2.3 From 948423e5ccc33bc257384ad4b339214c577bc926 Mon Sep 17 00:00:00 2001 From: Peter Osterlund Date: Tue, 14 Feb 2006 13:52:56 -0800 Subject: [PATCH] pktcdvd: Don't unlock the door if the disc is in use Unlocking the door when the disc is in use is obviously not good, because then it's possible to eject the disc at the wrong time and cause severe disc data corruption. Signed-off-by: Peter Osterlund Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/pktcdvd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index edf6bf29002e..89d8fe014efa 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -2435,7 +2435,8 @@ static int pkt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u * The door gets locked when the device is opened, so we * have to unlock it or else the eject command fails. */ - pkt_lock_door(pd, 0); + if (pd->refcnt == 1) + pkt_lock_door(pd, 0); return blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg); default: -- cgit v1.2.3 From 7277232374680595cdbc774fd246b206f56db015 Mon Sep 17 00:00:00 2001 From: Peter Osterlund Date: Tue, 14 Feb 2006 13:52:56 -0800 Subject: [PATCH] pktcdvd: Reduce stack usage Reduce stack usage in the pkt_start_write() function. Even though it's not currently a real problem, the pages and offsets arrays can be eliminated, which saves approximately 1000 bytes of stack space. Signed-off-by: Peter Osterlund Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/pktcdvd.c | 43 +++++++++++++++++-------------------------- 1 file changed, 17 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 89d8fe014efa..93e44d0292ab 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -645,7 +645,7 @@ static void pkt_copy_bio_data(struct bio *src_bio, int seg, int offs, struct pag * b) The data can be used as cache to avoid read requests if we receive a * new write request for the same zone. */ -static void pkt_make_local_copy(struct packet_data *pkt, struct page **pages, int *offsets) +static void pkt_make_local_copy(struct packet_data *pkt, struct bio_vec *bvec) { int f, p, offs; @@ -653,15 +653,15 @@ static void pkt_make_local_copy(struct packet_data *pkt, struct page **pages, in p = 0; offs = 0; for (f = 0; f < pkt->frames; f++) { - if (pages[f] != pkt->pages[p]) { - void *vfrom = kmap_atomic(pages[f], KM_USER0) + offsets[f]; + if (bvec[f].bv_page != pkt->pages[p]) { + void *vfrom = kmap_atomic(bvec[f].bv_page, KM_USER0) + bvec[f].bv_offset; void *vto = page_address(pkt->pages[p]) + offs; memcpy(vto, vfrom, CD_FRAMESIZE); kunmap_atomic(vfrom, KM_USER0); - pages[f] = pkt->pages[p]; - offsets[f] = offs; + bvec[f].bv_page = pkt->pages[p]; + bvec[f].bv_offset = offs; } else { - BUG_ON(offsets[f] != offs); + BUG_ON(bvec[f].bv_offset != offs); } offs += CD_FRAMESIZE; if (offs >= PAGE_SIZE) { @@ -991,18 +991,17 @@ try_next_bio: static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt) { struct bio *bio; - struct page *pages[PACKET_MAX_SIZE]; - int offsets[PACKET_MAX_SIZE]; int f; int frames_write; + struct bio_vec *bvec = pkt->w_bio->bi_io_vec; for (f = 0; f < pkt->frames; f++) { - pages[f] = pkt->pages[(f * CD_FRAMESIZE) / PAGE_SIZE]; - offsets[f] = (f * CD_FRAMESIZE) % PAGE_SIZE; + bvec[f].bv_page = pkt->pages[(f * CD_FRAMESIZE) / PAGE_SIZE]; + bvec[f].bv_offset = (f * CD_FRAMESIZE) % PAGE_SIZE; } /* - * Fill-in pages[] and offsets[] with data from orig_bios. + * Fill-in bvec with data from orig_bios. */ frames_write = 0; spin_lock(&pkt->lock); @@ -1024,11 +1023,11 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt) } if (src_bvl->bv_len - src_offs >= CD_FRAMESIZE) { - pages[f] = src_bvl->bv_page; - offsets[f] = src_bvl->bv_offset + src_offs; + bvec[f].bv_page = src_bvl->bv_page; + bvec[f].bv_offset = src_bvl->bv_offset + src_offs; } else { pkt_copy_bio_data(bio, segment, src_offs, - pages[f], offsets[f]); + bvec[f].bv_page, bvec[f].bv_offset); } src_offs += CD_FRAMESIZE; frames_write++; @@ -1042,7 +1041,7 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt) BUG_ON(frames_write != pkt->write_size); if (test_bit(PACKET_MERGE_SEGS, &pd->flags) || (pkt->write_size < pkt->frames)) { - pkt_make_local_copy(pkt, pages, offsets); + pkt_make_local_copy(pkt, bvec); pkt->cache_valid = 1; } else { pkt->cache_valid = 0; @@ -1055,17 +1054,9 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt) pkt->w_bio->bi_bdev = pd->bdev; pkt->w_bio->bi_end_io = pkt_end_io_packet_write; pkt->w_bio->bi_private = pkt; - for (f = 0; f < pkt->frames; f++) { - if ((f + 1 < pkt->frames) && (pages[f + 1] == pages[f]) && - (offsets[f + 1] = offsets[f] + CD_FRAMESIZE)) { - if (!bio_add_page(pkt->w_bio, pages[f], CD_FRAMESIZE * 2, offsets[f])) - BUG(); - f++; - } else { - if (!bio_add_page(pkt->w_bio, pages[f], CD_FRAMESIZE, offsets[f])) - BUG(); - } - } + for (f = 0; f < pkt->frames; f++) + if (!bio_add_page(pkt->w_bio, bvec[f].bv_page, CD_FRAMESIZE, bvec[f].bv_offset)) + BUG(); VPRINTK("pktcdvd: vcnt=%d\n", pkt->w_bio->bi_vcnt); atomic_set(&pkt->io_wait, 1); -- cgit v1.2.3 From da965822abd18a17d7cffe1d511f48951c82dfb6 Mon Sep 17 00:00:00 2001 From: Paul Fulghum Date: Tue, 14 Feb 2006 13:53:00 -0800 Subject: [PATCH] tty reference count fix Fix hole where tty structure can be released when reference count is non zero. Existing code can sleep without tty_sem protection between deciding to release the tty structure (setting local variables tty_closing and otty_closing) and setting TTY_CLOSING to prevent further opens. An open can occur during this interval causing release_dev() to free the tty structure while it is still referenced. This should fix bugzilla.kernel.org [Bug 6041] New: Unable to handle kernel paging request In Bug 6041, tty_open() oopes on accessing the tty structure it has successfully claimed. Bug was on SMP machine with the same tty being opened and closed by multiple processes, and DEBUG_PAGEALLOC enabled. Signed-off-by: Paul Fulghum Cc: Alan Cox Cc: Jesper Juhl Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/tty_io.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index a23816d3e9a1..e9bba94fc898 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1841,7 +1841,6 @@ static void release_dev(struct file * filp) tty_closing = tty->count <= 1; o_tty_closing = o_tty && (o_tty->count <= (pty_master ? 1 : 0)); - up(&tty_sem); do_sleep = 0; if (tty_closing) { @@ -1869,6 +1868,7 @@ static void release_dev(struct file * filp) printk(KERN_WARNING "release_dev: %s: read/write wait queue " "active!\n", tty_name(tty, buf)); + up(&tty_sem); schedule(); } @@ -1877,8 +1877,6 @@ static void release_dev(struct file * filp) * both sides, and we've completed the last operation that could * block, so it's safe to proceed with closing. */ - - down(&tty_sem); if (pty_master) { if (--o_tty->count < 0) { printk(KERN_WARNING "release_dev: bad pty slave count " @@ -1892,7 +1890,6 @@ static void release_dev(struct file * filp) tty->count, tty_name(tty, buf)); tty->count = 0; } - up(&tty_sem); /* * We've decremented tty->count, so we need to remove this file @@ -1937,6 +1934,8 @@ static void release_dev(struct file * filp) read_unlock(&tasklist_lock); } + up(&tty_sem); + /* check whether both sides are closing ... */ if (!tty_closing || (o_tty && !o_tty_closing)) return; -- cgit v1.2.3 From be5efffb762fa4a7b9a7a45ebf34b13e3bf5a2d8 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 14 Feb 2006 13:53:02 -0800 Subject: [PATCH] HPET: handle multiple ACPI EXTENDED_IRQ resources When the _CRS for a single HPET contains multiple EXTENDED_IRQ resources, we overwrote hdp->hd_nirqs every time we found one. So the driver worked when all the IRQs were described in a single EXTENDED_IRQ resource, but failed when multiple resources were used. (Strictly speaking, I think the latter is actually more correct, but both styles have been used.) Someday we should remove all the ACPI stuff from hpet.c and use PNP driver registration instead. But currently PNP_MAX_IRQ is 2, and HPETs often have more IRQs. Hint, hint, Adam :-) Signed-off-by: Bjorn Helgaas Acked-by: Bob Picco Cc: Venkatesh Pallipadi Cc: Len Brown Cc: Adam Belay Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/hpet.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 66a2fee06eb9..ef140ebde117 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -956,22 +956,18 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data) } } else if (res->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) { struct acpi_resource_extended_irq *irqp; - int i; + int i, irq; irqp = &res->data.extended_irq; - if (irqp->interrupt_count > 0) { - hdp->hd_nirqs = irqp->interrupt_count; - - for (i = 0; i < hdp->hd_nirqs; i++) { - int rc = - acpi_register_gsi(irqp->interrupts[i], - irqp->triggering, - irqp->polarity); - if (rc < 0) - return AE_ERROR; - hdp->hd_irq[i] = rc; - } + for (i = 0; i < irqp->interrupt_count; i++) { + irq = acpi_register_gsi(irqp->interrupts[i], + irqp->triggering, irqp->polarity); + if (irq < 0) + return AE_ERROR; + + hdp->hd_irq[hdp->hd_nirqs] = irq; + hdp->hd_nirqs++; } } -- cgit v1.2.3 From 61b9a26ae6d308ade964db122e0e89299586422c Mon Sep 17 00:00:00 2001 From: Karsten Keil Date: Tue, 14 Feb 2006 13:53:06 -0800 Subject: [PATCH] Fix NULL pointer dereference in isdn_tty_at_cout The changes in the tty related code introduced wrong parenthesis in a if condition in the isdn_tty_at_cout function. This caused access to index -1 in the dev->drv[] array. This patch change it back to the correct condition from the previous versions. Signed-off-by: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/i4l/isdn_tty.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index f190a99604f0..393633681f49 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -2359,8 +2359,8 @@ isdn_tty_at_cout(char *msg, modem_info * info) /* use queue instead of direct, if online and */ /* data is in queue or buffer is full */ - if ((info->online && tty_buffer_request_room(tty, l) < l) || - (!skb_queue_empty(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel]))) { + if (info->online && ((tty_buffer_request_room(tty, l) < l) || + !skb_queue_empty(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel]))) { skb = alloc_skb(l, GFP_ATOMIC); if (!skb) { spin_unlock_irqrestore(&info->readlock, flags); -- cgit v1.2.3 From 10ee39fe3ff618d274e1cd0f6abbc2917b736bfd Mon Sep 17 00:00:00 2001 From: Christian Trefzer Date: Tue, 14 Feb 2006 13:53:26 -0800 Subject: [PATCH] neofb: avoid resetting display config on unblank Fix issues with the NeoMagic framebuffer driver. It nicely complements my previous fix already in linus' tree. The only thing missing now is that the external CRT will not be activated at neofb init when external-only is selected, either by register read or module/kernel parameter. Testing was done on a Dell Latitude CPi-A/NM2200 chip. Previous behaviour: - before booting linux, set the preferred display config X via FN+F8 - boot linux, neofb stores the register values in a private variable - change the display config to Y via keystroke - leave the machine in peace until display is blanked - touching any key will result in display config X being restored - booting up, the BIOS will acknowledge config Y, though... Current behaviour: At the time of unblanking, config Y is honoured because we now read back register contents instead of just overwriting them with outdated values. Signed-off by: Christian Trefzer Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/neofb.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c index 747602aa5615..b85e2b180a44 100644 --- a/drivers/video/neofb.c +++ b/drivers/video/neofb.c @@ -1334,6 +1334,12 @@ static int neofb_blank(int blank_mode, struct fb_info *info) struct neofb_par *par = info->par; int seqflags, lcdflags, dpmsflags, reg; + /* + * Reload the value stored in the register, might have been changed via + * FN keystroke + */ + par->PanelDispCntlReg1 = vga_rgfx(NULL, 0x20) & 0x03; + switch (blank_mode) { case FB_BLANK_POWERDOWN: /* powerdown - both sync lines down */ seqflags = VGA_SR01_SCREEN_OFF; /* Disable sequencer */ @@ -1366,7 +1372,7 @@ static int neofb_blank(int blank_mode, struct fb_info *info) case FB_BLANK_NORMAL: /* just blank screen (backlight stays on) */ seqflags = VGA_SR01_SCREEN_OFF; /* Disable sequencer */ lcdflags = par->PanelDispCntlReg1 & 0x02; /* LCD normal */ - dpmsflags = 0; /* no hsync/vsync suppression */ + dpmsflags = 0x00; /* no hsync/vsync suppression */ break; case FB_BLANK_UNBLANK: /* unblank */ seqflags = 0; /* Enable sequencer */ -- cgit v1.2.3 From a09d31ff762a3671f2ae41b3bca50a100c5e4da6 Mon Sep 17 00:00:00 2001 From: Alessandro Zummo Date: Wed, 15 Feb 2006 00:48:40 -0500 Subject: Input: ixp4xx-beeper - fix compile error Signed-off-by: Alessandro Zummo Signed-off-by: Dmitry Torokhov --- drivers/input/misc/ixp4xx-beeper.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/input/misc/ixp4xx-beeper.c b/drivers/input/misc/ixp4xx-beeper.c index d448bb5e4869..3a6ae85cd69c 100644 --- a/drivers/input/misc/ixp4xx-beeper.c +++ b/drivers/input/misc/ixp4xx-beeper.c @@ -19,6 +19,7 @@ #include #include #include +#include #include MODULE_AUTHOR("Alessandro Zummo "); -- cgit v1.2.3 From 50f6dde0ad05ee4ee8450feb731b15b716115c4d Mon Sep 17 00:00:00 2001 From: Meelis Roos Date: Wed, 15 Feb 2006 00:48:58 -0500 Subject: Input: logips2pp - add new signature (99) Add Logitech mouse type 99 (Premium Optical Wheel Mouse, model M-BT58, plain 3 buttons + wheel) to cure the following message: logips2pp: Detected unknown logitech mouse model 99 Signed-off-by: Meelis Roos Signed-off-by: Andrew Morton Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/logips2pp.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c index c88520d3d13c..40333d61093c 100644 --- a/drivers/input/mouse/logips2pp.c +++ b/drivers/input/mouse/logips2pp.c @@ -232,6 +232,7 @@ static struct ps2pp_info *get_model_info(unsigned char model) { 88, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, { 96, 0, 0 }, { 97, PS2PP_KIND_TP3, PS2PP_WHEEL | PS2PP_HWHEEL }, + { 99, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, { 100, PS2PP_KIND_MX, /* MX510 */ PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN | PS2PP_EXTRA_BTN | PS2PP_NAV_BTN }, -- cgit v1.2.3 From b8044c74bcd64bd1a9d2e8cec58fdcd40f16f5a4 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 15 Feb 2006 00:49:09 -0500 Subject: Input: trackpoint - enable devices connected to external port Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/trackpoint.c | 20 ++++++++++++++------ drivers/input/mouse/trackpoint.h | 4 ++-- 2 files changed, 16 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c index b4898d8a68e2..6d9ec9ab1b90 100644 --- a/drivers/input/mouse/trackpoint.c +++ b/drivers/input/mouse/trackpoint.c @@ -68,15 +68,19 @@ struct trackpoint_attr_data { size_t field_offset; unsigned char command; unsigned char mask; + unsigned char inverted; }; static ssize_t trackpoint_show_int_attr(struct psmouse *psmouse, void *data, char *buf) { struct trackpoint_data *tp = psmouse->private; struct trackpoint_attr_data *attr = data; - unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset); + unsigned char value = *(unsigned char *)((char *)tp + attr->field_offset); + + if (attr->inverted) + value = !value; - return sprintf(buf, "%u\n", *field); + return sprintf(buf, "%u\n", value); } static ssize_t trackpoint_set_int_attr(struct psmouse *psmouse, void *data, @@ -120,6 +124,9 @@ static ssize_t trackpoint_set_bit_attr(struct psmouse *psmouse, void *data, if (*rest || value > 1) return -EINVAL; + if (attr->inverted) + value = !value; + if (*field != value) { *field = value; trackpoint_toggle_bit(&psmouse->ps2dev, attr->command, attr->mask); @@ -129,11 +136,12 @@ static ssize_t trackpoint_set_bit_attr(struct psmouse *psmouse, void *data, } -#define TRACKPOINT_BIT_ATTR(_name, _command, _mask) \ +#define TRACKPOINT_BIT_ATTR(_name, _command, _mask, _inv) \ static struct trackpoint_attr_data trackpoint_attr_##_name = { \ .field_offset = offsetof(struct trackpoint_data, _name), \ .command = _command, \ .mask = _mask, \ + .inverted = _inv, \ }; \ PSMOUSE_DEFINE_ATTR(_name, S_IWUSR | S_IRUGO, \ &trackpoint_attr_##_name, \ @@ -150,9 +158,9 @@ TRACKPOINT_INT_ATTR(upthresh, TP_UP_THRESH); TRACKPOINT_INT_ATTR(ztime, TP_Z_TIME); TRACKPOINT_INT_ATTR(jenks, TP_JENKS_CURV); -TRACKPOINT_BIT_ATTR(press_to_select, TP_TOGGLE_PTSON, TP_MASK_PTSON); -TRACKPOINT_BIT_ATTR(skipback, TP_TOGGLE_SKIPBACK, TP_MASK_SKIPBACK); -TRACKPOINT_BIT_ATTR(ext_dev, TP_TOGGLE_EXT_DEV, TP_MASK_EXT_DEV); +TRACKPOINT_BIT_ATTR(press_to_select, TP_TOGGLE_PTSON, TP_MASK_PTSON, 0); +TRACKPOINT_BIT_ATTR(skipback, TP_TOGGLE_SKIPBACK, TP_MASK_SKIPBACK, 0); +TRACKPOINT_BIT_ATTR(ext_dev, TP_TOGGLE_EXT_DEV, TP_MASK_EXT_DEV, 1); static struct attribute *trackpoint_attrs[] = { &psmouse_attr_sensitivity.dattr.attr, diff --git a/drivers/input/mouse/trackpoint.h b/drivers/input/mouse/trackpoint.h index 9857d8b6ad66..050298b1a09d 100644 --- a/drivers/input/mouse/trackpoint.h +++ b/drivers/input/mouse/trackpoint.h @@ -78,7 +78,7 @@ #define TP_TOGGLE_MB 0x23 /* Disable/Enable Middle Button */ #define TP_MASK_MB 0x01 -#define TP_TOGGLE_EXT_DEV 0x23 /* Toggle external device */ +#define TP_TOGGLE_EXT_DEV 0x23 /* Disable external device */ #define TP_MASK_EXT_DEV 0x02 #define TP_TOGGLE_DRIFT 0x23 /* Drift Correction */ #define TP_MASK_DRIFT 0x80 @@ -125,7 +125,7 @@ #define TP_DEF_MB 0x00 #define TP_DEF_PTSON 0x00 #define TP_DEF_SKIPBACK 0x00 -#define TP_DEF_EXT_DEV 0x01 +#define TP_DEF_EXT_DEV 0x00 /* 0 means enabled */ #define MAKE_PS2_CMD(params, results, cmd) ((params<<12) | (results<<8) | (cmd)) -- cgit v1.2.3 From a90f7e98b7df3309ebc0e389076990456db20989 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 15 Feb 2006 00:49:22 -0500 Subject: Input: ads7846 - convert to to dynamic input_dev allocation Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ads7846.c | 79 ++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index b45a45ca7cc9..72cf0a26d676 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -60,7 +60,7 @@ struct ts_event { }; struct ads7846 { - struct input_dev input; + struct input_dev *input; char phys[32]; struct spi_device *spi; @@ -152,7 +152,7 @@ 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; + int i; if (!req) return -ENOMEM; @@ -236,11 +236,12 @@ SHOW(vbatt) static void ads7846_rx(void *ads) { - struct ads7846 *ts = ads; - unsigned Rt; - unsigned sync = 0; - u16 x, y, z1, z2; - unsigned long flags; + struct ads7846 *ts = ads; + struct input_dev *input_dev = ts->input; + 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. @@ -276,21 +277,21 @@ static void ads7846_rx(void *ads) * won't notice that, even if nPENIRQ never fires ... */ if (!ts->pendown && Rt != 0) { - input_report_key(&ts->input, BTN_TOUCH, 1); + input_report_key(input_dev, BTN_TOUCH, 1); sync = 1; } else if (ts->pendown && Rt == 0) { - input_report_key(&ts->input, BTN_TOUCH, 0); + input_report_key(input_dev, 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); + input_report_abs(input_dev, ABS_X, x); + input_report_abs(input_dev, ABS_Y, y); + input_report_abs(input_dev, ABS_PRESSURE, Rt); sync = 1; } if (sync) - input_sync(&ts->input); + input_sync(input_dev); #ifdef VERBOSE if (Rt || ts->pendown) @@ -396,9 +397,11 @@ static int ads7846_resume(struct spi_device *spi) static int __devinit ads7846_probe(struct spi_device *spi) { struct ads7846 *ts; + struct input_dev *input_dev; struct ads7846_platform_data *pdata = spi->dev.platform_data; struct spi_transfer *x; int i; + int err; if (!spi->irq) { dev_dbg(&spi->dev, "no IRQ?\n"); @@ -423,13 +426,18 @@ static int __devinit ads7846_probe(struct spi_device *spi) * to discard the four garbage LSBs. */ - if (!(ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL))) - return -ENOMEM; + ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!ts || !input_dev) { + err = -ENOMEM; + goto err_free_mem; + } dev_set_drvdata(&spi->dev, ts); + spi->dev.power.power_state = PMSG_ON; ts->spi = spi; - spi->dev.power.power_state = PMSG_ON; + ts->input = input_dev; init_timer(&ts->timer); ts->timer.data = (unsigned long) ts; @@ -439,28 +447,25 @@ static int __devinit ads7846_probe(struct spi_device *spi) ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100; ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; - init_input_dev(&ts->input); + snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id); - ts->input.dev = &spi->dev; - ts->input.name = "ADS784x Touchscreen"; - snprintf(ts->phys, sizeof ts->phys, "%s/input0", spi->dev.bus_id); - ts->input.phys = ts->phys; + input_dev->name = "ADS784x Touchscreen"; + input_dev->phys = ts->phys; + input_dev->cdev.dev = &spi->dev; - 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, + input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); + input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); + input_set_abs_params(input_dev, ABS_X, pdata->x_min ? : 0, pdata->x_max ? : MAX_12BIT, 0, 0); - input_set_abs_params(&ts->input, ABS_Y, + input_set_abs_params(input_dev, ABS_Y, pdata->y_min ? : 0, pdata->y_max ? : MAX_12BIT, 0, 0); - input_set_abs_params(&ts->input, ABS_PRESSURE, + input_set_abs_params(input_dev, 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. */ @@ -510,9 +515,8 @@ static int __devinit ads7846_probe(struct spi_device *spi) SA_SAMPLE_RANDOM | SA_TRIGGER_FALLING, spi->dev.bus_id, ts)) { dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); - input_unregister_device(&ts->input); - kfree(ts); - return -EBUSY; + err = -EBUSY; + goto err_free_mem; } dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq); @@ -534,7 +538,18 @@ static int __devinit ads7846_probe(struct spi_device *spi) device_create_file(&spi->dev, &dev_attr_vbatt); device_create_file(&spi->dev, &dev_attr_vaux); + err = input_register_device(input_dev); + if (err) + goto err_free_irq; + return 0; + + err_free_irq: + free_irq(spi->irq, ts); + err_free_mem: + input_free_device(input_dev); + kfree(ts); + return err; } static int __devexit ads7846_remove(struct spi_device *spi) @@ -554,7 +569,7 @@ static int __devexit ads7846_remove(struct spi_device *spi) device_remove_file(&spi->dev, &dev_attr_vbatt); device_remove_file(&spi->dev, &dev_attr_vaux); - input_unregister_device(&ts->input); + input_unregister_device(ts->input); kfree(ts); dev_dbg(&spi->dev, "unregistered touchscreen\n"); -- cgit v1.2.3 From d93f70b2d758e79ee4ac9d6d982e3f532453911f Mon Sep 17 00:00:00 2001 From: David Brownell Date: Wed, 15 Feb 2006 00:49:35 -0500 Subject: Input: ads7846 - assorted updates This updates the ads7846 touchscreen driver: - to allow faster clocking (this driver doesn't push sample rates); - bugfixes the conversion of spi_transfer to lists; - some dma-unsafe command buffers are fixed. Signed-off-by: David Brownell Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ads7846.c | 68 ++++++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 72cf0a26d676..8c12a974b411 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -48,10 +48,13 @@ #define TS_POLL_PERIOD msecs_to_jiffies(10) +/* this driver doesn't aim at the peak continuous sample rate */ +#define SAMPLE_BITS (8 /*cmd*/ + 16 /*sample*/ + 2 /* before, after */) + 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, + * with msbs zeroed). Instead, we read them as two 8-bit values, * which need byteswapping then range adjustment. */ __be16 x; @@ -68,6 +71,7 @@ struct ads7846 { u16 vref_delay_usecs; u16 x_plate_ohms; + u8 read_x, read_y, read_z1, read_z2; struct ts_event tc; struct spi_transfer xfer[8]; @@ -117,10 +121,10 @@ struct ads7846 { #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 */ +#define READ_Y (READ_12BIT_DFR(y) | ADS_PD10_ADC_ON) +#define READ_Z1 (READ_12BIT_DFR(z1) | ADS_PD10_ADC_ON) +#define READ_Z2 (READ_12BIT_DFR(z2) | ADS_PD10_ADC_ON) +#define 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 @@ -128,8 +132,8 @@ static const u8 read_x = READ_12BIT_DFR(x) | ADS_PD10_PDOWN; /* LAST */ #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; +#define REF_ON (READ_12BIT_DFR(x) | ADS_PD10_ALL_ON) +#define REF_OFF (READ_12BIT_DFR(y) | ADS_PD10_PDOWN) /*--------------------------------------------------------------------------*/ @@ -138,7 +142,9 @@ static const u8 ref_off = READ_12BIT_DFR(y) | ADS_PD10_PDOWN; */ struct ser_req { + u8 ref_on; u8 command; + u8 ref_off; u16 scratch; __be16 sample; struct spi_message msg; @@ -160,7 +166,8 @@ static int ads7846_read12_ser(struct device *dev, unsigned command) INIT_LIST_HEAD(&req->msg.transfers); /* activate reference, so it has time to settle; */ - req->xfer[0].tx_buf = &ref_on; + req->ref_on = REF_ON; + req->xfer[0].tx_buf = &req->ref_on; req->xfer[0].len = 1; req->xfer[1].rx_buf = &req->scratch; req->xfer[1].len = 2; @@ -182,7 +189,8 @@ static int ads7846_read12_ser(struct device *dev, unsigned command) /* REVISIT: take a few more samples, and compare ... */ /* turn off reference */ - req->xfer[4].tx_buf = &ref_off; + req->ref_off = REF_OFF; + req->xfer[4].tx_buf = &req->ref_off; req->xfer[4].len = 1; req->xfer[5].rx_buf = &req->scratch; req->xfer[5].len = 2; @@ -400,7 +408,6 @@ static int __devinit ads7846_probe(struct spi_device *spi) struct input_dev *input_dev; struct ads7846_platform_data *pdata = spi->dev.platform_data; struct spi_transfer *x; - int i; int err; if (!spi->irq) { @@ -414,9 +421,9 @@ static int __devinit ads7846_probe(struct spi_device *spi) } /* don't exceed max specified sample rate */ - if (spi->max_speed_hz > (125000 * 16)) { + if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) { dev_dbg(&spi->dev, "f(sample) %d KHz?\n", - (spi->max_speed_hz/16)/1000); + (spi->max_speed_hz/SAMPLE_BITS)/1000); return -EINVAL; } @@ -469,45 +476,58 @@ static int __devinit ads7846_probe(struct spi_device *spi) /* set up the transfers to read touchscreen state; this assumes we * use formula #2 for pressure, not #3. */ + INIT_LIST_HEAD(&ts->msg.transfers); x = ts->xfer; /* y- still on; turn on only y+ (and ADC) */ - x->tx_buf = &read_y; + ts->read_y = READ_Y; + x->tx_buf = &ts->read_y; x->len = 1; + spi_message_add_tail(x, &ts->msg); + x++; x->rx_buf = &ts->tc.y; x->len = 2; - x++; + spi_message_add_tail(x, &ts->msg); /* turn y+ off, x- on; we'll use formula #2 */ if (ts->model == 7846) { - x->tx_buf = &read_z1; + x++; + ts->read_z1 = READ_Z1; + x->tx_buf = &ts->read_z1; x->len = 1; + spi_message_add_tail(x, &ts->msg); + x++; x->rx_buf = &ts->tc.z1; x->len = 2; - x++; + spi_message_add_tail(x, &ts->msg); - x->tx_buf = &read_z2; + x++; + ts->read_z2 = READ_Z2; + x->tx_buf = &ts->read_z2; x->len = 1; + spi_message_add_tail(x, &ts->msg); + x++; x->rx_buf = &ts->tc.z2; x->len = 2; - x++; + spi_message_add_tail(x, &ts->msg); } /* turn y- off, x+ on, then leave in lowpower */ - x->tx_buf = &read_x; + x++; + ts->read_x = READ_X; + x->tx_buf = &ts->read_x; x->len = 1; + spi_message_add_tail(x, &ts->msg); + x++; x->rx_buf = &ts->tc.x; x->len = 2; - x++; - - CS_CHANGE(x[-1]); + CS_CHANGE(*x); + spi_message_add_tail(x, &ts->msg); - 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; -- cgit v1.2.3 From 02860ab6cd2c71dbe42fa70a65a97823c213635b Mon Sep 17 00:00:00 2001 From: Arthur Othieno Date: Wed, 15 Feb 2006 00:49:48 -0500 Subject: Input: kill remnants of 98kbd{,-io} and 98spkr 98kbd{,-io} and 98spkr all went out with PC98 subarch. Remove stale Makefile entries that remained. Signed-off-by: Arthur Othieno Signed-off-by: Andrew Morton Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Makefile | 1 - drivers/input/misc/Makefile | 1 - drivers/input/serio/Makefile | 1 - 3 files changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 6e0afbb22383..2708167ba175 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -11,7 +11,6 @@ obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o -obj-$(CONFIG_KEYBOARD_98KBD) += 98kbd.o obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 184c4129470d..415c49178985 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -7,7 +7,6 @@ obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o -obj-$(CONFIG_INPUT_98SPKR) += 98spkr.o obj-$(CONFIG_INPUT_UINPUT) += uinput.o obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile index 678a8599f9ff..4155197867a3 100644 --- a/drivers/input/serio/Makefile +++ b/drivers/input/serio/Makefile @@ -13,7 +13,6 @@ obj-$(CONFIG_SERIO_RPCKBD) += rpckbd.o obj-$(CONFIG_SERIO_SA1111) += sa1111ps2.o obj-$(CONFIG_SERIO_AMBAKMI) += ambakmi.o obj-$(CONFIG_SERIO_Q40KBD) += q40kbd.o -obj-$(CONFIG_SERIO_98KBD) += 98kbd-io.o obj-$(CONFIG_SERIO_GSCPS2) += gscps2.o obj-$(CONFIG_HP_SDC) += hp_sdc.o obj-$(CONFIG_HIL_MLC) += hp_sdc_mlc.o hil_mlc.o -- cgit v1.2.3 From a5f1e4edb3cdd90733893b8aec38fac5553db60a Mon Sep 17 00:00:00 2001 From: Arthur Othieno Date: Wed, 15 Feb 2006 09:52:46 +0000 Subject: [SERIAL] Documentation/jsm.txt is a no show. In kernel bugzilla #5176 (http://bugzilla.kernel.org/show_bug.cgi?id=5176) Harry R\374ter points out Documentation/jsm.txt is missing. No one at Digi seems to care, so just remove the stale reference. Signed-off-by: Arthur Othieno Signed-off-by: Russell King --- drivers/serial/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 0f4361c8466b..b3c561abe3f6 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -902,8 +902,8 @@ config SERIAL_JSM something like this to connect more than two modems to your Linux box, for instance in order to become a dial-in server. This driver supports PCI boards only. - If you have a card like this, say Y here and read the file - . + + If you have a card like this, say Y here, otherwise say N. To compile this driver as a module, choose M here: the module will be called jsm. -- cgit v1.2.3 From dc7bf130b8552a218e2f3ea0b58268e469f335da Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 15 Feb 2006 09:59:47 +0000 Subject: [SERIAL] Fix typo in comment Signed-off-by: Ralf Baechle Signed-off-by: Russell King --- drivers/serial/8250.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index b1fc97d5f643..244e8ff11977 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -2198,7 +2198,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) touch_nmi_watchdog(); /* - * First save the UER then disable the interrupts + * First save the IER then disable the interrupts */ ier = serial_in(up, UART_IER); -- cgit v1.2.3 From ba09cf2bcf9b74d852dcb5ea957ac6af2bc0e057 Mon Sep 17 00:00:00 2001 From: Herbert Poetzl Date: Wed, 15 Feb 2006 10:13:02 +0000 Subject: [ARM] remove duplicate #includes Signed-off-by: Herbert P?tzl Signed-off-by: Russell King --- drivers/video/s3c2410fb.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index d574dd3c9c8a..9451932fbaf2 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c @@ -82,7 +82,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From d3454344b3507042e5d561d0cfed19e99cf2fc88 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 13 Feb 2006 05:32:09 -0500 Subject: [IA64] remove obsolete corporate address Remove obsolete SGI address Signed-off-by: Jes Sorensen Signed-off-by: Tony Luck --- drivers/ide/pci/sgiioc4.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c index 2b286e865163..43b96e298363 100644 --- a/drivers/ide/pci/sgiioc4.c +++ b/drivers/ide/pci/sgiioc4.c @@ -13,11 +13,6 @@ * License along with this program; if not, write the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * * For further information regarding this notice, see: * * http://oss.sgi.com/projects/GenInfo/NoticeExplan -- cgit v1.2.3 From 9f672004ab1a8094bec1785b39ac683ab9eebebc Mon Sep 17 00:00:00 2001 From: Christian Trefzer Date: Wed, 15 Feb 2006 15:17:34 -0800 Subject: [PATCH] neofb: avoid resetting display config on unblank (v2) There were two mistakes in the register-read-on-(un)blank approach. - First, without proper register (un)locking the value read back will always be zero, and this is what I missed entirely until just now. Due to this, the logic could not be verified at all and I tried some bogus checks which are completely stupid. - Second, the LCD status bit will always be set to zero when the backlight has been turned off. Reading the value back during unblank will disable the LCD unconditionally, regardless of the state it is supposed to be in, since we set it to zero beforehand. So this is what we do now: - create a new variable in struct neofb_par, and use that to determine whether to read back registers (initialized to true) - before actually blanking the screen, read back the register to sense any possible change made through Fn key combo - use proper neoUnlock() / neoLock() to actually read something - every call to neofb_blank() determines if we read back next time: blanking disables readback, unblanking (FB_BLANK_UNBLANK) enables it This should give us a nice and clean state machine. Has been thoroughly tested on a Dell Latitude CPiA / NM220 Chip docked to a C/Dock2 with attached CRT in all possible combinations of LCD/CRT on/off. I changed the config via Fn key, let the console blank, unblanked by keypress - works flawlessly. Signed-off-by: Christian Trefzer Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/neofb.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c index b85e2b180a44..a2e201dc40f7 100644 --- a/drivers/video/neofb.c +++ b/drivers/video/neofb.c @@ -843,6 +843,9 @@ static int neofb_set_par(struct fb_info *info) par->SysIfaceCntl2 = 0xc0; /* VESA Bios sets this to 0x80! */ + /* Initialize: by default, we want display config register to be read */ + par->PanelDispCntlRegRead = 1; + /* Enable any user specified display devices. */ par->PanelDispCntlReg1 = 0x00; if (par->internal_display) @@ -1334,11 +1337,17 @@ static int neofb_blank(int blank_mode, struct fb_info *info) struct neofb_par *par = info->par; int seqflags, lcdflags, dpmsflags, reg; + /* - * Reload the value stored in the register, might have been changed via - * FN keystroke + * Reload the value stored in the register, if sensible. It might have + * been changed via FN keystroke. */ - par->PanelDispCntlReg1 = vga_rgfx(NULL, 0x20) & 0x03; + if (par->PanelDispCntlRegRead) { + neoUnlock(); + par->PanelDispCntlReg1 = vga_rgfx(NULL, 0x20) & 0x03; + neoLock(&par->state); + } + par->PanelDispCntlRegRead = !blank_mode; switch (blank_mode) { case FB_BLANK_POWERDOWN: /* powerdown - both sync lines down */ -- cgit v1.2.3 From 651c29a17f7ea0204dacbc2a5042d57b1c9e2e37 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 15 Feb 2006 15:17:37 -0800 Subject: [PATCH] ide: touch softlockup detector during pio We're getting some softlockup false positives during heavy PIO operations. So poke the lockup detector. Cc: Bartlomiej Zolnierkiewicz Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/ide-taskfile.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 9834dce4e20f..0606bd2f6020 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -314,6 +315,8 @@ static void ide_pio_datablock(ide_drive_t *drive, struct request *rq, if (rq->bio) /* fs request */ rq->errors = 0; + touch_softlockup_watchdog(); + switch (drive->hwif->data_phase) { case TASKFILE_MULTI_IN: case TASKFILE_MULTI_OUT: -- cgit v1.2.3 From 0425a14213f373595bd23cacdc675f2b973a28d4 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 16 Feb 2006 16:48:31 +0000 Subject: [MMC] mmci: allow small data transfers If a data transfer is small (less than a FIFO size) we would hang waiting for the data to be read due to the PIO interrupt not occuring. We allowed for this in our PIO interrupt handler, but not when setting up a data transfer. Apply the "fix" when setting up a data transfer as well. Signed-off-by: Russell King --- drivers/mmc/mmci.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c index 37ee7f8dc82f..9fef29d978b5 100644 --- a/drivers/mmc/mmci.c +++ b/drivers/mmc/mmci.c @@ -97,6 +97,13 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) if (data->flags & MMC_DATA_READ) { datactrl |= MCI_DPSM_DIRECTION; irqmask = MCI_RXFIFOHALFFULLMASK; + + /* + * If we have less than a FIFOSIZE of bytes to transfer, + * trigger a PIO interrupt as soon as any data is available. + */ + if (host->size < MCI_FIFOSIZE) + irqmask |= MCI_RXDATAAVLBLMASK; } else { /* * We don't actually need to include "FIFO empty" here -- cgit v1.2.3 From 10487fbd74f2f9c9b5fb2d77efd50eab48db191a Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Thu, 16 Feb 2006 22:17:00 +0100 Subject: sis190: early setting of the pci driver private data Below this point, the error path will proceed through sis190_release_board(). It will happily oops if pci_set_drvdata() has not been issued. Signed-off-by: Francois Romieu --- drivers/net/sis190.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index b420182eec4b..ed4bc91638d2 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -1791,6 +1791,8 @@ static int __devinit sis190_init_one(struct pci_dev *pdev, goto out; } + pci_set_drvdata(pdev, dev); + tp = netdev_priv(dev); ioaddr = tp->mmio_addr; @@ -1827,8 +1829,6 @@ static int __devinit sis190_init_one(struct pci_dev *pdev, if (rc < 0) goto err_remove_mii; - pci_set_drvdata(pdev, dev); - net_probe(tp, KERN_INFO "%s: %s at %p (IRQ: %d), " "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", pci_name(pdev), sis_chip_info[ent->driver_data].name, -- cgit v1.2.3 From 0d467502b7fc2656f01d7f18ab290c8d41762018 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 5 Feb 2006 17:52:21 -0500 Subject: [PATCH] wireless/atmel: fix setting TX key only in ENCODEEXT The previous patch that added ENCODEEXT and AUTH support to the atmel driver contained a slight error which would cause just setting the TX key index to also set the encryption key again. This patch allows any combination of setting the TX key index and setting an encryption key. Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/atmel.c | 61 +++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index 98a76f10a0f7..c1c27e10b8df 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c @@ -1872,7 +1872,7 @@ static int atmel_set_encodeext(struct net_device *dev, 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; + int idx, key_len, alg = ext->alg, set_key = 1; /* Determine and validate the key index */ idx = encoding->flags & IW_ENCODE_INDEX; @@ -1883,39 +1883,42 @@ static int atmel_set_encodeext(struct net_device *dev, } 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 (encoding->flags & IW_ENCODE_DISABLED) + alg = IW_ENCODE_ALG_NONE; - if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { priv->default_key = idx; + set_key = ext->key_len > 0 ? 1 : 0; + } - /* 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 { + if (set_key) { + /* Set the requested key first */ + switch (alg) { + case IW_ENCODE_ALG_NONE: + priv->wep_is_on = 0; + priv->encryption_level = 0; + priv->pairwise_cipher_suite = CIPHER_SUITE_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; } - 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; -- cgit v1.2.3 From 7345137930907ba747781636c60112f7c2789aa8 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 5 Feb 2006 17:55:16 -0500 Subject: [PATCH] wireless/atmel: fix Open System authentication process bugs This patch fixes a number of bugs in the authentication process: 1) When falling back to Shared Key authentication mode from Open System, a missing 'return' would cause the auth request to be sent, but would drop the card into Management Error state. When falling back, the driver should also indicate that it is switching to Shared Key mode by setting exclude_unencrypted. 2) Initial authentication modes were apparently wrong in some cases, causing the driver to attempt Shared Key authentication mode when in fact the access point didn't support that mode or even had WEP disabled. The driver should set the correct initial authentication mode based on wep_is_on and exclude_unencrypted. 3) Authentication response packets from the access point in Open System mode were getting ignored because the driver was expecting the sequence number of a Shared Key mode response. The patch separates the OS and SK mode handling to provide the correct behavior. Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/atmel.c | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index c1c27e10b8df..dfc24016ba81 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c @@ -3064,17 +3064,26 @@ static void authenticate(struct atmel_private *priv, u16 frame_len) } if (status == C80211_MGMT_SC_Success && priv->wep_is_on) { + int should_associate = 0; /* WEP */ if (trans_seq_no != priv->ExpectedAuthentTransactionSeqNum) return; - if (trans_seq_no == 0x0002 && - auth->el_id == C80211_MGMT_ElementID_ChallengeText) { - send_authentication_request(priv, system, auth->chall_text, auth->chall_text_len); - return; + if (system == C80211_MGMT_AAN_OPENSYSTEM) { + if (trans_seq_no == 0x0002) { + should_associate = 1; + } + } else if (system == C80211_MGMT_AAN_SHAREDKEY) { + if (trans_seq_no == 0x0002 && + auth->el_id == C80211_MGMT_ElementID_ChallengeText) { + send_authentication_request(priv, system, auth->chall_text, auth->chall_text_len); + return; + } else if (trans_seq_no == 0x0004) { + should_associate = 1; + } } - if (trans_seq_no == 0x0004) { + if (should_associate) { if(priv->station_was_associated) { atmel_enter_state(priv, STATION_STATE_REASSOCIATING); send_association_request(priv, 1); @@ -3087,11 +3096,13 @@ static void authenticate(struct atmel_private *priv, u16 frame_len) } } - if (status == C80211_MGMT_SC_AuthAlgNotSupported) { + if (status == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) { /* Do opensystem first, then try sharedkey */ - if (system == C80211_MGMT_AAN_OPENSYSTEM) { + if (system == WLAN_AUTH_OPEN) { priv->CurrentAuthentTransactionSeqNum = 0x001; - send_authentication_request(priv, C80211_MGMT_AAN_SHAREDKEY, NULL, 0); + priv->exclude_unencrypted = 1; + send_authentication_request(priv, WLAN_AUTH_SHARED_KEY, NULL, 0); + return; } else if (priv->connect_to_any_BSS) { int bss_index; @@ -3442,10 +3453,13 @@ static void atmel_management_timer(u_long a) priv->AuthenticationRequestRetryCnt = 0; restart_search(priv); } else { + int auth = C80211_MGMT_AAN_OPENSYSTEM; priv->AuthenticationRequestRetryCnt++; priv->CurrentAuthentTransactionSeqNum = 0x0001; mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES); - send_authentication_request(priv, C80211_MGMT_AAN_OPENSYSTEM, NULL, 0); + if (priv->wep_is_on && priv->exclude_unencrypted) + auth = C80211_MGMT_AAN_SHAREDKEY; + send_authentication_request(priv, auth, NULL, 0); } break; @@ -3544,12 +3558,15 @@ static void atmel_command_irq(struct atmel_private *priv) priv->station_was_associated = priv->station_is_associated; atmel_enter_state(priv, STATION_STATE_READY); } else { + int auth = C80211_MGMT_AAN_OPENSYSTEM; priv->AuthenticationRequestRetryCnt = 0; atmel_enter_state(priv, STATION_STATE_AUTHENTICATING); mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES); priv->CurrentAuthentTransactionSeqNum = 0x0001; - send_authentication_request(priv, C80211_MGMT_AAN_SHAREDKEY, NULL, 0); + if (priv->wep_is_on && priv->exclude_unencrypted) + auth = C80211_MGMT_AAN_SHAREDKEY; + send_authentication_request(priv, auth, NULL, 0); } return; } -- cgit v1.2.3 From d30864392823d5f38002fa32950689e651ee11da Mon Sep 17 00:00:00 2001 From: Joshua Kinard Date: Fri, 17 Feb 2006 03:52:25 +0000 Subject: [PATCH] Fix SGI O2 compile error in drivers/video/gbefb.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A sysfs function call uses the wrong parameter, and thus breaks a build on SGI O2. CC drivers/video/gbefb.o drivers/video/gbefb.c: In function ‘gbefb_remove’: drivers/video/gbefb.c:1246: error: ‘dev’ undeclared (first use in this function) drivers/video/gbefb.c:1246: error: (Each undeclared identifier is reported only once drivers/video/gbefb.c:1246: error: for each function it appears in.) make[2]: *** [drivers/video/gbefb.o] Error 1 Signed-off-by: Joshua Kinard Signed-off-by: Antonino Daplas Signed-off-by: Martin Michlmayr Signed-off-by: Linus Torvalds --- drivers/video/gbefb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c index 38d22729b129..c9a7cdf6d543 100644 --- a/drivers/video/gbefb.c +++ b/drivers/video/gbefb.c @@ -1243,7 +1243,7 @@ static int __devexit gbefb_remove(struct platform_device* p_dev) (void *)gbe_tiles.cpu, gbe_tiles.dma); release_mem_region(GBE_BASE, sizeof(struct sgi_gbe)); iounmap(gbe); - gbefb_remove_sysfs(dev); + gbefb_remove_sysfs(&p_dev->dev); framebuffer_release(info); return 0; -- cgit v1.2.3 From aca0b510cdbf81d52e15014a720be2b8dfd26aea Mon Sep 17 00:00:00 2001 From: Jean Tourrilhes Date: Thu, 16 Feb 2006 17:44:54 -0800 Subject: [PATCH] Wavelan_cs bitfield fixes Some bitfields were incorrectly initialised in wavelan_cs, causing some compiler warning. Also killed a error message that should not be there... Signed-off-by: Jean Tourrilhes Signed-off-by: Jeff Garzik --- drivers/net/wireless/wavelan_cs.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index cf373625fc70..98122f3a4bc2 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c @@ -950,16 +950,8 @@ wv_82593_cmd(struct net_device * dev, static inline int wv_diag(struct net_device * dev) { - int ret = FALSE; - - if(wv_82593_cmd(dev, "wv_diag(): diagnose", - OP0_DIAGNOSE, SR0_DIAGNOSE_PASSED)) - ret = TRUE; - -#ifdef DEBUG_CONFIG_ERRORS - printk(KERN_INFO "wavelan_cs: i82593 Self Test failed!\n"); -#endif - return(ret); + return(wv_82593_cmd(dev, "wv_diag(): diagnose", + OP0_DIAGNOSE, SR0_DIAGNOSE_PASSED)); } /* wv_diag */ /*------------------------------------------------------------------*/ @@ -3604,8 +3596,8 @@ wv_82593_config(struct net_device * dev) cfblk.lin_prio = 0; /* conform to 802.3 backoff algoritm */ cfblk.exp_prio = 5; /* conform to 802.3 backoff algoritm */ cfblk.bof_met = 1; /* conform to 802.3 backoff algoritm */ - cfblk.ifrm_spc = 0x20; /* 32 bit times interframe spacing */ - cfblk.slottim_low = 0x20; /* 32 bit times slot time */ + cfblk.ifrm_spc = 0x20 >> 4; /* 32 bit times interframe spacing */ + cfblk.slottim_low = 0x20 >> 5; /* 32 bit times slot time */ cfblk.slottim_hi = 0x0; cfblk.max_retr = 15; cfblk.prmisc = ((lp->promiscuous) ? TRUE: FALSE); /* Promiscuous mode */ -- cgit v1.2.3 From 56c8f7e290a1b3249c6a5b464fada8a167f2e5ff Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 13 Feb 2006 15:49:55 -0800 Subject: [PATCH] sk98lin: no d-link support (kconfig) The sk98lin driver was changed a while ago to remove support for the D-Link 530T card because that hardware has no working VPD data. The help text for Kconfig was not updated. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 47c72a63dfe1..ae8037acf489 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2082,7 +2082,6 @@ config SK98LIN - Allied Telesyn AT-2971SX Gigabit Ethernet Adapter - Allied Telesyn AT-2971T Gigabit Ethernet Adapter - Belkin Gigabit Desktop Card 10/100/1000Base-T Adapter, Copper RJ-45 - - DGE-530T Gigabit Ethernet Adapter - EG1032 v2 Instant Gigabit Network Adapter - EG1064 v2 Instant Gigabit Network Adapter - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Abit) -- cgit v1.2.3 From 7a160c735a264de400cbbf4cf0fb3250007ae0c6 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 13 Feb 2006 15:48:08 -0800 Subject: [PATCH] skge: no longer experimental Take the experimental dependency of skge driver, it is as stable as the others. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index ae8037acf489..e45a8f959719 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2020,8 +2020,8 @@ config SIS190 will be called sis190. This is recommended. config SKGE - tristate "New SysKonnect GigaEthernet support (EXPERIMENTAL)" - depends on PCI && EXPERIMENTAL + tristate "New SysKonnect GigaEthernet support" + depends on PCI select CRC32 ---help--- This driver support the Marvell Yukon or SysKonnect SK-98xx/SK-95xx -- cgit v1.2.3 From 564f9abb34c936e5d0c7682129042dad14dbbb95 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 13 Feb 2006 15:46:48 -0800 Subject: [PATCH] skge: speed setting This is a clone of John Linville's fixed for speed setting on sky2 driver. The skge driver has the same code (and bug). It would not allow manually forcing 100 and 10 mbit. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/skge.c b/drivers/net/skge.c index bf55a4cfb3d2..67fb19b8fde9 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -1697,6 +1697,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port) skge_write32(hw, SK_REG(port, GPHY_CTRL), reg | GPC_RST_SET); skge_write32(hw, SK_REG(port, GPHY_CTRL), reg | GPC_RST_CLR); skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR); + if (skge->autoneg == AUTONEG_DISABLE) { reg = GM_GPCR_AU_ALL_DIS; gma_write16(hw, port, GM_GP_CTRL, @@ -1704,16 +1705,23 @@ static void yukon_mac_init(struct skge_hw *hw, int port) switch (skge->speed) { case SPEED_1000: + reg &= ~GM_GPCR_SPEED_100; reg |= GM_GPCR_SPEED_1000; - /* fallthru */ + break; case SPEED_100: + reg &= ~GM_GPCR_SPEED_1000; reg |= GM_GPCR_SPEED_100; + break; + case SPEED_10: + reg &= ~(GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100); + break; } if (skge->duplex == DUPLEX_FULL) reg |= GM_GPCR_DUP_FULL; } else reg = GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100 | GM_GPCR_DUP_FULL; + switch (skge->flow_control) { case FLOW_MODE_NONE: skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); -- cgit v1.2.3 From 6f4c56b2ae10b680be518cc99f5308fc59236db2 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 10 Feb 2006 15:58:59 -0800 Subject: [PATCH] sky2: speed setting fix Users report problems w/ auto-negotiation disabled and the link set to 100/Half or 10/Half. Problems range from poor performance to no link at all. The current sky2 code does not set things properly on link up if autonegotiation is disabled. Plus it does not contemplate a 10Mbit setting at all. This patch corrects that. Signed-off-by: John W. Linville Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index cae2edf23004..bfeba5b9cd7a 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -520,10 +520,16 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) switch (sky2->speed) { case SPEED_1000: + reg &= ~GM_GPCR_SPEED_100; reg |= GM_GPCR_SPEED_1000; - /* fallthru */ + break; case SPEED_100: + reg &= ~GM_GPCR_SPEED_1000; reg |= GM_GPCR_SPEED_100; + break; + case SPEED_10: + reg &= ~(GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100); + break; } if (sky2->duplex == DUPLEX_FULL) @@ -1446,6 +1452,29 @@ static void sky2_link_up(struct sky2_port *sky2) sky2_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK); reg = gma_read16(hw, port, GM_GP_CTRL); + if (sky2->autoneg == AUTONEG_DISABLE) { + reg |= GM_GPCR_AU_ALL_DIS; + + /* Is write/read necessary? Copied from sky2_mac_init */ + gma_write16(hw, port, GM_GP_CTRL, reg); + gma_read16(hw, port, GM_GP_CTRL); + + switch (sky2->speed) { + case SPEED_1000: + reg &= ~GM_GPCR_SPEED_100; + reg |= GM_GPCR_SPEED_1000; + break; + case SPEED_100: + reg &= ~GM_GPCR_SPEED_1000; + reg |= GM_GPCR_SPEED_100; + break; + case SPEED_10: + reg &= ~(GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100); + break; + } + } else + reg &= ~GM_GPCR_AU_ALL_DIS; + if (sky2->duplex == DUPLEX_FULL || sky2->autoneg == AUTONEG_ENABLE) reg |= GM_GPCR_DUP_FULL; -- cgit v1.2.3 From ca5b0ec8ae9f11c85d1f27b19f182a054303f324 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 10 Feb 2006 02:00:43 -0800 Subject: [PATCH] smctr warning fix drivers/net/tokenring/smctr.c: In function `smctr_load_firmware': drivers/net/tokenring/smctr.c:2981: warning: assignment discards qualifiers from pointer target type Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/tokenring/smctr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/tokenring/smctr.h b/drivers/net/tokenring/smctr.h index b306c7e4c793..88dfa2e01d6e 100644 --- a/drivers/net/tokenring/smctr.h +++ b/drivers/net/tokenring/smctr.h @@ -1042,7 +1042,7 @@ typedef struct net_local { __u16 functional_address[2]; __u16 bitwise_group_address[2]; - __u8 *ptr_ucode; + const __u8 *ptr_ucode; __u8 cleanup; -- cgit v1.2.3 From 0d613a27cc753bfacd20e6eaa2183bb7fef4c76e Mon Sep 17 00:00:00 2001 From: Frank Pavlic Date: Tue, 7 Feb 2006 17:04:36 +0100 Subject: [PATCH] s390: lcs performance enhancements [patch 1/2] s390: lcs performance enhancements From: Klaus Wacker - When flood pinging (with large packet size) an LCS device, about 90 % of all packets are dropped by driver. - increased number of lcs IO buffers to 32. - use netif_stop_queue/netif_wake_queue in lcs_start_xmit routine - don't lock the whole xmit routine but just the piece of code where tx_buffer is touched. Signed-off-by: Frank Pavlic diffstat: lcs.c | 31 +++++++++++++++++-------------- lcs.h | 2 +- 2 files changed, 18 insertions(+), 15 deletions(-) Signed-off-by: Jeff Garzik --- drivers/s390/net/lcs.c | 31 +++++++++++++++++-------------- drivers/s390/net/lcs.h | 2 +- 2 files changed, 18 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 6229ba4995ad..9cf88d7201d3 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -98,9 +98,9 @@ lcs_register_debug_facility(void) return -ENOMEM; } debug_register_view(lcs_dbf_setup, &debug_hex_ascii_view); - debug_set_level(lcs_dbf_setup, 4); + debug_set_level(lcs_dbf_setup, 2); debug_register_view(lcs_dbf_trace, &debug_hex_ascii_view); - debug_set_level(lcs_dbf_trace, 4); + debug_set_level(lcs_dbf_trace, 2); return 0; } @@ -1292,9 +1292,8 @@ lcs_set_multicast_list(struct net_device *dev) LCS_DBF_TEXT(4, trace, "setmulti"); card = (struct lcs_card *) dev->priv; - if (!lcs_set_thread_start_bit(card, LCS_SET_MC_THREAD)) { + if (!lcs_set_thread_start_bit(card, LCS_SET_MC_THREAD)) schedule_work(&card->kernel_thread_starter); - } } #endif /* CONFIG_IP_MULTICAST */ @@ -1459,6 +1458,8 @@ lcs_txbuffer_cb(struct lcs_channel *channel, struct lcs_buffer *buffer) lcs_release_buffer(channel, buffer); card = (struct lcs_card *) ((char *) channel - offsetof(struct lcs_card, write)); + if (netif_queue_stopped(card->dev)) + netif_wake_queue(card->dev); spin_lock(&card->lock); card->tx_emitted--; if (card->tx_emitted <= 0 && card->tx_buffer != NULL) @@ -1478,6 +1479,7 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb, struct net_device *dev) { struct lcs_header *header; + int rc = 0; LCS_DBF_TEXT(5, trace, "hardxmit"); if (skb == NULL) { @@ -1492,10 +1494,8 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb, card->stats.tx_carrier_errors++; return 0; } - if (netif_queue_stopped(dev) ) { - card->stats.tx_dropped++; - return -EBUSY; - } + netif_stop_queue(card->dev); + spin_lock(&card->lock); if (card->tx_buffer != NULL && card->tx_buffer->count + sizeof(struct lcs_header) + skb->len + sizeof(u16) > LCS_IOBUFFERSIZE) @@ -1506,7 +1506,8 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb, card->tx_buffer = lcs_get_buffer(&card->write); if (card->tx_buffer == NULL) { card->stats.tx_dropped++; - return -EBUSY; + rc = -EBUSY; + goto out; } card->tx_buffer->callback = lcs_txbuffer_cb; card->tx_buffer->count = 0; @@ -1518,13 +1519,18 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb, header->type = card->lan_type; header->slot = card->portno; memcpy(header + 1, skb->data, skb->len); + spin_unlock(&card->lock); card->stats.tx_bytes += skb->len; card->stats.tx_packets++; dev_kfree_skb(skb); - if (card->tx_emitted <= 0) + netif_wake_queue(card->dev); + spin_lock(&card->lock); + if (card->tx_emitted <= 0 && card->tx_buffer != NULL) /* If this is the first tx buffer emit it immediately. */ __lcs_emit_txbuffer(card); - return 0; +out: + spin_unlock(&card->lock); + return rc; } static int @@ -1535,9 +1541,7 @@ lcs_start_xmit(struct sk_buff *skb, struct net_device *dev) LCS_DBF_TEXT(5, trace, "pktxmit"); card = (struct lcs_card *) dev->priv; - spin_lock(&card->lock); rc = __lcs_start_xmit(card, skb, dev); - spin_unlock(&card->lock); return rc; } @@ -2319,7 +2323,6 @@ __init lcs_init_module(void) PRINT_ERR("Initialization failed\n"); return rc; } - return 0; } diff --git a/drivers/s390/net/lcs.h b/drivers/s390/net/lcs.h index 08e60ad43916..2fad5e40c2e4 100644 --- a/drivers/s390/net/lcs.h +++ b/drivers/s390/net/lcs.h @@ -95,7 +95,7 @@ do { \ */ #define LCS_ILLEGAL_OFFSET 0xffff #define LCS_IOBUFFERSIZE 0x5000 -#define LCS_NUM_BUFFS 8 /* needs to be power of 2 */ +#define LCS_NUM_BUFFS 32 /* needs to be power of 2 */ #define LCS_MAC_LENGTH 6 #define LCS_INVALID_PORT_NO -1 #define LCS_LANCMD_TIMEOUT_DEFAULT 5 -- cgit v1.2.3 From 66cc5d5aee1ea427b3aeacdabd006a4195c81eee Mon Sep 17 00:00:00 2001 From: Frank Pavlic Date: Tue, 7 Feb 2006 17:04:38 +0100 Subject: [PATCH] s390: some qeth driver fixes [patch 2/2] s390: some qeth driver fixes From: Frank Pavlic - fixed kernel panic when using EDDP support in Layer 2 mode - NULL pointer exception in qeth_set_offline fixed. - setting EDDP in Layer 2 mode did not set NETIF_F_(SG/TSO) flags when device became online. - use sscanf for parsing and converting IPv4 addresses from string to __u8 values. - qeth_string_to_ipaddr6 fixed. in case of double colon the converted IPv6 address out from the string was not correct in previous implementation. Signed-off-by: Frank Pavlic diffstat: qeth.h | 112 +++++++++++++++++++++++++----------------------------------- qeth_eddp.c | 11 ++++- qeth_main.c | 17 +++------ 3 files changed, 63 insertions(+), 77 deletions(-) Signed-off-by: Jeff Garzik --- drivers/s390/net/qeth.h | 112 ++++++++++++++++++------------------------- drivers/s390/net/qeth_eddp.c | 11 ++++- drivers/s390/net/qeth_main.c | 17 +++---- 3 files changed, 63 insertions(+), 77 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h index 9a064d4727ad..4df0fcd7b10b 100644 --- a/drivers/s390/net/qeth.h +++ b/drivers/s390/net/qeth.h @@ -1075,16 +1075,6 @@ qeth_get_qdio_q_format(struct qeth_card *card) } } -static inline int -qeth_isdigit(char * buf) -{ - while (*buf) { - if (!isdigit(*buf++)) - return 0; - } - return 1; -} - static inline int qeth_isxdigit(char * buf) { @@ -1104,33 +1094,17 @@ qeth_ipaddr4_to_string(const __u8 *addr, char *buf) static inline int qeth_string_to_ipaddr4(const char *buf, __u8 *addr) { - const char *start, *end; - char abuf[4]; - char *tmp; - int len; - int i; - - start = buf; - for (i = 0; i < 4; i++) { - if (i == 3) { - end = strchr(start,0xa); - if (end) - len = end - start; - else - len = strlen(start); - } - else { - end = strchr(start, '.'); - len = end - start; - } - if ((len <= 0) || (len > 3)) - return -EINVAL; - memset(abuf, 0, 4); - strncpy(abuf, start, len); - if (!qeth_isdigit(abuf)) + int count = 0, rc = 0; + int in[4]; + + rc = sscanf(buf, "%d.%d.%d.%d%n", + &in[0], &in[1], &in[2], &in[3], &count); + if (rc != 4 || count) + return -EINVAL; + for (count = 0; count < 4; count++) { + if (in[count] > 255) return -EINVAL; - addr[i] = simple_strtoul(abuf, &tmp, 10); - start = end + 1; + addr[count] = in[count]; } return 0; } @@ -1149,36 +1123,44 @@ qeth_ipaddr6_to_string(const __u8 *addr, char *buf) static inline int qeth_string_to_ipaddr6(const char *buf, __u8 *addr) { - const char *start, *end; - u16 *tmp_addr; - char abuf[5]; - char *tmp; - int len; - int i; - - tmp_addr = (u16 *)addr; - start = buf; - for (i = 0; i < 8; i++) { - if (i == 7) { - end = strchr(start,0xa); - if (end) - len = end - start; - else - len = strlen(start); - } - else { - end = strchr(start, ':'); - len = end - start; + char *end, *start; + __u16 *in; + char num[5]; + int num2, cnt, out, found, save_cnt; + unsigned short in_tmp[8] = {0, }; + + cnt = out = found = save_cnt = num2 = 0; + end = start = (char *) buf; + in = (__u16 *) addr; + memset(in, 0, 16); + while (end) { + end = strchr(end,':'); + if (end == NULL) { + end = (char *)buf + (strlen(buf)); + out = 1; + } + if ((end - start)) { + memset(num, 0, 5); + memcpy(num, start, end - start); + if (!qeth_isxdigit(num)) + return -EINVAL; + sscanf(start, "%x", &num2); + if (found) + in_tmp[save_cnt++] = num2; + else + in[cnt++] = num2; + if (out) + break; + } else { + if (found) + return -EINVAL; + found = 1; } - if ((len <= 0) || (len > 4)) - return -EINVAL; - memset(abuf, 0, 5); - strncpy(abuf, start, len); - if (!qeth_isxdigit(abuf)) - return -EINVAL; - tmp_addr[i] = simple_strtoul(abuf, &tmp, 16); - start = end + 1; - } + start = ++end; + } + cnt = 7; + while (save_cnt) + in[cnt--] = in_tmp[--save_cnt]; return 0; } diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c index b02313127780..82cb4af2f0e7 100644 --- a/drivers/s390/net/qeth_eddp.c +++ b/drivers/s390/net/qeth_eddp.c @@ -59,8 +59,7 @@ qeth_eddp_free_context(struct qeth_eddp_context *ctx) for (i = 0; i < ctx->num_pages; ++i) free_page((unsigned long)ctx->pages[i]); kfree(ctx->pages); - if (ctx->elements != NULL) - kfree(ctx->elements); + kfree(ctx->elements); kfree(ctx); } @@ -413,6 +412,13 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, QETH_DBF_TEXT(trace, 5, "eddpftcp"); eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl; + if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) { + eddp->skb_offset += sizeof(struct ethhdr); +#ifdef CONFIG_QETH_VLAN + if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) + eddp->skb_offset += VLAN_HLEN; +#endif /* CONFIG_QETH_VLAN */ + } tcph = eddp->skb->h.th; while (eddp->skb_offset < eddp->skb->len) { data_len = min((int)skb_shinfo(eddp->skb)->tso_size, @@ -483,6 +489,7 @@ qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, return -ENOMEM; } if (qhdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) { + skb->mac.raw = (skb->data) + sizeof(struct qeth_hdr); memcpy(&eddp->mac, eth_hdr(skb), ETH_HLEN); #ifdef CONFIG_QETH_VLAN if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) { diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 410abeada6c4..dba7f7f02e79 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -516,7 +516,8 @@ __qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode) QETH_DBF_TEXT(setup, 3, "setoffl"); QETH_DBF_HEX(setup, 3, &card, sizeof(void *)); - netif_carrier_off(card->dev); + if (card->dev && netif_carrier_ok(card->dev)) + netif_carrier_off(card->dev); recover_flag = card->state; if (qeth_stop_card(card, recovery_mode) == -ERESTARTSYS){ PRINT_WARN("Stopping card %s interrupted by user!\n", @@ -1679,6 +1680,7 @@ qeth_cmd_timeout(unsigned long data) spin_unlock_irqrestore(&reply->card->lock, flags); } + static struct qeth_ipa_cmd * qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob) { @@ -1699,7 +1701,8 @@ qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob) QETH_CARD_IFNAME(card), card->info.chpid); card->lan_online = 0; - netif_carrier_off(card->dev); + if (card->dev && netif_carrier_ok(card->dev)) + netif_carrier_off(card->dev); return NULL; case IPA_CMD_STARTLAN: PRINT_INFO("Link reestablished on %s " @@ -5562,7 +5565,7 @@ qeth_set_multicast_list(struct net_device *dev) if (card->info.type == QETH_CARD_TYPE_OSN) return ; - QETH_DBF_TEXT(trace,3,"setmulti"); + QETH_DBF_TEXT(trace, 3, "setmulti"); qeth_delete_mc_addresses(card); if (card->options.layer2) { qeth_layer2_add_multicast(card); @@ -5579,7 +5582,6 @@ out: return; if (qeth_set_thread_start_bit(card, QETH_SET_PROMISC_MODE_THREAD)==0) schedule_work(&card->kernel_thread_starter); - } static int @@ -7452,6 +7454,7 @@ qeth_softsetup_card(struct qeth_card *card) card->lan_online = 1; if (card->info.type==QETH_CARD_TYPE_OSN) goto out; + qeth_set_large_send(card, card->options.large_send); if (card->options.layer2) { card->dev->features |= NETIF_F_HW_VLAN_FILTER | @@ -7468,12 +7471,6 @@ qeth_softsetup_card(struct qeth_card *card) #endif goto out; } - if ((card->options.large_send == QETH_LARGE_SEND_EDDP) || - (card->options.large_send == QETH_LARGE_SEND_TSO)) - card->dev->features |= NETIF_F_TSO | NETIF_F_SG; - else - card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG); - if ((rc = qeth_setadapter_parms(card))) QETH_DBF_TEXT_(setup, 2, "2err%d", rc); if ((rc = qeth_start_ipassists(card))) -- cgit v1.2.3 From f5e2a7b22e7d7dfda8794906d0fddeaaa09bb944 Mon Sep 17 00:00:00 2001 From: Jay Vosburgh Date: Tue, 7 Feb 2006 21:17:22 -0800 Subject: [PATCH] bonding: fix a locking bug in bond_release bond_release returns EINVAL without releasing the bond lock if the slave device is not being bonded by the bond. The following patch ensures that the lock is released in this case. Signed-off-by: Stephen J. Bevan Acked-by: Jay Vosburgh Signed-off-by: Jeff Garzik --- drivers/net/bonding/bond_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index e0f51afec778..bcf9f17daf0d 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1581,6 +1581,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) printk(KERN_INFO DRV_NAME ": %s: %s not enslaved\n", bond_dev->name, slave_dev->name); + write_unlock_bh(&bond->lock); return -EINVAL; } -- cgit v1.2.3