mirror of https://gitee.com/openkylin/linux.git
Merge branch 'upstream-fixes' into upstream
This commit is contained in:
commit
48cb37bd9e
|
@ -1676,10 +1676,8 @@ L: linux-kernel@vger.kernel.org
|
|||
S: Maintained
|
||||
|
||||
LAPB module
|
||||
P: Henner Eisen
|
||||
M: eis@baty.hanse.de
|
||||
L: linux-x25@vger.kernel.org
|
||||
S: Maintained
|
||||
S: Orphan
|
||||
|
||||
LASI 53c700 driver for PARISC
|
||||
P: James E.J. Bottomley
|
||||
|
|
|
@ -273,7 +273,7 @@ startup_continue:
|
|||
.Lbss_end: .long _end
|
||||
.Lparmaddr: .long PARMAREA
|
||||
.Lsccbaddr: .long .Lsccb
|
||||
.align 4096
|
||||
.org 0x12000
|
||||
.Lsccb:
|
||||
.hword 0x1000 # length, one page
|
||||
.byte 0x00,0x00,0x00
|
||||
|
@ -290,7 +290,7 @@ startup_continue:
|
|||
.Lscpincr2:
|
||||
.quad 0x00
|
||||
.fill 3984,1,0
|
||||
.align 4096
|
||||
.org 0x13000
|
||||
|
||||
#ifdef CONFIG_SHARED_KERNEL
|
||||
.org 0x100000
|
||||
|
|
|
@ -268,7 +268,7 @@ startup_continue:
|
|||
.Lparmaddr:
|
||||
.quad PARMAREA
|
||||
|
||||
.align 4096
|
||||
.org 0x12000
|
||||
.Lsccb:
|
||||
.hword 0x1000 # length, one page
|
||||
.byte 0x00,0x00,0x00
|
||||
|
@ -285,7 +285,7 @@ startup_continue:
|
|||
.Lscpincr2:
|
||||
.quad 0x00
|
||||
.fill 3984,1,0
|
||||
.align 4096
|
||||
.org 0x13000
|
||||
|
||||
#ifdef CONFIG_SHARED_KERNEL
|
||||
.org 0x100000
|
||||
|
|
|
@ -877,31 +877,57 @@ static struct bin_attribute ipl_scp_data_attr = {
|
|||
|
||||
static decl_subsys(ipl, NULL, NULL);
|
||||
|
||||
static int ipl_register_fcp_files(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = sysfs_create_group(&ipl_subsys.kset.kobj,
|
||||
&ipl_fcp_attr_group);
|
||||
if (rc)
|
||||
goto out;
|
||||
rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj,
|
||||
&ipl_parameter_attr);
|
||||
if (rc)
|
||||
goto out_ipl_parm;
|
||||
rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj,
|
||||
&ipl_scp_data_attr);
|
||||
if (!rc)
|
||||
goto out;
|
||||
|
||||
sysfs_remove_bin_file(&ipl_subsys.kset.kobj, &ipl_parameter_attr);
|
||||
|
||||
out_ipl_parm:
|
||||
sysfs_remove_group(&ipl_subsys.kset.kobj, &ipl_fcp_attr_group);
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __init
|
||||
ipl_device_sysfs_register(void) {
|
||||
int rc;
|
||||
|
||||
rc = firmware_register(&ipl_subsys);
|
||||
if (rc)
|
||||
return rc;
|
||||
goto out;
|
||||
|
||||
switch (get_ipl_type()) {
|
||||
case ipl_type_ccw:
|
||||
sysfs_create_group(&ipl_subsys.kset.kobj, &ipl_ccw_attr_group);
|
||||
rc = sysfs_create_group(&ipl_subsys.kset.kobj,
|
||||
&ipl_ccw_attr_group);
|
||||
break;
|
||||
case ipl_type_fcp:
|
||||
sysfs_create_group(&ipl_subsys.kset.kobj, &ipl_fcp_attr_group);
|
||||
sysfs_create_bin_file(&ipl_subsys.kset.kobj,
|
||||
&ipl_parameter_attr);
|
||||
sysfs_create_bin_file(&ipl_subsys.kset.kobj,
|
||||
&ipl_scp_data_attr);
|
||||
rc = ipl_register_fcp_files();
|
||||
break;
|
||||
default:
|
||||
sysfs_create_group(&ipl_subsys.kset.kobj,
|
||||
&ipl_unknown_attr_group);
|
||||
rc = sysfs_create_group(&ipl_subsys.kset.kobj,
|
||||
&ipl_unknown_attr_group);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
||||
if (rc)
|
||||
firmware_unregister(&ipl_subsys);
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
__initcall(ipl_device_sysfs_register);
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include <asm/page.h>
|
||||
#include <asm/oplib.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/cpudata.h>
|
||||
|
@ -34,12 +35,6 @@ static int check_cpu_node(int nd, int *cur_inst,
|
|||
int (*compare)(int, int, void *), void *compare_arg,
|
||||
int *prom_node, int *mid)
|
||||
{
|
||||
char node_str[128];
|
||||
|
||||
prom_getstring(nd, "device_type", node_str, sizeof(node_str));
|
||||
if (strcmp(node_str, "cpu"))
|
||||
return -ENODEV;
|
||||
|
||||
if (!compare(nd, *cur_inst, compare_arg)) {
|
||||
if (prom_node)
|
||||
*prom_node = nd;
|
||||
|
@ -59,20 +54,14 @@ static int check_cpu_node(int nd, int *cur_inst,
|
|||
static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg,
|
||||
int *prom_node, int *mid)
|
||||
{
|
||||
int nd, cur_inst, err;
|
||||
struct device_node *dp;
|
||||
int cur_inst;
|
||||
|
||||
nd = prom_root_node;
|
||||
cur_inst = 0;
|
||||
|
||||
err = check_cpu_node(nd, &cur_inst, compare, compare_arg,
|
||||
prom_node, mid);
|
||||
if (!err)
|
||||
return 0;
|
||||
|
||||
nd = prom_getchild(nd);
|
||||
while ((nd = prom_getsibling(nd)) != 0) {
|
||||
err = check_cpu_node(nd, &cur_inst, compare, compare_arg,
|
||||
prom_node, mid);
|
||||
for_each_node_by_type(dp, "cpu") {
|
||||
int err = check_cpu_node(dp->node, &cur_inst,
|
||||
compare, compare_arg,
|
||||
prom_node, mid);
|
||||
if (!err)
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -329,7 +329,7 @@ void handler_irq(int irq, struct pt_regs * regs)
|
|||
disable_pil_irq(irq);
|
||||
#ifdef CONFIG_SMP
|
||||
/* Only rotate on lower priority IRQ's (scsi, ethernet, etc.). */
|
||||
if(irq < 10)
|
||||
if((sparc_cpu_model==sun4m) && (irq < 10))
|
||||
smp4m_irq_rotate(cpu);
|
||||
#endif
|
||||
action = sparc_irq[irq].action;
|
||||
|
|
|
@ -596,14 +596,41 @@ static struct of_device * __init scan_one_device(struct device_node *dp,
|
|||
static int pil_to_sbus[] = {
|
||||
0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0,
|
||||
};
|
||||
struct device_node *busp = dp->parent;
|
||||
struct device_node *io_unit, *sbi = dp->parent;
|
||||
struct linux_prom_registers *regs;
|
||||
int board = of_getintprop_default(busp, "board#", 0);
|
||||
int slot;
|
||||
int board, slot;
|
||||
|
||||
while (sbi) {
|
||||
if (!strcmp(sbi->name, "sbi"))
|
||||
break;
|
||||
|
||||
sbi = sbi->parent;
|
||||
}
|
||||
if (!sbi)
|
||||
goto build_resources;
|
||||
|
||||
regs = of_get_property(dp, "reg", NULL);
|
||||
if (!regs)
|
||||
goto build_resources;
|
||||
|
||||
slot = regs->which_io;
|
||||
|
||||
/* If SBI's parent is not io-unit or the io-unit lacks
|
||||
* a "board#" property, something is very wrong.
|
||||
*/
|
||||
if (!sbi->parent || strcmp(sbi->parent->name, "io-unit")) {
|
||||
printk("%s: Error, parent is not io-unit.\n",
|
||||
sbi->full_name);
|
||||
goto build_resources;
|
||||
}
|
||||
io_unit = sbi->parent;
|
||||
board = of_getintprop_default(io_unit, "board#", -1);
|
||||
if (board == -1) {
|
||||
printk("%s: Error, lacks board# property.\n",
|
||||
io_unit->full_name);
|
||||
goto build_resources;
|
||||
}
|
||||
|
||||
for (i = 0; i < op->num_irqs; i++) {
|
||||
int this_irq = op->irqs[i];
|
||||
int sbusl = pil_to_sbus[this_irq];
|
||||
|
@ -617,6 +644,7 @@ static struct of_device * __init scan_one_device(struct device_node *dp,
|
|||
}
|
||||
}
|
||||
|
||||
build_resources:
|
||||
build_device_resources(op, parent);
|
||||
|
||||
op->dev.parent = parent;
|
||||
|
|
|
@ -444,6 +444,7 @@ static struct property * __init build_one_prop(phandle node, char *prev, char *s
|
|||
static struct property *tmp = NULL;
|
||||
struct property *p;
|
||||
int len;
|
||||
const char *name;
|
||||
|
||||
if (tmp) {
|
||||
p = tmp;
|
||||
|
@ -456,19 +457,21 @@ static struct property * __init build_one_prop(phandle node, char *prev, char *s
|
|||
|
||||
p->name = (char *) (p + 1);
|
||||
if (special_name) {
|
||||
strcpy(p->name, special_name);
|
||||
p->length = special_len;
|
||||
p->value = prom_early_alloc(special_len);
|
||||
memcpy(p->value, special_val, special_len);
|
||||
} else {
|
||||
if (prev == NULL) {
|
||||
prom_firstprop(node, p->name);
|
||||
name = prom_firstprop(node, NULL);
|
||||
} else {
|
||||
prom_nextprop(node, prev, p->name);
|
||||
name = prom_nextprop(node, prev, NULL);
|
||||
}
|
||||
if (strlen(p->name) == 0) {
|
||||
if (strlen(name) == 0) {
|
||||
tmp = p;
|
||||
return NULL;
|
||||
}
|
||||
strcpy(p->name, name);
|
||||
p->length = prom_getproplen(node, p->name);
|
||||
if (p->length <= 0) {
|
||||
p->length = 0;
|
||||
|
|
|
@ -87,6 +87,7 @@ void __cpuinit smp_store_cpu_info(int id)
|
|||
void __init smp_cpus_done(unsigned int max_cpus)
|
||||
{
|
||||
extern void smp4m_smp_done(void);
|
||||
extern void smp4d_smp_done(void);
|
||||
unsigned long bogosum = 0;
|
||||
int cpu, num;
|
||||
|
||||
|
@ -100,8 +101,34 @@ void __init smp_cpus_done(unsigned int max_cpus)
|
|||
num, bogosum/(500000/HZ),
|
||||
(bogosum/(5000/HZ))%100);
|
||||
|
||||
BUG_ON(sparc_cpu_model != sun4m);
|
||||
smp4m_smp_done();
|
||||
switch(sparc_cpu_model) {
|
||||
case sun4:
|
||||
printk("SUN4\n");
|
||||
BUG();
|
||||
break;
|
||||
case sun4c:
|
||||
printk("SUN4C\n");
|
||||
BUG();
|
||||
break;
|
||||
case sun4m:
|
||||
smp4m_smp_done();
|
||||
break;
|
||||
case sun4d:
|
||||
smp4d_smp_done();
|
||||
break;
|
||||
case sun4e:
|
||||
printk("SUN4E\n");
|
||||
BUG();
|
||||
break;
|
||||
case sun4u:
|
||||
printk("SUN4U\n");
|
||||
BUG();
|
||||
break;
|
||||
default:
|
||||
printk("UNKNOWN!\n");
|
||||
BUG();
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
void cpu_panic(void)
|
||||
|
@ -267,9 +294,9 @@ int setup_profiling_timer(unsigned int multiplier)
|
|||
void __init smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
extern void smp4m_boot_cpus(void);
|
||||
extern void smp4d_boot_cpus(void);
|
||||
int i, cpuid, extra;
|
||||
|
||||
BUG_ON(sparc_cpu_model != sun4m);
|
||||
printk("Entering SMP Mode...\n");
|
||||
|
||||
extra = 0;
|
||||
|
@ -283,7 +310,34 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
|
|||
|
||||
smp_store_cpu_info(boot_cpu_id);
|
||||
|
||||
smp4m_boot_cpus();
|
||||
switch(sparc_cpu_model) {
|
||||
case sun4:
|
||||
printk("SUN4\n");
|
||||
BUG();
|
||||
break;
|
||||
case sun4c:
|
||||
printk("SUN4C\n");
|
||||
BUG();
|
||||
break;
|
||||
case sun4m:
|
||||
smp4m_boot_cpus();
|
||||
break;
|
||||
case sun4d:
|
||||
smp4d_boot_cpus();
|
||||
break;
|
||||
case sun4e:
|
||||
printk("SUN4E\n");
|
||||
BUG();
|
||||
break;
|
||||
case sun4u:
|
||||
printk("SUN4U\n");
|
||||
BUG();
|
||||
break;
|
||||
default:
|
||||
printk("UNKNOWN!\n");
|
||||
BUG();
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
/* Set this up early so that things like the scheduler can init
|
||||
|
@ -323,9 +377,37 @@ void __init smp_prepare_boot_cpu(void)
|
|||
int __cpuinit __cpu_up(unsigned int cpu)
|
||||
{
|
||||
extern int smp4m_boot_one_cpu(int);
|
||||
int ret;
|
||||
extern int smp4d_boot_one_cpu(int);
|
||||
int ret=0;
|
||||
|
||||
ret = smp4m_boot_one_cpu(cpu);
|
||||
switch(sparc_cpu_model) {
|
||||
case sun4:
|
||||
printk("SUN4\n");
|
||||
BUG();
|
||||
break;
|
||||
case sun4c:
|
||||
printk("SUN4C\n");
|
||||
BUG();
|
||||
break;
|
||||
case sun4m:
|
||||
ret = smp4m_boot_one_cpu(cpu);
|
||||
break;
|
||||
case sun4d:
|
||||
ret = smp4d_boot_one_cpu(cpu);
|
||||
break;
|
||||
case sun4e:
|
||||
printk("SUN4E\n");
|
||||
BUG();
|
||||
break;
|
||||
case sun4u:
|
||||
printk("SUN4U\n");
|
||||
BUG();
|
||||
break;
|
||||
default:
|
||||
printk("UNKNOWN!\n");
|
||||
BUG();
|
||||
break;
|
||||
};
|
||||
|
||||
if (!ret) {
|
||||
cpu_set(cpu, smp_commenced_mask);
|
||||
|
|
|
@ -237,7 +237,6 @@ EXPORT_SYMBOL(prom_node_has_property);
|
|||
EXPORT_SYMBOL(prom_setprop);
|
||||
EXPORT_SYMBOL(saved_command_line);
|
||||
EXPORT_SYMBOL(prom_apply_obio_ranges);
|
||||
EXPORT_SYMBOL(prom_getname);
|
||||
EXPORT_SYMBOL(prom_feval);
|
||||
EXPORT_SYMBOL(prom_getbool);
|
||||
EXPORT_SYMBOL(prom_getstring);
|
||||
|
|
|
@ -43,15 +43,10 @@ extern ctxd_t *srmmu_ctx_table_phys;
|
|||
extern void calibrate_delay(void);
|
||||
|
||||
extern volatile int smp_processors_ready;
|
||||
extern int smp_num_cpus;
|
||||
static int smp_highest_cpu;
|
||||
extern volatile unsigned long cpu_callin_map[NR_CPUS];
|
||||
extern cpuinfo_sparc cpu_data[NR_CPUS];
|
||||
extern unsigned char boot_cpu_id;
|
||||
extern int smp_activated;
|
||||
extern volatile int __cpu_number_map[NR_CPUS];
|
||||
extern volatile int __cpu_logical_map[NR_CPUS];
|
||||
extern volatile unsigned long ipi_count;
|
||||
extern volatile int smp_process_available;
|
||||
|
||||
extern cpumask_t smp_commenced_mask;
|
||||
|
@ -144,6 +139,8 @@ void __init smp4d_callin(void)
|
|||
spin_lock_irqsave(&sun4d_imsk_lock, flags);
|
||||
cc_set_imsk(cc_get_imsk() & ~0x4000); /* Allow PIL 14 as well */
|
||||
spin_unlock_irqrestore(&sun4d_imsk_lock, flags);
|
||||
cpu_set(cpuid, cpu_online_map);
|
||||
|
||||
}
|
||||
|
||||
extern void init_IRQ(void);
|
||||
|
@ -160,51 +157,24 @@ extern unsigned long trapbase_cpu3[];
|
|||
|
||||
void __init smp4d_boot_cpus(void)
|
||||
{
|
||||
int cpucount = 0;
|
||||
int i, mid;
|
||||
|
||||
printk("Entering SMP Mode...\n");
|
||||
|
||||
if (boot_cpu_id)
|
||||
current_set[0] = NULL;
|
||||
|
||||
local_irq_enable();
|
||||
cpus_clear(cpu_present_map);
|
||||
|
||||
/* XXX This whole thing has to go. See sparc64. */
|
||||
for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++)
|
||||
cpu_set(mid, cpu_present_map);
|
||||
SMP_PRINTK(("cpu_present_map %08lx\n", cpus_addr(cpu_present_map)[0]));
|
||||
for(i=0; i < NR_CPUS; i++)
|
||||
__cpu_number_map[i] = -1;
|
||||
for(i=0; i < NR_CPUS; i++)
|
||||
__cpu_logical_map[i] = -1;
|
||||
__cpu_number_map[boot_cpu_id] = 0;
|
||||
__cpu_logical_map[0] = boot_cpu_id;
|
||||
current_thread_info()->cpu = boot_cpu_id;
|
||||
smp_store_cpu_info(boot_cpu_id);
|
||||
smp_setup_percpu_timer();
|
||||
local_flush_cache_all();
|
||||
if (cpu_find_by_instance(1, NULL, NULL))
|
||||
return; /* Not an MP box. */
|
||||
SMP_PRINTK(("Iterating over CPUs\n"));
|
||||
for(i = 0; i < NR_CPUS; i++) {
|
||||
if(i == boot_cpu_id)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cpu_isset(i, cpu_present_map)) {
|
||||
int smp4d_boot_one_cpu(int i)
|
||||
{
|
||||
extern unsigned long sun4d_cpu_startup;
|
||||
unsigned long *entry = &sun4d_cpu_startup;
|
||||
struct task_struct *p;
|
||||
int timeout;
|
||||
int no;
|
||||
int cpu_node;
|
||||
|
||||
cpu_find_by_instance(i, &cpu_node,NULL);
|
||||
/* Cook up an idler for this guy. */
|
||||
p = fork_idle(i);
|
||||
cpucount++;
|
||||
current_set[i] = task_thread_info(p);
|
||||
for (no = 0; !cpu_find_by_instance(no, NULL, &mid)
|
||||
&& mid != i; no++) ;
|
||||
|
||||
/*
|
||||
* Initialize the contexts table
|
||||
|
@ -216,9 +186,9 @@ void __init smp4d_boot_cpus(void)
|
|||
smp_penguin_ctable.reg_size = 0;
|
||||
|
||||
/* whirrr, whirrr, whirrrrrrrrr... */
|
||||
SMP_PRINTK(("Starting CPU %d at %p task %d node %08x\n", i, entry, cpucount, cpu_data(no).prom_node));
|
||||
SMP_PRINTK(("Starting CPU %d at %p \n", i, entry));
|
||||
local_flush_cache_all();
|
||||
prom_startcpu(cpu_data(no).prom_node,
|
||||
prom_startcpu(cpu_node,
|
||||
&smp_penguin_ctable, 0, (char *)entry);
|
||||
|
||||
SMP_PRINTK(("prom_startcpu returned :)\n"));
|
||||
|
@ -230,39 +200,30 @@ void __init smp4d_boot_cpus(void)
|
|||
udelay(200);
|
||||
}
|
||||
|
||||
if(cpu_callin_map[i]) {
|
||||
/* Another "Red Snapper". */
|
||||
__cpu_number_map[i] = cpucount;
|
||||
__cpu_logical_map[cpucount] = i;
|
||||
} else {
|
||||
cpucount--;
|
||||
printk("Processor %d is stuck.\n", i);
|
||||
}
|
||||
}
|
||||
if(!(cpu_callin_map[i])) {
|
||||
cpu_clear(i, cpu_present_map);
|
||||
__cpu_number_map[i] = -1;
|
||||
}
|
||||
if (!(cpu_callin_map[i])) {
|
||||
printk("Processor %d is stuck.\n", i);
|
||||
return -ENODEV;
|
||||
|
||||
}
|
||||
local_flush_cache_all();
|
||||
if(cpucount == 0) {
|
||||
printk("Error: only one Processor found.\n");
|
||||
cpu_present_map = cpumask_of_cpu(hard_smp4d_processor_id());
|
||||
} else {
|
||||
unsigned long bogosum = 0;
|
||||
|
||||
for_each_present_cpu(i) {
|
||||
bogosum += cpu_data(i).udelay_val;
|
||||
smp_highest_cpu = i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __init smp4d_smp_done(void)
|
||||
{
|
||||
int i, first;
|
||||
int *prev;
|
||||
|
||||
/* setup cpu list for irq rotation */
|
||||
first = 0;
|
||||
prev = &first;
|
||||
for (i = 0; i < NR_CPUS; i++)
|
||||
if (cpu_online(i)) {
|
||||
*prev = i;
|
||||
prev = &cpu_data(i).next;
|
||||
}
|
||||
SMP_PRINTK(("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n", cpucount + 1, bogosum/(500000/HZ), (bogosum/(5000/HZ))%100));
|
||||
printk("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n",
|
||||
cpucount + 1,
|
||||
bogosum/(500000/HZ),
|
||||
(bogosum/(5000/HZ))%100);
|
||||
smp_activated = 1;
|
||||
smp_num_cpus = cpucount + 1;
|
||||
}
|
||||
*prev = first;
|
||||
local_flush_cache_all();
|
||||
|
||||
/* Free unneeded trap tables */
|
||||
ClearPageReserved(virt_to_page(trapbase_cpu1));
|
||||
|
@ -334,7 +295,7 @@ void smp4d_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2,
|
|||
register int i;
|
||||
|
||||
mask = cpumask_of_cpu(hard_smp4d_processor_id());
|
||||
cpus_andnot(mask, cpu_present_map, mask);
|
||||
cpus_andnot(mask, cpu_online_map, mask);
|
||||
for(i = 0; i <= high; i++) {
|
||||
if (cpu_isset(i, mask)) {
|
||||
ccall_info.processors_in[i] = 0;
|
||||
|
|
|
@ -465,21 +465,21 @@ sys_rt_sigaction(int sig,
|
|||
|
||||
asmlinkage int sys_getdomainname(char __user *name, int len)
|
||||
{
|
||||
int nlen;
|
||||
int err = -EFAULT;
|
||||
int nlen, err;
|
||||
|
||||
if (len < 0 || len > __NEW_UTS_LEN)
|
||||
return -EINVAL;
|
||||
|
||||
down_read(&uts_sem);
|
||||
|
||||
nlen = strlen(system_utsname.domainname) + 1;
|
||||
|
||||
if (nlen < len)
|
||||
len = nlen;
|
||||
if (len > __NEW_UTS_LEN)
|
||||
goto done;
|
||||
if (copy_to_user(name, system_utsname.domainname, len))
|
||||
goto done;
|
||||
err = 0;
|
||||
done:
|
||||
|
||||
err = -EFAULT;
|
||||
if (!copy_to_user(name, system_utsname.domainname, len))
|
||||
err = 0;
|
||||
|
||||
up_read(&uts_sem);
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@ iounit_init(int sbi_node, int io_node, struct sbus_bus *sbus)
|
|||
|
||||
sbus->iommu = (struct iommu_struct *)iounit;
|
||||
iounit->page_table = xpt;
|
||||
spin_lock_init(&iounit->lock);
|
||||
|
||||
for (xptend = iounit->page_table + (16 * PAGE_SIZE) / sizeof(iopte_t);
|
||||
xpt < xptend;)
|
||||
|
|
|
@ -205,24 +205,6 @@ int prom_searchsiblings(int node_start, char *nodename)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Gets name in the form prom v2+ uses it (name@x,yyyyy or name (if no reg)) */
|
||||
int prom_getname (int node, char *buffer, int len)
|
||||
{
|
||||
int i;
|
||||
struct linux_prom_registers reg[PROMREG_MAX];
|
||||
|
||||
i = prom_getproperty (node, "name", buffer, len);
|
||||
if (i <= 0) return -1;
|
||||
buffer [i] = 0;
|
||||
len -= i;
|
||||
i = prom_getproperty (node, "reg", (char *)reg, sizeof (reg));
|
||||
if (i <= 0) return 0;
|
||||
if (len < 11) return -1;
|
||||
buffer = strchr (buffer, 0);
|
||||
sprintf (buffer, "@%x,%x", reg[0].which_io, (uint)reg[0].phys_addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Interal version of nextprop that does not alter return values. */
|
||||
char * __prom_nextprop(int node, char * oprop)
|
||||
{
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.18-rc1
|
||||
# Wed Jul 12 14:00:58 2006
|
||||
# Linux kernel version: 2.6.18-rc2
|
||||
# Fri Jul 21 14:19:24 2006
|
||||
#
|
||||
CONFIG_SPARC=y
|
||||
CONFIG_SPARC64=y
|
||||
|
@ -36,6 +36,7 @@ CONFIG_SWAP=y
|
|||
CONFIG_SYSVIPC=y
|
||||
CONFIG_POSIX_MQUEUE=y
|
||||
# CONFIG_BSD_PROCESS_ACCT is not set
|
||||
# CONFIG_TASKSTATS is not set
|
||||
CONFIG_SYSCTL=y
|
||||
# CONFIG_AUDIT is not set
|
||||
# CONFIG_IKCONFIG is not set
|
||||
|
@ -1120,7 +1121,7 @@ CONFIG_USB_HIDDEV=y
|
|||
# CONFIG_USB_LEGOTOWER is not set
|
||||
# CONFIG_USB_LCD is not set
|
||||
# CONFIG_USB_LED is not set
|
||||
# CONFIG_USB_CY7C63 is not set
|
||||
# CONFIG_USB_CYPRESS_CY7C63 is not set
|
||||
# CONFIG_USB_CYTHERM is not set
|
||||
# CONFIG_USB_PHIDGETKIT is not set
|
||||
# CONFIG_USB_PHIDGETSERVO is not set
|
||||
|
@ -1279,7 +1280,6 @@ CONFIG_RAMFS=y
|
|||
# CONFIG_NFSD is not set
|
||||
# CONFIG_SMB_FS is not set
|
||||
# CONFIG_CIFS is not set
|
||||
# CONFIG_CIFS_DEBUG2 is not set
|
||||
# CONFIG_NCP_FS is not set
|
||||
# CONFIG_CODA_FS is not set
|
||||
# CONFIG_AFS_FS is not set
|
||||
|
|
|
@ -66,9 +66,6 @@ static int check_cpu_node(struct device_node *dp, int *cur_inst,
|
|||
void *compare_arg,
|
||||
struct device_node **dev_node, int *mid)
|
||||
{
|
||||
if (strcmp(dp->type, "cpu"))
|
||||
return -ENODEV;
|
||||
|
||||
if (!compare(dp, *cur_inst, compare_arg)) {
|
||||
if (dev_node)
|
||||
*dev_node = dp;
|
||||
|
|
|
@ -542,9 +542,17 @@ static void __init build_device_resources(struct of_device *op,
|
|||
/* Convert to num-cells. */
|
||||
num_reg /= 4;
|
||||
|
||||
/* Conver to num-entries. */
|
||||
/* Convert to num-entries. */
|
||||
num_reg /= na + ns;
|
||||
|
||||
/* Prevent overruning the op->resources[] array. */
|
||||
if (num_reg > PROMREG_MAX) {
|
||||
printk(KERN_WARNING "%s: Too many regs (%d), "
|
||||
"limiting to %d.\n",
|
||||
op->node->full_name, num_reg, PROMREG_MAX);
|
||||
num_reg = PROMREG_MAX;
|
||||
}
|
||||
|
||||
for (index = 0; index < num_reg; index++) {
|
||||
struct resource *r = &op->resource[index];
|
||||
u32 addr[OF_MAX_ADDR_CELLS];
|
||||
|
@ -650,8 +658,22 @@ apply_interrupt_map(struct device_node *dp, struct device_node *pp,
|
|||
next:
|
||||
imap += (na + 3);
|
||||
}
|
||||
if (i == imlen)
|
||||
if (i == imlen) {
|
||||
/* Psycho and Sabre PCI controllers can have 'interrupt-map'
|
||||
* properties that do not include the on-board device
|
||||
* interrupts. Instead, the device's 'interrupts' property
|
||||
* is already a fully specified INO value.
|
||||
*
|
||||
* Handle this by deciding that, if we didn't get a
|
||||
* match in the parent's 'interrupt-map', and the
|
||||
* parent is an IRQ translater, then use the parent as
|
||||
* our IRQ controller.
|
||||
*/
|
||||
if (pp->irq_trans)
|
||||
return pp;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*irq_p = irq;
|
||||
cp = of_find_node_by_phandle(handle);
|
||||
|
@ -803,6 +825,14 @@ static struct of_device * __init scan_one_device(struct device_node *dp,
|
|||
op->num_irqs = 0;
|
||||
}
|
||||
|
||||
/* Prevent overruning the op->irqs[] array. */
|
||||
if (op->num_irqs > PROMINTR_MAX) {
|
||||
printk(KERN_WARNING "%s: Too many irqs (%d), "
|
||||
"limiting to %d.\n",
|
||||
dp->full_name, op->num_irqs, PROMINTR_MAX);
|
||||
op->num_irqs = PROMINTR_MAX;
|
||||
}
|
||||
|
||||
build_device_resources(op, parent);
|
||||
for (i = 0; i < op->num_irqs; i++)
|
||||
op->irqs[i] = build_one_device_irq(op, parent, op->irqs[i]);
|
||||
|
|
|
@ -344,10 +344,12 @@ static unsigned long __psycho_onboard_imap_off[] = {
|
|||
/*0x2f*/ PSYCHO_IMAP_CE,
|
||||
/*0x30*/ PSYCHO_IMAP_A_ERR,
|
||||
/*0x31*/ PSYCHO_IMAP_B_ERR,
|
||||
/*0x32*/ PSYCHO_IMAP_PMGMT
|
||||
/*0x32*/ PSYCHO_IMAP_PMGMT,
|
||||
/*0x33*/ PSYCHO_IMAP_GFX,
|
||||
/*0x34*/ PSYCHO_IMAP_EUPA,
|
||||
};
|
||||
#define PSYCHO_ONBOARD_IRQ_BASE 0x20
|
||||
#define PSYCHO_ONBOARD_IRQ_LAST 0x32
|
||||
#define PSYCHO_ONBOARD_IRQ_LAST 0x34
|
||||
#define psycho_onboard_imap_offset(__ino) \
|
||||
__psycho_onboard_imap_off[(__ino) - PSYCHO_ONBOARD_IRQ_BASE]
|
||||
|
||||
|
@ -529,6 +531,10 @@ static unsigned long __sabre_onboard_imap_off[] = {
|
|||
/*0x2e*/ SABRE_IMAP_UE,
|
||||
/*0x2f*/ SABRE_IMAP_CE,
|
||||
/*0x30*/ SABRE_IMAP_PCIERR,
|
||||
/*0x31*/ 0 /* reserved */,
|
||||
/*0x32*/ 0 /* reserved */,
|
||||
/*0x33*/ SABRE_IMAP_GFX,
|
||||
/*0x34*/ SABRE_IMAP_EUPA,
|
||||
};
|
||||
#define SABRE_ONBOARD_IRQ_BASE 0x20
|
||||
#define SABRE_ONBOARD_IRQ_LAST 0x30
|
||||
|
@ -895,6 +901,8 @@ static unsigned long sysio_irq_offsets[] = {
|
|||
SYSIO_IMAP_CE,
|
||||
SYSIO_IMAP_SBERR,
|
||||
SYSIO_IMAP_PMGMT,
|
||||
SYSIO_IMAP_GFX,
|
||||
SYSIO_IMAP_EUPA,
|
||||
};
|
||||
|
||||
#undef bogon
|
||||
|
|
|
@ -254,7 +254,6 @@ EXPORT_SYMBOL(prom_getproperty);
|
|||
EXPORT_SYMBOL(prom_node_has_property);
|
||||
EXPORT_SYMBOL(prom_setprop);
|
||||
EXPORT_SYMBOL(saved_command_line);
|
||||
EXPORT_SYMBOL(prom_getname);
|
||||
EXPORT_SYMBOL(prom_finddevice);
|
||||
EXPORT_SYMBOL(prom_feval);
|
||||
EXPORT_SYMBOL(prom_getbool);
|
||||
|
|
|
@ -701,21 +701,21 @@ extern void check_pending(int signum);
|
|||
|
||||
asmlinkage long sys_getdomainname(char __user *name, int len)
|
||||
{
|
||||
int nlen;
|
||||
int err = -EFAULT;
|
||||
int nlen, err;
|
||||
|
||||
if (len < 0 || len > __NEW_UTS_LEN)
|
||||
return -EINVAL;
|
||||
|
||||
down_read(&uts_sem);
|
||||
|
||||
nlen = strlen(system_utsname.domainname) + 1;
|
||||
|
||||
if (nlen < len)
|
||||
len = nlen;
|
||||
if (len > __NEW_UTS_LEN)
|
||||
goto done;
|
||||
if (copy_to_user(name, system_utsname.domainname, len))
|
||||
goto done;
|
||||
err = 0;
|
||||
done:
|
||||
|
||||
err = -EFAULT;
|
||||
if (!copy_to_user(name, system_utsname.domainname, len))
|
||||
err = 0;
|
||||
|
||||
up_read(&uts_sem);
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -193,91 +193,6 @@ prom_searchsiblings(int node_start, const char *nodename)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Gets name in the {name@x,yyyyy|name (if no reg)} form */
|
||||
int
|
||||
prom_getname (int node, char *buffer, int len)
|
||||
{
|
||||
int i, sbus = 0;
|
||||
int pci = 0, ebus = 0, ide = 0;
|
||||
struct linux_prom_registers *reg;
|
||||
struct linux_prom64_registers reg64[PROMREG_MAX];
|
||||
|
||||
for (sbus = prom_getparent (node); sbus; sbus = prom_getparent (sbus)) {
|
||||
i = prom_getproperty (sbus, "name", buffer, len);
|
||||
if (i > 0) {
|
||||
buffer [i] = 0;
|
||||
if (!strcmp (buffer, "sbus"))
|
||||
goto getit;
|
||||
}
|
||||
}
|
||||
if ((pci = prom_getparent (node))) {
|
||||
i = prom_getproperty (pci, "name", buffer, len);
|
||||
if (i > 0) {
|
||||
buffer [i] = 0;
|
||||
if (!strcmp (buffer, "pci"))
|
||||
goto getit;
|
||||
}
|
||||
pci = 0;
|
||||
}
|
||||
if ((ebus = prom_getparent (node))) {
|
||||
i = prom_getproperty (ebus, "name", buffer, len);
|
||||
if (i > 0) {
|
||||
buffer[i] = 0;
|
||||
if (!strcmp (buffer, "ebus"))
|
||||
goto getit;
|
||||
}
|
||||
ebus = 0;
|
||||
}
|
||||
if ((ide = prom_getparent (node))) {
|
||||
i = prom_getproperty (ide, "name", buffer, len);
|
||||
if (i > 0) {
|
||||
buffer [i] = 0;
|
||||
if (!strcmp (buffer, "ide"))
|
||||
goto getit;
|
||||
}
|
||||
ide = 0;
|
||||
}
|
||||
getit:
|
||||
i = prom_getproperty (node, "name", buffer, len);
|
||||
if (i <= 0) {
|
||||
buffer [0] = 0;
|
||||
return -1;
|
||||
}
|
||||
buffer [i] = 0;
|
||||
len -= i;
|
||||
i = prom_getproperty (node, "reg", (char *)reg64, sizeof (reg64));
|
||||
if (i <= 0) return 0;
|
||||
if (len < 16) return -1;
|
||||
buffer = strchr (buffer, 0);
|
||||
if (sbus) {
|
||||
reg = (struct linux_prom_registers *)reg64;
|
||||
sprintf (buffer, "@%x,%x", reg[0].which_io, (uint)reg[0].phys_addr);
|
||||
} else if (pci) {
|
||||
int dev, fn;
|
||||
reg = (struct linux_prom_registers *)reg64;
|
||||
fn = (reg[0].which_io >> 8) & 0x07;
|
||||
dev = (reg[0].which_io >> 11) & 0x1f;
|
||||
if (fn)
|
||||
sprintf (buffer, "@%x,%x", dev, fn);
|
||||
else
|
||||
sprintf (buffer, "@%x", dev);
|
||||
} else if (ebus) {
|
||||
reg = (struct linux_prom_registers *)reg64;
|
||||
sprintf (buffer, "@%x,%x", reg[0].which_io, reg[0].phys_addr);
|
||||
} else if (ide) {
|
||||
reg = (struct linux_prom_registers *)reg64;
|
||||
sprintf (buffer, "@%x,%x", reg[0].which_io, reg[0].phys_addr);
|
||||
} else if (i == 4) { /* Happens on 8042's children on Ultra/PCI. */
|
||||
reg = (struct linux_prom_registers *)reg64;
|
||||
sprintf (buffer, "@%x", reg[0].which_io);
|
||||
} else {
|
||||
sprintf (buffer, "@%x,%x",
|
||||
(unsigned int)(reg64[0].phys_addr >> 36),
|
||||
(unsigned int)(reg64[0].phys_addr));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return the first property type for node 'node'.
|
||||
* buffer should be at least 32B in length
|
||||
*/
|
||||
|
|
|
@ -1174,8 +1174,12 @@ static void dcd_change(MGSLPC_INFO *info)
|
|||
else
|
||||
info->input_signal_events.dcd_down++;
|
||||
#ifdef CONFIG_HDLC
|
||||
if (info->netcount)
|
||||
hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, info->netdev);
|
||||
if (info->netcount) {
|
||||
if (info->serial_signals & SerialSignal_DCD)
|
||||
netif_carrier_on(info->netdev);
|
||||
else
|
||||
netif_carrier_off(info->netdev);
|
||||
}
|
||||
#endif
|
||||
wake_up_interruptible(&info->status_event_wait_q);
|
||||
wake_up_interruptible(&info->event_wait_q);
|
||||
|
@ -4251,8 +4255,10 @@ static int hdlcdev_open(struct net_device *dev)
|
|||
spin_lock_irqsave(&info->lock, flags);
|
||||
get_signals(info);
|
||||
spin_unlock_irqrestore(&info->lock, flags);
|
||||
hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, dev);
|
||||
|
||||
if (info->serial_signals & SerialSignal_DCD)
|
||||
netif_carrier_on(dev);
|
||||
else
|
||||
netif_carrier_off(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1344,8 +1344,12 @@ static void mgsl_isr_io_pin( struct mgsl_struct *info )
|
|||
} else
|
||||
info->input_signal_events.dcd_down++;
|
||||
#ifdef CONFIG_HDLC
|
||||
if (info->netcount)
|
||||
hdlc_set_carrier(status & MISCSTATUS_DCD, info->netdev);
|
||||
if (info->netcount) {
|
||||
if (status & MISCSTATUS_DCD)
|
||||
netif_carrier_on(info->netdev);
|
||||
else
|
||||
netif_carrier_off(info->netdev);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (status & MISCSTATUS_CTS_LATCHED)
|
||||
|
@ -7844,8 +7848,10 @@ static int hdlcdev_open(struct net_device *dev)
|
|||
spin_lock_irqsave(&info->irq_spinlock, flags);
|
||||
usc_get_serial_signals(info);
|
||||
spin_unlock_irqrestore(&info->irq_spinlock, flags);
|
||||
hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, dev);
|
||||
|
||||
if (info->serial_signals & SerialSignal_DCD)
|
||||
netif_carrier_on(dev);
|
||||
else
|
||||
netif_carrier_off(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1497,8 +1497,10 @@ static int hdlcdev_open(struct net_device *dev)
|
|||
spin_lock_irqsave(&info->lock, flags);
|
||||
get_signals(info);
|
||||
spin_unlock_irqrestore(&info->lock, flags);
|
||||
hdlc_set_carrier(info->signals & SerialSignal_DCD, dev);
|
||||
|
||||
if (info->signals & SerialSignal_DCD)
|
||||
netif_carrier_on(dev);
|
||||
else
|
||||
netif_carrier_off(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1997,8 +1999,12 @@ static void dcd_change(struct slgt_info *info)
|
|||
info->input_signal_events.dcd_down++;
|
||||
}
|
||||
#ifdef CONFIG_HDLC
|
||||
if (info->netcount)
|
||||
hdlc_set_carrier(info->signals & SerialSignal_DCD, info->netdev);
|
||||
if (info->netcount) {
|
||||
if (info->signals & SerialSignal_DCD)
|
||||
netif_carrier_on(info->netdev);
|
||||
else
|
||||
netif_carrier_off(info->netdev);
|
||||
}
|
||||
#endif
|
||||
wake_up_interruptible(&info->status_event_wait_q);
|
||||
wake_up_interruptible(&info->event_wait_q);
|
||||
|
|
|
@ -1752,8 +1752,10 @@ static int hdlcdev_open(struct net_device *dev)
|
|||
spin_lock_irqsave(&info->lock, flags);
|
||||
get_signals(info);
|
||||
spin_unlock_irqrestore(&info->lock, flags);
|
||||
hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, dev);
|
||||
|
||||
if (info->serial_signals & SerialSignal_DCD)
|
||||
netif_carrier_on(dev);
|
||||
else
|
||||
netif_carrier_off(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2522,8 +2524,12 @@ void isr_io_pin( SLMP_INFO *info, u16 status )
|
|||
} else
|
||||
info->input_signal_events.dcd_down++;
|
||||
#ifdef CONFIG_HDLC
|
||||
if (info->netcount)
|
||||
hdlc_set_carrier(status & SerialSignal_DCD, info->netdev);
|
||||
if (info->netcount) {
|
||||
if (status & SerialSignal_DCD)
|
||||
netif_carrier_on(info->netdev);
|
||||
else
|
||||
netif_carrier_off(info->netdev);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (status & MISCSTATUS_CTS_LATCHED)
|
||||
|
|
|
@ -239,6 +239,8 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
|
|||
total_ticks = (unsigned int) cputime64_sub(cur_jiffies,
|
||||
this_dbs_info->prev_cpu_wall);
|
||||
this_dbs_info->prev_cpu_wall = cur_jiffies;
|
||||
if (!total_ticks)
|
||||
return;
|
||||
/*
|
||||
* Every sampling_rate, we check, if current idle time is less
|
||||
* than 20% (default), then we try to increase frequency
|
||||
|
@ -304,6 +306,9 @@ static void do_dbs_timer(void *data)
|
|||
unsigned int cpu = smp_processor_id();
|
||||
struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu);
|
||||
|
||||
if (!dbs_info->enable)
|
||||
return;
|
||||
|
||||
dbs_check_cpu(dbs_info);
|
||||
queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work,
|
||||
usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
|
||||
|
@ -319,11 +324,11 @@ static inline void dbs_timer_init(unsigned int cpu)
|
|||
return;
|
||||
}
|
||||
|
||||
static inline void dbs_timer_exit(unsigned int cpu)
|
||||
static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)
|
||||
{
|
||||
struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu);
|
||||
|
||||
cancel_rearming_delayed_workqueue(kondemand_wq, &dbs_info->work);
|
||||
dbs_info->enable = 0;
|
||||
cancel_delayed_work(&dbs_info->work);
|
||||
flush_workqueue(kondemand_wq);
|
||||
}
|
||||
|
||||
static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
|
||||
|
@ -396,8 +401,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
|
|||
|
||||
case CPUFREQ_GOV_STOP:
|
||||
mutex_lock(&dbs_mutex);
|
||||
dbs_timer_exit(policy->cpu);
|
||||
this_dbs_info->enable = 0;
|
||||
dbs_timer_exit(this_dbs_info);
|
||||
sysfs_remove_group(&policy->kobj, &dbs_attr_group);
|
||||
dbs_enable--;
|
||||
if (dbs_enable == 0)
|
||||
|
|
|
@ -828,7 +828,7 @@ static int __init ioat_init_module(void)
|
|||
/* if forced, worst case is that rmmod hangs */
|
||||
__unsafe(THIS_MODULE);
|
||||
|
||||
return pci_module_init(&ioat_pci_drv);
|
||||
return pci_register_driver(&ioat_pci_drv);
|
||||
}
|
||||
|
||||
module_init(ioat_init_module);
|
||||
|
|
|
@ -429,7 +429,7 @@ static inline void fcp_scsi_receive(fc_channel *fc, int token, int status, fc_hd
|
|||
|
||||
if (fcmd->data) {
|
||||
if (SCpnt->use_sg)
|
||||
dma_unmap_sg(fc->dev, (struct scatterlist *)SCpnt->buffer,
|
||||
dma_unmap_sg(fc->dev, (struct scatterlist *)SCpnt->request_buffer,
|
||||
SCpnt->use_sg,
|
||||
SCpnt->sc_data_direction);
|
||||
else
|
||||
|
@ -810,7 +810,7 @@ static int fcp_scsi_queue_it(fc_channel *fc, Scsi_Cmnd *SCpnt, fcp_cmnd *fcmd, i
|
|||
SCpnt->request_bufflen,
|
||||
SCpnt->sc_data_direction);
|
||||
} else {
|
||||
struct scatterlist *sg = (struct scatterlist *)SCpnt->buffer;
|
||||
struct scatterlist *sg = (struct scatterlist *)SCpnt->request_buffer;
|
||||
int nents;
|
||||
|
||||
FCD(("XXX: Use_sg %d %d\n", SCpnt->use_sg, sg->length))
|
||||
|
|
|
@ -48,10 +48,8 @@ config FUSION_SAS
|
|||
List of supported controllers:
|
||||
|
||||
LSISAS1064
|
||||
LSISAS1066
|
||||
LSISAS1068
|
||||
LSISAS1064E
|
||||
LSISAS1066E
|
||||
LSISAS1068E
|
||||
|
||||
config FUSION_MAX_SGE
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#EXTRA_CFLAGS += -DMPT_DEBUG_EXIT
|
||||
#EXTRA_CFLAGS += -DMPT_DEBUG_FAIL
|
||||
|
||||
|
||||
#
|
||||
# driver/module specifics...
|
||||
#
|
||||
|
|
|
@ -436,8 +436,6 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
|
|||
*/
|
||||
if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) {
|
||||
freereq = 0;
|
||||
devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p does not return Request frame\n",
|
||||
ioc->name, pEvReply));
|
||||
} else {
|
||||
devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
|
||||
ioc->name, pEvReply));
|
||||
|
@ -678,19 +676,19 @@ int
|
|||
mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
|
||||
{
|
||||
MPT_ADAPTER *ioc;
|
||||
const struct pci_device_id *id;
|
||||
|
||||
if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) {
|
||||
if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
|
||||
|
||||
/* call per pci device probe entry point */
|
||||
list_for_each_entry(ioc, &ioc_list, list) {
|
||||
if(dd_cbfunc->probe) {
|
||||
dd_cbfunc->probe(ioc->pcidev,
|
||||
ioc->pcidev->driver->id_table);
|
||||
}
|
||||
id = ioc->pcidev->driver ?
|
||||
ioc->pcidev->driver->id_table : NULL;
|
||||
if (dd_cbfunc->probe)
|
||||
dd_cbfunc->probe(ioc->pcidev, id);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1056,9 +1054,8 @@ mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
|
|||
|
||||
dinitprintk((MYIOC_s_INFO_FMT
|
||||
"host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",
|
||||
ioc->name,
|
||||
ioc->HostPageBuffer,
|
||||
ioc->HostPageBuffer_dma,
|
||||
ioc->name, ioc->HostPageBuffer,
|
||||
(u32)ioc->HostPageBuffer_dma,
|
||||
host_page_buffer_sz));
|
||||
ioc->alloc_total += host_page_buffer_sz;
|
||||
ioc->HostPageBuffer_sz = host_page_buffer_sz;
|
||||
|
@ -1380,6 +1377,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
printk(KERN_WARNING MYNAM
|
||||
": WARNING - %s did not initialize properly! (%d)\n",
|
||||
ioc->name, r);
|
||||
|
||||
list_del(&ioc->list);
|
||||
if (ioc->alt_ioc)
|
||||
ioc->alt_ioc->alt_ioc = NULL;
|
||||
|
@ -1762,9 +1760,9 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
|
|||
* chips (mpt_adapter_disable,
|
||||
* mpt_diag_reset)
|
||||
*/
|
||||
ioc->cached_fw = NULL;
|
||||
ddlprintk((MYIOC_s_INFO_FMT ": mpt_upload: alt_%s has cached_fw=%p \n",
|
||||
ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
|
||||
ioc->alt_ioc->cached_fw = NULL;
|
||||
}
|
||||
} else {
|
||||
printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
|
||||
|
@ -1885,7 +1883,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
|
|||
/* FIXME? Examine results here? */
|
||||
}
|
||||
|
||||
out:
|
||||
out:
|
||||
if ((ret != 0) && irq_allocated) {
|
||||
free_irq(ioc->pci_irq, ioc);
|
||||
if (mpt_msi_enable)
|
||||
|
@ -2670,6 +2668,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
|
|||
dinitprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
|
||||
ioc->name, count));
|
||||
|
||||
ioc->aen_event_read_flag=0;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -2737,6 +2736,8 @@ mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
|
|||
if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
|
||||
ioc->cached_fw = ioc->alt_ioc->cached_fw; /* use alt_ioc's memory */
|
||||
ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
|
||||
ioc->alloc_total += size;
|
||||
ioc->alt_ioc->alloc_total -= size;
|
||||
} else {
|
||||
if ( (ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma) ) )
|
||||
ioc->alloc_total += size;
|
||||
|
@ -3166,6 +3167,7 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
|
|||
static int
|
||||
mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
|
||||
{
|
||||
MPT_ADAPTER *iocp=NULL;
|
||||
u32 diag0val;
|
||||
u32 doorbell;
|
||||
int hard_reset_done = 0;
|
||||
|
@ -3301,17 +3303,23 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
|
|||
/* FIXME? Examine results here? */
|
||||
}
|
||||
|
||||
if (ioc->cached_fw) {
|
||||
if (ioc->cached_fw)
|
||||
iocp = ioc;
|
||||
else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
|
||||
iocp = ioc->alt_ioc;
|
||||
if (iocp) {
|
||||
/* If the DownloadBoot operation fails, the
|
||||
* IOC will be left unusable. This is a fatal error
|
||||
* case. _diag_reset will return < 0
|
||||
*/
|
||||
for (count = 0; count < 30; count ++) {
|
||||
diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
|
||||
diag0val = CHIPREG_READ32(&iocp->chip->Diagnostic);
|
||||
if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
|
||||
break;
|
||||
}
|
||||
|
||||
dprintk((MYIOC_s_INFO_FMT "cached_fw: diag0val=%x count=%d\n",
|
||||
iocp->name, diag0val, count));
|
||||
/* wait 1 sec */
|
||||
if (sleepFlag == CAN_SLEEP) {
|
||||
msleep (1000);
|
||||
|
@ -3320,7 +3328,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
|
|||
}
|
||||
}
|
||||
if ((count = mpt_downloadboot(ioc,
|
||||
(MpiFwHeader_t *)ioc->cached_fw, sleepFlag)) < 0) {
|
||||
(MpiFwHeader_t *)iocp->cached_fw, sleepFlag)) < 0) {
|
||||
printk(KERN_WARNING MYNAM
|
||||
": firmware downloadboot failure (%d)!\n", count);
|
||||
}
|
||||
|
@ -3907,18 +3915,18 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
|
|||
|
||||
if (sleepFlag == CAN_SLEEP) {
|
||||
while (--cntdn) {
|
||||
msleep (1);
|
||||
intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
|
||||
if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
|
||||
break;
|
||||
msleep (1);
|
||||
count++;
|
||||
}
|
||||
} else {
|
||||
while (--cntdn) {
|
||||
mdelay (1);
|
||||
intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
|
||||
if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
|
||||
break;
|
||||
mdelay (1);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
@ -4883,6 +4891,7 @@ mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
|
|||
pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma);
|
||||
if (!pIoc4)
|
||||
return;
|
||||
ioc->alloc_total += iocpage4sz;
|
||||
} else {
|
||||
ioc4_dma = ioc->spi_data.IocPg4_dma;
|
||||
iocpage4sz = ioc->spi_data.IocPg4Sz;
|
||||
|
@ -4899,6 +4908,7 @@ mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
|
|||
} else {
|
||||
pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma);
|
||||
ioc->spi_data.pIocPg4 = NULL;
|
||||
ioc->alloc_total -= iocpage4sz;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5030,19 +5040,18 @@ SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
|
|||
EventAck_t *pAck;
|
||||
|
||||
if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
|
||||
printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK "
|
||||
"request frame for Event=%x EventContext=%x EventData=%x!\n",
|
||||
ioc->name, evnp->Event, le32_to_cpu(evnp->EventContext),
|
||||
le32_to_cpu(evnp->Data[0]));
|
||||
dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
|
||||
ioc->name,__FUNCTION__));
|
||||
return -1;
|
||||
}
|
||||
memset(pAck, 0, sizeof(*pAck));
|
||||
|
||||
dprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name));
|
||||
devtverboseprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name));
|
||||
|
||||
pAck->Function = MPI_FUNCTION_EVENT_ACK;
|
||||
pAck->ChainOffset = 0;
|
||||
pAck->Reserved[0] = pAck->Reserved[1] = 0;
|
||||
pAck->MsgFlags = 0;
|
||||
pAck->Reserved1[0] = pAck->Reserved1[1] = pAck->Reserved1[2] = 0;
|
||||
pAck->Event = evnp->Event;
|
||||
pAck->EventContext = evnp->EventContext;
|
||||
|
||||
|
@ -5704,9 +5713,9 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
|
|||
break;
|
||||
case MPI_EVENT_EVENT_CHANGE:
|
||||
if (evData0)
|
||||
ds = "Events(ON) Change";
|
||||
ds = "Events ON";
|
||||
else
|
||||
ds = "Events(OFF) Change";
|
||||
ds = "Events OFF";
|
||||
break;
|
||||
case MPI_EVENT_INTEGRATED_RAID:
|
||||
{
|
||||
|
@ -5777,8 +5786,27 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
|
|||
break;
|
||||
case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
|
||||
snprintf(evStr, EVENT_DESCR_STR_SZ,
|
||||
"SAS Device Status Change: No Persistancy "
|
||||
"Added: id=%d", id);
|
||||
"SAS Device Status Change: No Persistancy: id=%d", id);
|
||||
break;
|
||||
case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
|
||||
snprintf(evStr, EVENT_DESCR_STR_SZ,
|
||||
"SAS Device Status Change: Internal Device Reset : id=%d", id);
|
||||
break;
|
||||
case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
|
||||
snprintf(evStr, EVENT_DESCR_STR_SZ,
|
||||
"SAS Device Status Change: Internal Task Abort : id=%d", id);
|
||||
break;
|
||||
case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
|
||||
snprintf(evStr, EVENT_DESCR_STR_SZ,
|
||||
"SAS Device Status Change: Internal Abort Task Set : id=%d", id);
|
||||
break;
|
||||
case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
|
||||
snprintf(evStr, EVENT_DESCR_STR_SZ,
|
||||
"SAS Device Status Change: Internal Clear Task Set : id=%d", id);
|
||||
break;
|
||||
case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
|
||||
snprintf(evStr, EVENT_DESCR_STR_SZ,
|
||||
"SAS Device Status Change: Internal Query Task : id=%d", id);
|
||||
break;
|
||||
default:
|
||||
snprintf(evStr, EVENT_DESCR_STR_SZ,
|
||||
|
@ -6034,7 +6062,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
|
|||
* @ioc: Pointer to MPT_ADAPTER structure
|
||||
* @log_info: U32 LogInfo reply word from the IOC
|
||||
*
|
||||
* Refer to lsi/fc_log.h.
|
||||
* Refer to lsi/mpi_log_fc.h.
|
||||
*/
|
||||
static void
|
||||
mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
|
||||
|
@ -6131,8 +6159,10 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
|
|||
"Invalid SAS Address", /* 01h */
|
||||
NULL, /* 02h */
|
||||
"Invalid Page", /* 03h */
|
||||
NULL, /* 04h */
|
||||
"Task Terminated" /* 05h */
|
||||
"Diag Message Error", /* 04h */
|
||||
"Task Terminated", /* 05h */
|
||||
"Enclosure Management", /* 06h */
|
||||
"Target Mode" /* 07h */
|
||||
};
|
||||
static char *pl_code_str[] = {
|
||||
NULL, /* 00h */
|
||||
|
@ -6158,7 +6188,7 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
|
|||
"IO Executed", /* 14h */
|
||||
"Persistant Reservation Out Not Affiliation Owner", /* 15h */
|
||||
"Open Transmit DMA Abort", /* 16h */
|
||||
NULL, /* 17h */
|
||||
"IO Device Missing Delay Retry", /* 17h */
|
||||
NULL, /* 18h */
|
||||
NULL, /* 19h */
|
||||
NULL, /* 1Ah */
|
||||
|
@ -6238,7 +6268,7 @@ static void
|
|||
mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
|
||||
{
|
||||
u32 status = ioc_status & MPI_IOCSTATUS_MASK;
|
||||
char *desc = "";
|
||||
char *desc = NULL;
|
||||
|
||||
switch (status) {
|
||||
case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
|
||||
|
@ -6348,7 +6378,7 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
|
|||
desc = "Others";
|
||||
break;
|
||||
}
|
||||
if (desc != "")
|
||||
if (desc != NULL)
|
||||
printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc);
|
||||
}
|
||||
|
||||
|
@ -6386,7 +6416,6 @@ EXPORT_SYMBOL(mpt_alloc_fw_memory);
|
|||
EXPORT_SYMBOL(mpt_free_fw_memory);
|
||||
EXPORT_SYMBOL(mptbase_sas_persist_operation);
|
||||
|
||||
|
||||
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
||||
/*
|
||||
* fusion_init - Fusion MPT base driver initialization routine.
|
||||
|
|
|
@ -75,8 +75,8 @@
|
|||
#define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR
|
||||
#endif
|
||||
|
||||
#define MPT_LINUX_VERSION_COMMON "3.04.00"
|
||||
#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.00"
|
||||
#define MPT_LINUX_VERSION_COMMON "3.04.01"
|
||||
#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.01"
|
||||
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
|
||||
|
||||
#define show_mptmod_ver(s,ver) \
|
||||
|
@ -307,8 +307,8 @@ typedef struct _SYSIF_REGS
|
|||
u32 HostIndex; /* 50 Host Index register */
|
||||
u32 Reserved4[15]; /* 54-8F */
|
||||
u32 Fubar; /* 90 For Fubar usage */
|
||||
u32 Reserved5[1050];/* 94-10F8 */
|
||||
u32 Reset_1078; /* 10FC Reset 1078 */
|
||||
u32 Reserved5[1050];/* 94-10F8 */
|
||||
u32 Reset_1078; /* 10FC Reset 1078 */
|
||||
} SYSIF_REGS;
|
||||
|
||||
/*
|
||||
|
@ -363,6 +363,7 @@ typedef struct _VirtDevice {
|
|||
#define MPT_TARGET_FLAGS_VALID_56 0x10
|
||||
#define MPT_TARGET_FLAGS_SAF_TE_ISSUED 0x20
|
||||
#define MPT_TARGET_FLAGS_RAID_COMPONENT 0x40
|
||||
#define MPT_TARGET_FLAGS_LED_ON 0x80
|
||||
|
||||
/*
|
||||
* /proc/mpt interface
|
||||
|
@ -634,7 +635,6 @@ typedef struct _MPT_ADAPTER
|
|||
u16 handle;
|
||||
int sas_index; /* index refrencing */
|
||||
MPT_SAS_MGMT sas_mgmt;
|
||||
int num_ports;
|
||||
struct work_struct sas_persist_task;
|
||||
|
||||
struct work_struct fc_setup_reset_work;
|
||||
|
@ -644,7 +644,6 @@ typedef struct _MPT_ADAPTER
|
|||
struct work_struct fc_rescan_work;
|
||||
char fc_rescan_work_q_name[KOBJ_NAME_LEN];
|
||||
struct workqueue_struct *fc_rescan_work_q;
|
||||
u8 port_serial_number;
|
||||
} MPT_ADAPTER;
|
||||
|
||||
/*
|
||||
|
@ -982,7 +981,7 @@ typedef struct _MPT_SCSI_HOST {
|
|||
wait_queue_head_t scandv_waitq;
|
||||
int scandv_wait_done;
|
||||
long last_queue_full;
|
||||
u8 mpt_pq_filter;
|
||||
u16 tm_iocstatus;
|
||||
} MPT_SCSI_HOST;
|
||||
|
||||
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
||||
|
|
|
@ -2332,7 +2332,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
|
|||
}
|
||||
|
||||
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
||||
/* Prototype Routine for the HP HOST INFO command.
|
||||
/* Prototype Routine for the HOST INFO command.
|
||||
*
|
||||
* Outputs: None.
|
||||
* Return: 0 if successful
|
||||
|
@ -2568,7 +2568,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
|
|||
}
|
||||
|
||||
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
||||
/* Prototype Routine for the HP TARGET INFO command.
|
||||
/* Prototype Routine for the TARGET INFO command.
|
||||
*
|
||||
* Outputs: None.
|
||||
* Return: 0 if successful
|
||||
|
|
|
@ -354,9 +354,6 @@ struct mpt_ioctl_command32 {
|
|||
|
||||
|
||||
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
||||
/*
|
||||
* HP Specific IOCTL Defines and Structures
|
||||
*/
|
||||
|
||||
#define CPQFCTS_IOC_MAGIC 'Z'
|
||||
#define HP_IOC_MAGIC 'Z'
|
||||
|
@ -364,8 +361,6 @@ struct mpt_ioctl_command32 {
|
|||
#define HP_GETHOSTINFO1 _IOR(HP_IOC_MAGIC, 20, hp_host_info_rev0_t)
|
||||
#define HP_GETTARGETINFO _IOR(HP_IOC_MAGIC, 21, hp_target_info_t)
|
||||
|
||||
/* All HP IOCTLs must include this header
|
||||
*/
|
||||
typedef struct _hp_header {
|
||||
unsigned int iocnum;
|
||||
unsigned int host;
|
||||
|
|
|
@ -77,10 +77,6 @@ MODULE_DESCRIPTION(my_NAME);
|
|||
MODULE_LICENSE("GPL");
|
||||
|
||||
/* Command line args */
|
||||
static int mpt_pq_filter = 0;
|
||||
module_param(mpt_pq_filter, int, 0);
|
||||
MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)");
|
||||
|
||||
#define MPTFC_DEV_LOSS_TMO (60)
|
||||
static int mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO; /* reasonable default */
|
||||
module_param(mptfc_dev_loss_tmo, int, 0);
|
||||
|
@ -513,8 +509,7 @@ mptfc_slave_alloc(struct scsi_device *sdev)
|
|||
|
||||
if (vtarget->num_luns == 0) {
|
||||
vtarget->ioc_id = hd->ioc->id;
|
||||
vtarget->tflags = MPT_TARGET_FLAGS_Q_YES |
|
||||
MPT_TARGET_FLAGS_VALID_INQUIRY;
|
||||
vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
|
||||
hd->Targets[sdev->id] = vtarget;
|
||||
}
|
||||
|
||||
|
@ -1129,13 +1124,6 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
hd->timer.data = (unsigned long) hd;
|
||||
hd->timer.function = mptscsih_timer_expired;
|
||||
|
||||
hd->mpt_pq_filter = mpt_pq_filter;
|
||||
|
||||
ddvprintk((MYIOC_s_INFO_FMT
|
||||
"mpt_pq_filter %x\n",
|
||||
ioc->name,
|
||||
mpt_pq_filter));
|
||||
|
||||
init_waitqueue_head(&hd->scandv_waitq);
|
||||
hd->scandv_wait_done = 0;
|
||||
hd->last_queue_full = 0;
|
||||
|
|
|
@ -67,20 +67,19 @@
|
|||
#define my_VERSION MPT_LINUX_VERSION_COMMON
|
||||
#define MYNAM "mptsas"
|
||||
|
||||
/*
|
||||
* Reserved channel for integrated raid
|
||||
*/
|
||||
#define MPTSAS_RAID_CHANNEL 1
|
||||
|
||||
MODULE_AUTHOR(MODULEAUTHOR);
|
||||
MODULE_DESCRIPTION(my_NAME);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static int mpt_pq_filter;
|
||||
module_param(mpt_pq_filter, int, 0);
|
||||
MODULE_PARM_DESC(mpt_pq_filter,
|
||||
"Enable peripheral qualifier filter: enable=1 "
|
||||
"(default=0)");
|
||||
|
||||
static int mpt_pt_clear;
|
||||
module_param(mpt_pt_clear, int, 0);
|
||||
MODULE_PARM_DESC(mpt_pt_clear,
|
||||
"Clear persistency table: enable=1 "
|
||||
" Clear persistency table: enable=1 "
|
||||
"(default=MPTSCSIH_PT_CLEAR=0)");
|
||||
|
||||
static int mptsasDoneCtx = -1;
|
||||
|
@ -144,7 +143,6 @@ struct mptsas_devinfo {
|
|||
* Specific details on ports, wide/narrow
|
||||
*/
|
||||
struct mptsas_portinfo_details{
|
||||
u8 port_id; /* port number provided to transport */
|
||||
u16 num_phys; /* number of phys belong to this port */
|
||||
u64 phy_bitmask; /* TODO, extend support for 255 phys */
|
||||
struct sas_rphy *rphy; /* transport layer rphy object */
|
||||
|
@ -350,10 +348,10 @@ mptsas_port_delete(struct mptsas_portinfo_details * port_details)
|
|||
port_info = port_details->port_info;
|
||||
phy_info = port_info->phy_info;
|
||||
|
||||
dsaswideprintk((KERN_DEBUG "%s: [%p]: port=%02d num_phys=%02d "
|
||||
dsaswideprintk((KERN_DEBUG "%s: [%p]: num_phys=%02d "
|
||||
"bitmask=0x%016llX\n",
|
||||
__FUNCTION__, port_details, port_details->port_id,
|
||||
port_details->num_phys, port_details->phy_bitmask));
|
||||
__FUNCTION__, port_details, port_details->num_phys,
|
||||
port_details->phy_bitmask));
|
||||
|
||||
for (i = 0; i < port_info->num_phys; i++, phy_info++) {
|
||||
if(phy_info->port_details != port_details)
|
||||
|
@ -462,9 +460,8 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
|
|||
* phy be removed by firmware events.
|
||||
*/
|
||||
dsaswideprintk((KERN_DEBUG
|
||||
"%s: [%p]: port=%d deleting phy = %d\n",
|
||||
__FUNCTION__, port_details,
|
||||
port_details->port_id, i));
|
||||
"%s: [%p]: deleting phy = %d\n",
|
||||
__FUNCTION__, port_details, i));
|
||||
port_details->num_phys--;
|
||||
port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
|
||||
memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
|
||||
|
@ -493,7 +490,6 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
|
|||
goto out;
|
||||
port_details->num_phys = 1;
|
||||
port_details->port_info = port_info;
|
||||
port_details->port_id = ioc->port_serial_number++;
|
||||
if (phy_info->phy_id < 64 )
|
||||
port_details->phy_bitmask |=
|
||||
(1 << phy_info->phy_id);
|
||||
|
@ -525,12 +521,8 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
|
|||
mptsas_get_port(phy_info_cmp);
|
||||
port_details->starget =
|
||||
mptsas_get_starget(phy_info_cmp);
|
||||
port_details->port_id =
|
||||
phy_info_cmp->port_details->port_id;
|
||||
port_details->num_phys =
|
||||
phy_info_cmp->port_details->num_phys;
|
||||
// port_info->port_serial_number--;
|
||||
ioc->port_serial_number--;
|
||||
if (!phy_info_cmp->port_details->num_phys)
|
||||
kfree(phy_info_cmp->port_details);
|
||||
} else
|
||||
|
@ -554,11 +546,11 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
|
|||
if (!port_details)
|
||||
continue;
|
||||
dsaswideprintk((KERN_DEBUG
|
||||
"%s: [%p]: phy_id=%02d port_id=%02d num_phys=%02d "
|
||||
"%s: [%p]: phy_id=%02d num_phys=%02d "
|
||||
"bitmask=0x%016llX\n",
|
||||
__FUNCTION__,
|
||||
port_details, i, port_details->port_id,
|
||||
port_details->num_phys, port_details->phy_bitmask));
|
||||
port_details, i, port_details->num_phys,
|
||||
port_details->phy_bitmask));
|
||||
dsaswideprintk((KERN_DEBUG"\t\tport = %p rphy=%p\n",
|
||||
port_details->port, port_details->rphy));
|
||||
}
|
||||
|
@ -651,16 +643,13 @@ mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
|
|||
static int
|
||||
mptsas_slave_configure(struct scsi_device *sdev)
|
||||
{
|
||||
struct Scsi_Host *host = sdev->host;
|
||||
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
|
||||
|
||||
/*
|
||||
* RAID volumes placed beyond the last expected port.
|
||||
* Ignore sending sas mode pages in that case..
|
||||
*/
|
||||
if (sdev->channel < hd->ioc->num_ports)
|
||||
sas_read_port_mode_page(sdev);
|
||||
if (sdev->channel == MPTSAS_RAID_CHANNEL)
|
||||
goto out;
|
||||
|
||||
sas_read_port_mode_page(sdev);
|
||||
|
||||
out:
|
||||
return mptscsih_slave_configure(sdev);
|
||||
}
|
||||
|
||||
|
@ -689,10 +678,7 @@ mptsas_target_alloc(struct scsi_target *starget)
|
|||
|
||||
hd->Targets[target_id] = vtarget;
|
||||
|
||||
/*
|
||||
* RAID volumes placed beyond the last expected port.
|
||||
*/
|
||||
if (starget->channel == hd->ioc->num_ports)
|
||||
if (starget->channel == MPTSAS_RAID_CHANNEL)
|
||||
goto out;
|
||||
|
||||
rphy = dev_to_rphy(starget->dev.parent);
|
||||
|
@ -743,7 +729,7 @@ mptsas_target_destroy(struct scsi_target *starget)
|
|||
if (!starget->hostdata)
|
||||
return;
|
||||
|
||||
if (starget->channel == hd->ioc->num_ports)
|
||||
if (starget->channel == MPTSAS_RAID_CHANNEL)
|
||||
goto out;
|
||||
|
||||
rphy = dev_to_rphy(starget->dev.parent);
|
||||
|
@ -783,10 +769,7 @@ mptsas_slave_alloc(struct scsi_device *sdev)
|
|||
starget = scsi_target(sdev);
|
||||
vdev->vtarget = starget->hostdata;
|
||||
|
||||
/*
|
||||
* RAID volumes placed beyond the last expected port.
|
||||
*/
|
||||
if (sdev->channel == hd->ioc->num_ports)
|
||||
if (sdev->channel == MPTSAS_RAID_CHANNEL)
|
||||
goto out;
|
||||
|
||||
rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
|
||||
|
@ -1608,11 +1591,7 @@ static int mptsas_probe_one_phy(struct device *dev,
|
|||
if (phy_info->sas_port_add_phy) {
|
||||
|
||||
if (!port) {
|
||||
port = sas_port_alloc(dev,
|
||||
phy_info->port_details->port_id);
|
||||
dsaswideprintk((KERN_DEBUG
|
||||
"sas_port_alloc: port=%p dev=%p port_id=%d\n",
|
||||
port, dev, phy_info->port_details->port_id));
|
||||
port = sas_port_alloc_num(dev);
|
||||
if (!port) {
|
||||
error = -ENOMEM;
|
||||
goto out;
|
||||
|
@ -1625,6 +1604,9 @@ static int mptsas_probe_one_phy(struct device *dev,
|
|||
goto out;
|
||||
}
|
||||
mptsas_set_port(phy_info, port);
|
||||
dsaswideprintk((KERN_DEBUG
|
||||
"sas_port_alloc: port=%p dev=%p port_id=%d\n",
|
||||
port, dev, port->port_identifier));
|
||||
}
|
||||
dsaswideprintk((KERN_DEBUG "sas_port_add_phy: phy_id=%d\n",
|
||||
phy_info->phy_id));
|
||||
|
@ -1736,7 +1718,6 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
|
|||
hba = NULL;
|
||||
}
|
||||
mutex_unlock(&ioc->sas_topology_mutex);
|
||||
ioc->num_ports = port_info->num_phys;
|
||||
|
||||
for (i = 0; i < port_info->num_phys; i++) {
|
||||
mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
|
||||
|
@ -1939,7 +1920,8 @@ mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
|
|||
expander_sas_address)
|
||||
continue;
|
||||
#ifdef MPT_DEBUG_SAS_WIDE
|
||||
dev_printk(KERN_DEBUG, &port->dev, "delete\n");
|
||||
dev_printk(KERN_DEBUG, &port->dev,
|
||||
"delete port (%d)\n", port->port_identifier);
|
||||
#endif
|
||||
sas_port_delete(port);
|
||||
mptsas_port_delete(phy_info->port_details);
|
||||
|
@ -1984,7 +1966,7 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
|
|||
if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
|
||||
goto out;
|
||||
for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
|
||||
scsi_add_device(ioc->sh, ioc->num_ports,
|
||||
scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
|
||||
ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
|
||||
}
|
||||
out:
|
||||
|
@ -2185,7 +2167,8 @@ mptsas_hotplug_work(void *arg)
|
|||
ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
|
||||
|
||||
#ifdef MPT_DEBUG_SAS_WIDE
|
||||
dev_printk(KERN_DEBUG, &port->dev, "delete\n");
|
||||
dev_printk(KERN_DEBUG, &port->dev,
|
||||
"delete port (%d)\n", port->port_identifier);
|
||||
#endif
|
||||
sas_port_delete(port);
|
||||
mptsas_port_delete(phy_info->port_details);
|
||||
|
@ -2289,35 +2272,26 @@ mptsas_hotplug_work(void *arg)
|
|||
mptsas_set_rphy(phy_info, rphy);
|
||||
break;
|
||||
case MPTSAS_ADD_RAID:
|
||||
sdev = scsi_device_lookup(
|
||||
ioc->sh,
|
||||
ioc->num_ports,
|
||||
ev->id,
|
||||
0);
|
||||
sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
|
||||
ev->id, 0);
|
||||
if (sdev) {
|
||||
scsi_device_put(sdev);
|
||||
break;
|
||||
}
|
||||
printk(MYIOC_s_INFO_FMT
|
||||
"attaching raid volume, channel %d, id %d\n",
|
||||
ioc->name, ioc->num_ports, ev->id);
|
||||
scsi_add_device(ioc->sh,
|
||||
ioc->num_ports,
|
||||
ev->id,
|
||||
0);
|
||||
ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
|
||||
scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, ev->id, 0);
|
||||
mpt_findImVolumes(ioc);
|
||||
break;
|
||||
case MPTSAS_DEL_RAID:
|
||||
sdev = scsi_device_lookup(
|
||||
ioc->sh,
|
||||
ioc->num_ports,
|
||||
ev->id,
|
||||
0);
|
||||
sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
|
||||
ev->id, 0);
|
||||
if (!sdev)
|
||||
break;
|
||||
printk(MYIOC_s_INFO_FMT
|
||||
"removing raid volume, channel %d, id %d\n",
|
||||
ioc->name, ioc->num_ports, ev->id);
|
||||
ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
|
||||
vdevice = sdev->hostdata;
|
||||
vdevice->vtarget->deleted = 1;
|
||||
mptsas_target_reset(ioc, vdevice->vtarget);
|
||||
|
@ -2723,7 +2697,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
hd->timer.data = (unsigned long) hd;
|
||||
hd->timer.function = mptscsih_timer_expired;
|
||||
|
||||
hd->mpt_pq_filter = mpt_pq_filter;
|
||||
ioc->sas_data.ptClear = mpt_pt_clear;
|
||||
|
||||
if (ioc->sas_data.ptClear==1) {
|
||||
|
@ -2731,12 +2704,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
|
||||
}
|
||||
|
||||
ddvprintk((MYIOC_s_INFO_FMT
|
||||
"mpt_pq_filter %x mpt_pq_filter %x\n",
|
||||
ioc->name,
|
||||
mpt_pq_filter,
|
||||
mpt_pq_filter));
|
||||
|
||||
init_waitqueue_head(&hd->scandv_waitq);
|
||||
hd->scandv_wait_done = 0;
|
||||
hd->last_queue_full = 0;
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
|
||||
#include "mptbase.h"
|
||||
#include "mptscsih.h"
|
||||
#include "lsi/mpi_log_sas.h"
|
||||
|
||||
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
||||
#define my_NAME "Fusion MPT SCSI Host driver"
|
||||
|
@ -127,7 +128,7 @@ static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
|
|||
static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
|
||||
static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
|
||||
static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
|
||||
static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
|
||||
static int SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
|
||||
|
||||
static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
|
||||
|
||||
|
@ -497,6 +498,34 @@ mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
|
|||
return SUCCESS;
|
||||
} /* mptscsih_AddSGE() */
|
||||
|
||||
static void
|
||||
mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget,
|
||||
U32 SlotStatus)
|
||||
{
|
||||
MPT_FRAME_HDR *mf;
|
||||
SEPRequest_t *SEPMsg;
|
||||
|
||||
if (ioc->bus_type == FC)
|
||||
return;
|
||||
|
||||
if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
|
||||
dfailprintk((MYIOC_s_WARN_FMT "%s: no msg frames!!\n",
|
||||
ioc->name,__FUNCTION__));
|
||||
return;
|
||||
}
|
||||
|
||||
SEPMsg = (SEPRequest_t *)mf;
|
||||
SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
|
||||
SEPMsg->Bus = vtarget->bus_id;
|
||||
SEPMsg->TargetID = vtarget->target_id;
|
||||
SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS;
|
||||
SEPMsg->SlotStatus = SlotStatus;
|
||||
devtverboseprintk((MYIOC_s_WARN_FMT
|
||||
"Sending SEP cmd=%x id=%d bus=%d\n",
|
||||
ioc->name, SlotStatus, SEPMsg->TargetID, SEPMsg->Bus));
|
||||
mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
|
||||
}
|
||||
|
||||
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
||||
/*
|
||||
* mptscsih_io_done - Main SCSI IO callback routine registered to
|
||||
|
@ -520,6 +549,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
|
|||
SCSIIORequest_t *pScsiReq;
|
||||
SCSIIOReply_t *pScsiReply;
|
||||
u16 req_idx, req_idx_MR;
|
||||
VirtDevice *vdev;
|
||||
VirtTarget *vtarget;
|
||||
|
||||
hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
|
||||
|
||||
|
@ -538,6 +569,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
|
|||
}
|
||||
|
||||
sc = hd->ScsiLookup[req_idx];
|
||||
hd->ScsiLookup[req_idx] = NULL;
|
||||
if (sc == NULL) {
|
||||
MPIHeader_t *hdr = (MPIHeader_t *)mf;
|
||||
|
||||
|
@ -553,6 +585,12 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if ((unsigned char *)mf != sc->host_scribble) {
|
||||
mptscsih_freeChainBuffers(ioc, req_idx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
sc->host_scribble = NULL;
|
||||
sc->result = DID_OK << 16; /* Set default reply as OK */
|
||||
pScsiReq = (SCSIIORequest_t *) mf;
|
||||
pScsiReply = (SCSIIOReply_t *) mr;
|
||||
|
@ -640,10 +678,36 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
|
|||
|
||||
if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
|
||||
hd->sel_timeout[pScsiReq->TargetID]++;
|
||||
|
||||
vdev = sc->device->hostdata;
|
||||
if (!vdev)
|
||||
break;
|
||||
vtarget = vdev->vtarget;
|
||||
if (vtarget->tflags & MPT_TARGET_FLAGS_LED_ON) {
|
||||
mptscsih_issue_sep_command(ioc, vtarget,
|
||||
MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED);
|
||||
vtarget->tflags &= ~MPT_TARGET_FLAGS_LED_ON;
|
||||
}
|
||||
break;
|
||||
|
||||
case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
|
||||
case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
|
||||
if ( ioc->bus_type == SAS ) {
|
||||
u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus);
|
||||
if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
|
||||
u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
|
||||
log_info &=SAS_LOGINFO_MASK;
|
||||
if (log_info == SAS_LOGINFO_NEXUS_LOSS) {
|
||||
sc->result = (DID_BUS_BUSY << 16);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Allow non-SAS & non-NEXUS_LOSS to drop into below code
|
||||
*/
|
||||
|
||||
case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
|
||||
case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
|
||||
/* Linux handles an unsolicited DID_RESET better
|
||||
* than an unsolicited DID_ABORT.
|
||||
|
@ -658,7 +722,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
|
|||
sc->result=DID_SOFT_ERROR << 16;
|
||||
else /* Sufficient data transfer occurred */
|
||||
sc->result = (DID_OK << 16) | scsi_status;
|
||||
dreplyprintk((KERN_NOTICE
|
||||
dreplyprintk((KERN_NOTICE
|
||||
"RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id));
|
||||
break;
|
||||
|
||||
|
@ -784,8 +848,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
|
|||
sc->request_bufflen, sc->sc_data_direction);
|
||||
}
|
||||
|
||||
hd->ScsiLookup[req_idx] = NULL;
|
||||
|
||||
sc->scsi_done(sc); /* Issue the command callback */
|
||||
|
||||
/* Free Chain buffers */
|
||||
|
@ -827,9 +889,17 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
|
|||
dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
|
||||
mf, SCpnt));
|
||||
|
||||
/* Free Chain buffers */
|
||||
mptscsih_freeChainBuffers(ioc, ii);
|
||||
|
||||
/* Free Message frames */
|
||||
mpt_free_msg_frame(ioc, mf);
|
||||
|
||||
if ((unsigned char *)mf != SCpnt->host_scribble)
|
||||
continue;
|
||||
|
||||
/* Set status, free OS resources (SG DMA buffers)
|
||||
* Do OS callback
|
||||
* Free driver resources (chain, msg buffers)
|
||||
*/
|
||||
if (SCpnt->use_sg) {
|
||||
pci_unmap_sg(ioc->pcidev,
|
||||
|
@ -845,12 +915,6 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
|
|||
SCpnt->result = DID_RESET << 16;
|
||||
SCpnt->host_scribble = NULL;
|
||||
|
||||
/* Free Chain buffers */
|
||||
mptscsih_freeChainBuffers(ioc, ii);
|
||||
|
||||
/* Free Message frames */
|
||||
mpt_free_msg_frame(ioc, mf);
|
||||
|
||||
SCpnt->scsi_done(SCpnt); /* Issue the command callback */
|
||||
}
|
||||
}
|
||||
|
@ -887,10 +951,10 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
|
|||
if ((sc = hd->ScsiLookup[ii]) != NULL) {
|
||||
|
||||
mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
|
||||
|
||||
if (mf == NULL)
|
||||
continue;
|
||||
dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
|
||||
hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
|
||||
|
||||
if ((mf->TargetID != ((u8)vdevice->vtarget->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun)))
|
||||
continue;
|
||||
|
||||
|
@ -899,6 +963,8 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
|
|||
hd->ScsiLookup[ii] = NULL;
|
||||
mptscsih_freeChainBuffers(hd->ioc, ii);
|
||||
mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
|
||||
if ((unsigned char *)mf != sc->host_scribble)
|
||||
continue;
|
||||
if (sc->use_sg) {
|
||||
pci_unmap_sg(hd->ioc->pcidev,
|
||||
(struct scatterlist *) sc->request_buffer,
|
||||
|
@ -1341,8 +1407,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
|
|||
goto fail;
|
||||
}
|
||||
|
||||
SCpnt->host_scribble = (unsigned char *)mf;
|
||||
hd->ScsiLookup[my_idx] = SCpnt;
|
||||
SCpnt->host_scribble = NULL;
|
||||
|
||||
mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
|
||||
dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
|
||||
|
@ -1529,6 +1595,12 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
|
|||
rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check IOCStatus from TM reply message
|
||||
*/
|
||||
if (hd->tm_iocstatus != MPI_IOCSTATUS_SUCCESS)
|
||||
rc = FAILED;
|
||||
|
||||
dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
|
||||
|
||||
return rc;
|
||||
|
@ -1654,6 +1726,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
|
|||
int scpnt_idx;
|
||||
int retval;
|
||||
VirtDevice *vdev;
|
||||
ulong sn = SCpnt->serial_number;
|
||||
|
||||
/* If we can't locate our host adapter structure, return FAILED status.
|
||||
*/
|
||||
|
@ -1707,6 +1780,11 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
|
|||
vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun,
|
||||
ctx2abort, mptscsih_get_tm_timeout(hd->ioc));
|
||||
|
||||
if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
|
||||
SCpnt->serial_number == sn) {
|
||||
retval = FAILED;
|
||||
}
|
||||
|
||||
printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
|
||||
hd->ioc->name,
|
||||
((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
|
||||
|
@ -2023,6 +2101,7 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
|
|||
DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
|
||||
|
||||
iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
|
||||
hd->tm_iocstatus = iocstatus;
|
||||
dtmprintk((MYIOC_s_WARN_FMT " SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",
|
||||
ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo)));
|
||||
/* Error? (anything non-zero?) */
|
||||
|
@ -2401,6 +2480,13 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR
|
|||
ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
|
||||
|
||||
ioc->eventContext++;
|
||||
if (hd->ioc->pcidev->vendor ==
|
||||
PCI_VENDOR_ID_IBM) {
|
||||
mptscsih_issue_sep_command(hd->ioc,
|
||||
vdev->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
|
||||
vdev->vtarget->tflags |=
|
||||
MPT_TARGET_FLAGS_LED_ON;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -2409,7 +2495,7 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR
|
|||
}
|
||||
}
|
||||
|
||||
static u32
|
||||
static int
|
||||
SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
|
||||
{
|
||||
MPT_SCSI_HOST *hd;
|
||||
|
|
|
@ -83,10 +83,6 @@ static int mpt_saf_te = MPTSCSIH_SAF_TE;
|
|||
module_param(mpt_saf_te, int, 0);
|
||||
MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1 (default=MPTSCSIH_SAF_TE=0)");
|
||||
|
||||
static int mpt_pq_filter = 0;
|
||||
module_param(mpt_pq_filter, int, 0);
|
||||
MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)");
|
||||
|
||||
static void mptspi_write_offset(struct scsi_target *, int);
|
||||
static void mptspi_write_width(struct scsi_target *, int);
|
||||
static int mptspi_write_spi_device_pg1(struct scsi_target *,
|
||||
|
@ -1047,14 +1043,12 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
hd->timer.function = mptscsih_timer_expired;
|
||||
|
||||
ioc->spi_data.Saf_Te = mpt_saf_te;
|
||||
hd->mpt_pq_filter = mpt_pq_filter;
|
||||
|
||||
hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
|
||||
ddvprintk((MYIOC_s_INFO_FMT
|
||||
"saf_te %x mpt_pq_filter %x\n",
|
||||
"saf_te %x\n",
|
||||
ioc->name,
|
||||
mpt_saf_te,
|
||||
mpt_pq_filter));
|
||||
mpt_saf_te));
|
||||
ioc->spi_data.noQas = 0;
|
||||
|
||||
init_waitqueue_head(&hd->scandv_waitq);
|
||||
|
|
|
@ -132,6 +132,7 @@ static int __init dummy_init_module(void)
|
|||
for (i = 0; i < numdummies && !err; i++)
|
||||
err = dummy_init_one(i);
|
||||
if (err) {
|
||||
i--;
|
||||
while (--i >= 0)
|
||||
dummy_free_one(i);
|
||||
}
|
||||
|
|
|
@ -110,6 +110,9 @@ struct e1000_adapter;
|
|||
#define E1000_MIN_RXD 80
|
||||
#define E1000_MAX_82544_RXD 4096
|
||||
|
||||
/* this is the size past which hardware will drop packets when setting LPE=0 */
|
||||
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
|
||||
|
||||
/* Supported Rx Buffer Sizes */
|
||||
#define E1000_RXBUFFER_128 128 /* Used for packet split */
|
||||
#define E1000_RXBUFFER_256 256 /* Used for packet split */
|
||||
|
|
|
@ -36,7 +36,7 @@ static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
|
|||
#else
|
||||
#define DRIVERNAPI "-NAPI"
|
||||
#endif
|
||||
#define DRV_VERSION "7.1.9-k2"DRIVERNAPI
|
||||
#define DRV_VERSION "7.1.9-k4"DRIVERNAPI
|
||||
char e1000_driver_version[] = DRV_VERSION;
|
||||
static char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
|
||||
|
||||
|
@ -1068,7 +1068,7 @@ e1000_sw_init(struct e1000_adapter *adapter)
|
|||
|
||||
pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
|
||||
|
||||
adapter->rx_buffer_len = MAXIMUM_ETHERNET_FRAME_SIZE;
|
||||
adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
|
||||
adapter->rx_ps_bsize0 = E1000_RXBUFFER_128;
|
||||
hw->max_frame_size = netdev->mtu +
|
||||
ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
|
||||
|
@ -3148,7 +3148,6 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
|
|||
adapter->rx_buffer_len = E1000_RXBUFFER_16384;
|
||||
|
||||
/* adjust allocation if LPE protects us, and we aren't using SBP */
|
||||
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
|
||||
if (!adapter->hw.tbi_compatibility_on &&
|
||||
((max_frame == MAXIMUM_ETHERNET_FRAME_SIZE) ||
|
||||
(max_frame == MAXIMUM_ETHERNET_VLAN_SIZE)))
|
||||
|
@ -3387,8 +3386,8 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
|
|||
E1000_WRITE_REG(hw, IMC, ~0);
|
||||
E1000_WRITE_FLUSH(hw);
|
||||
}
|
||||
if (likely(netif_rx_schedule_prep(&adapter->polling_netdev[0])))
|
||||
__netif_rx_schedule(&adapter->polling_netdev[0]);
|
||||
if (likely(netif_rx_schedule_prep(netdev)))
|
||||
__netif_rx_schedule(netdev);
|
||||
else
|
||||
e1000_irq_enable(adapter);
|
||||
#else
|
||||
|
@ -3431,34 +3430,26 @@ e1000_clean(struct net_device *poll_dev, int *budget)
|
|||
{
|
||||
struct e1000_adapter *adapter;
|
||||
int work_to_do = min(*budget, poll_dev->quota);
|
||||
int tx_cleaned = 0, i = 0, work_done = 0;
|
||||
int tx_cleaned = 0, work_done = 0;
|
||||
|
||||
/* Must NOT use netdev_priv macro here. */
|
||||
adapter = poll_dev->priv;
|
||||
|
||||
/* Keep link state information with original netdev */
|
||||
if (!netif_carrier_ok(adapter->netdev))
|
||||
if (!netif_carrier_ok(poll_dev))
|
||||
goto quit_polling;
|
||||
|
||||
while (poll_dev != &adapter->polling_netdev[i]) {
|
||||
i++;
|
||||
BUG_ON(i == adapter->num_rx_queues);
|
||||
/* e1000_clean is called per-cpu. This lock protects
|
||||
* tx_ring[0] from being cleaned by multiple cpus
|
||||
* simultaneously. A failure obtaining the lock means
|
||||
* tx_ring[0] is currently being cleaned anyway. */
|
||||
if (spin_trylock(&adapter->tx_queue_lock)) {
|
||||
tx_cleaned = e1000_clean_tx_irq(adapter,
|
||||
&adapter->tx_ring[0]);
|
||||
spin_unlock(&adapter->tx_queue_lock);
|
||||
}
|
||||
|
||||
if (likely(adapter->num_tx_queues == 1)) {
|
||||
/* e1000_clean is called per-cpu. This lock protects
|
||||
* tx_ring[0] from being cleaned by multiple cpus
|
||||
* simultaneously. A failure obtaining the lock means
|
||||
* tx_ring[0] is currently being cleaned anyway. */
|
||||
if (spin_trylock(&adapter->tx_queue_lock)) {
|
||||
tx_cleaned = e1000_clean_tx_irq(adapter,
|
||||
&adapter->tx_ring[0]);
|
||||
spin_unlock(&adapter->tx_queue_lock);
|
||||
}
|
||||
} else
|
||||
tx_cleaned = e1000_clean_tx_irq(adapter, &adapter->tx_ring[i]);
|
||||
|
||||
adapter->clean_rx(adapter, &adapter->rx_ring[i],
|
||||
adapter->clean_rx(adapter, &adapter->rx_ring[0],
|
||||
&work_done, work_to_do);
|
||||
|
||||
*budget -= work_done;
|
||||
|
@ -3466,7 +3457,7 @@ e1000_clean(struct net_device *poll_dev, int *budget)
|
|||
|
||||
/* If no Tx and not enough Rx work done, exit the polling mode */
|
||||
if ((!tx_cleaned && (work_done == 0)) ||
|
||||
!netif_running(adapter->netdev)) {
|
||||
!netif_running(poll_dev)) {
|
||||
quit_polling:
|
||||
netif_rx_complete(poll_dev);
|
||||
e1000_irq_enable(adapter);
|
||||
|
@ -3681,6 +3672,9 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
|
|||
|
||||
length = le16_to_cpu(rx_desc->length);
|
||||
|
||||
/* adjust length to remove Ethernet CRC */
|
||||
length -= 4;
|
||||
|
||||
if (unlikely(!(status & E1000_RXD_STAT_EOP))) {
|
||||
/* All receives must fit into a single buffer */
|
||||
E1000_DBG("%s: Receive packet consumed multiple"
|
||||
|
@ -3885,8 +3879,9 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
|
|||
pci_dma_sync_single_for_device(pdev,
|
||||
ps_page_dma->ps_page_dma[0],
|
||||
PAGE_SIZE, PCI_DMA_FROMDEVICE);
|
||||
/* remove the CRC */
|
||||
l1 -= 4;
|
||||
skb_put(skb, l1);
|
||||
length += l1;
|
||||
goto copydone;
|
||||
} /* if */
|
||||
}
|
||||
|
@ -3905,6 +3900,10 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
|
|||
skb->truesize += length;
|
||||
}
|
||||
|
||||
/* strip the ethernet crc, problem is we're using pages now so
|
||||
* this whole operation can get a little cpu intensive */
|
||||
pskb_trim(skb, skb->len - 4);
|
||||
|
||||
copydone:
|
||||
e1000_rx_checksum(adapter, staterr,
|
||||
le16_to_cpu(rx_desc->wb.lower.hi_dword.csum_ip.csum), skb);
|
||||
|
@ -4752,6 +4751,7 @@ static void
|
|||
e1000_netpoll(struct net_device *netdev)
|
||||
{
|
||||
struct e1000_adapter *adapter = netdev_priv(netdev);
|
||||
|
||||
disable_irq(adapter->pdev->irq);
|
||||
e1000_intr(adapter->pdev->irq, netdev, NULL);
|
||||
e1000_clean_tx_irq(adapter, adapter->tx_ring);
|
||||
|
|
|
@ -271,6 +271,7 @@ static int __init ifb_init_module(void)
|
|||
for (i = 0; i < numifbs && !err; i++)
|
||||
err = ifb_init_one(i);
|
||||
if (err) {
|
||||
i--;
|
||||
while (--i >= 0)
|
||||
ifb_free_one(i);
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
#include "sky2.h"
|
||||
|
||||
#define DRV_NAME "sky2"
|
||||
#define DRV_VERSION "1.4"
|
||||
#define DRV_VERSION "1.5"
|
||||
#define PFX DRV_NAME " "
|
||||
|
||||
/*
|
||||
|
@ -2204,9 +2204,6 @@ static int sky2_poll(struct net_device *dev0, int *budget)
|
|||
int work_done = 0;
|
||||
u32 status = sky2_read32(hw, B0_Y2_SP_EISR);
|
||||
|
||||
if (!~status)
|
||||
goto out;
|
||||
|
||||
if (status & Y2_IS_HW_ERR)
|
||||
sky2_hw_intr(hw);
|
||||
|
||||
|
@ -2243,7 +2240,7 @@ static int sky2_poll(struct net_device *dev0, int *budget)
|
|||
|
||||
if (sky2_more_work(hw))
|
||||
return 1;
|
||||
out:
|
||||
|
||||
netif_rx_complete(dev0);
|
||||
|
||||
sky2_read32(hw, B0_Y2_SP_LISR);
|
||||
|
|
|
@ -84,7 +84,7 @@ MODULE_DEVICE_TABLE(pci, spider_net_pci_tbl);
|
|||
*
|
||||
* returns the content of the specified SMMIO register.
|
||||
*/
|
||||
static u32
|
||||
static inline u32
|
||||
spider_net_read_reg(struct spider_net_card *card, u32 reg)
|
||||
{
|
||||
u32 value;
|
||||
|
@ -101,7 +101,7 @@ spider_net_read_reg(struct spider_net_card *card, u32 reg)
|
|||
* @reg: register to write to
|
||||
* @value: value to write into the specified SMMIO register
|
||||
*/
|
||||
static void
|
||||
static inline void
|
||||
spider_net_write_reg(struct spider_net_card *card, u32 reg, u32 value)
|
||||
{
|
||||
value = cpu_to_le32(value);
|
||||
|
@ -259,39 +259,10 @@ spider_net_get_mac_address(struct net_device *netdev)
|
|||
*
|
||||
* returns the status as in the dmac_cmd_status field of the descriptor
|
||||
*/
|
||||
static enum spider_net_descr_status
|
||||
static inline int
|
||||
spider_net_get_descr_status(struct spider_net_descr *descr)
|
||||
{
|
||||
u32 cmd_status;
|
||||
|
||||
cmd_status = descr->dmac_cmd_status;
|
||||
cmd_status >>= SPIDER_NET_DESCR_IND_PROC_SHIFT;
|
||||
/* no need to mask out any bits, as cmd_status is 32 bits wide only
|
||||
* (and unsigned) */
|
||||
return cmd_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* spider_net_set_descr_status -- sets the status of a descriptor
|
||||
* @descr: descriptor to change
|
||||
* @status: status to set in the descriptor
|
||||
*
|
||||
* changes the status to the specified value. Doesn't change other bits
|
||||
* in the status
|
||||
*/
|
||||
static void
|
||||
spider_net_set_descr_status(struct spider_net_descr *descr,
|
||||
enum spider_net_descr_status status)
|
||||
{
|
||||
u32 cmd_status;
|
||||
/* read the status */
|
||||
cmd_status = descr->dmac_cmd_status;
|
||||
/* clean the upper 4 bits */
|
||||
cmd_status &= SPIDER_NET_DESCR_IND_PROC_MASKO;
|
||||
/* add the status to it */
|
||||
cmd_status |= ((u32)status)<<SPIDER_NET_DESCR_IND_PROC_SHIFT;
|
||||
/* and write it back */
|
||||
descr->dmac_cmd_status = cmd_status;
|
||||
return descr->dmac_cmd_status & SPIDER_NET_DESCR_IND_PROC_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -328,24 +299,23 @@ spider_net_free_chain(struct spider_net_card *card,
|
|||
static int
|
||||
spider_net_init_chain(struct spider_net_card *card,
|
||||
struct spider_net_descr_chain *chain,
|
||||
struct spider_net_descr *start_descr, int no)
|
||||
struct spider_net_descr *start_descr,
|
||||
int direction, int no)
|
||||
{
|
||||
int i;
|
||||
struct spider_net_descr *descr;
|
||||
dma_addr_t buf;
|
||||
|
||||
atomic_set(&card->rx_chain_refill,0);
|
||||
|
||||
descr = start_descr;
|
||||
memset(descr, 0, sizeof(*descr) * no);
|
||||
|
||||
/* set up the hardware pointers in each descriptor */
|
||||
for (i=0; i<no; i++, descr++) {
|
||||
spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
|
||||
descr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
|
||||
|
||||
buf = pci_map_single(card->pdev, descr,
|
||||
SPIDER_NET_DESCR_SIZE,
|
||||
PCI_DMA_BIDIRECTIONAL);
|
||||
direction);
|
||||
|
||||
if (buf == DMA_ERROR_CODE)
|
||||
goto iommu_error;
|
||||
|
@ -360,10 +330,11 @@ spider_net_init_chain(struct spider_net_card *card,
|
|||
start_descr->prev = descr-1;
|
||||
|
||||
descr = start_descr;
|
||||
for (i=0; i < no; i++, descr++) {
|
||||
descr->next_descr_addr = descr->next->bus_addr;
|
||||
}
|
||||
if (direction == PCI_DMA_FROMDEVICE)
|
||||
for (i=0; i < no; i++, descr++)
|
||||
descr->next_descr_addr = descr->next->bus_addr;
|
||||
|
||||
spin_lock_init(&chain->lock);
|
||||
chain->head = start_descr;
|
||||
chain->tail = start_descr;
|
||||
|
||||
|
@ -375,7 +346,7 @@ spider_net_init_chain(struct spider_net_card *card,
|
|||
if (descr->bus_addr)
|
||||
pci_unmap_single(card->pdev, descr->bus_addr,
|
||||
SPIDER_NET_DESCR_SIZE,
|
||||
PCI_DMA_BIDIRECTIONAL);
|
||||
direction);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -396,7 +367,7 @@ spider_net_free_rx_chain_contents(struct spider_net_card *card)
|
|||
dev_kfree_skb(descr->skb);
|
||||
pci_unmap_single(card->pdev, descr->buf_addr,
|
||||
SPIDER_NET_MAX_FRAME,
|
||||
PCI_DMA_BIDIRECTIONAL);
|
||||
PCI_DMA_FROMDEVICE);
|
||||
}
|
||||
descr = descr->next;
|
||||
}
|
||||
|
@ -446,15 +417,16 @@ spider_net_prepare_rx_descr(struct spider_net_card *card,
|
|||
skb_reserve(descr->skb, SPIDER_NET_RXBUF_ALIGN - offset);
|
||||
/* io-mmu-map the skb */
|
||||
buf = pci_map_single(card->pdev, descr->skb->data,
|
||||
SPIDER_NET_MAX_FRAME, PCI_DMA_BIDIRECTIONAL);
|
||||
SPIDER_NET_MAX_FRAME, PCI_DMA_FROMDEVICE);
|
||||
descr->buf_addr = buf;
|
||||
if (buf == DMA_ERROR_CODE) {
|
||||
dev_kfree_skb_any(descr->skb);
|
||||
if (netif_msg_rx_err(card) && net_ratelimit())
|
||||
pr_err("Could not iommu-map rx buffer\n");
|
||||
spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
|
||||
descr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
|
||||
} else {
|
||||
descr->dmac_cmd_status = SPIDER_NET_DMAC_RX_CARDOWNED;
|
||||
descr->dmac_cmd_status = SPIDER_NET_DESCR_CARDOWNED |
|
||||
SPIDER_NET_DMAC_NOINTR_COMPLETE;
|
||||
}
|
||||
|
||||
return error;
|
||||
|
@ -468,7 +440,7 @@ spider_net_prepare_rx_descr(struct spider_net_card *card,
|
|||
* chip by writing to the appropriate register. DMA is enabled in
|
||||
* spider_net_enable_rxdmac.
|
||||
*/
|
||||
static void
|
||||
static inline void
|
||||
spider_net_enable_rxchtails(struct spider_net_card *card)
|
||||
{
|
||||
/* assume chain is aligned correctly */
|
||||
|
@ -483,7 +455,7 @@ spider_net_enable_rxchtails(struct spider_net_card *card)
|
|||
* spider_net_enable_rxdmac enables the DMA controller by setting RX_DMA_EN
|
||||
* in the GDADMACCNTR register
|
||||
*/
|
||||
static void
|
||||
static inline void
|
||||
spider_net_enable_rxdmac(struct spider_net_card *card)
|
||||
{
|
||||
wmb();
|
||||
|
@ -500,23 +472,24 @@ spider_net_enable_rxdmac(struct spider_net_card *card)
|
|||
static void
|
||||
spider_net_refill_rx_chain(struct spider_net_card *card)
|
||||
{
|
||||
struct spider_net_descr_chain *chain;
|
||||
|
||||
chain = &card->rx_chain;
|
||||
struct spider_net_descr_chain *chain = &card->rx_chain;
|
||||
unsigned long flags;
|
||||
|
||||
/* one context doing the refill (and a second context seeing that
|
||||
* and omitting it) is ok. If called by NAPI, we'll be called again
|
||||
* as spider_net_decode_one_descr is called several times. If some
|
||||
* interrupt calls us, the NAPI is about to clean up anyway. */
|
||||
if (atomic_inc_return(&card->rx_chain_refill) == 1)
|
||||
while (spider_net_get_descr_status(chain->head) ==
|
||||
SPIDER_NET_DESCR_NOT_IN_USE) {
|
||||
if (spider_net_prepare_rx_descr(card, chain->head))
|
||||
break;
|
||||
chain->head = chain->head->next;
|
||||
}
|
||||
if (!spin_trylock_irqsave(&chain->lock, flags))
|
||||
return;
|
||||
|
||||
atomic_dec(&card->rx_chain_refill);
|
||||
while (spider_net_get_descr_status(chain->head) ==
|
||||
SPIDER_NET_DESCR_NOT_IN_USE) {
|
||||
if (spider_net_prepare_rx_descr(card, chain->head))
|
||||
break;
|
||||
chain->head = chain->head->next;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&chain->lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -553,111 +526,6 @@ spider_net_alloc_rx_skbs(struct spider_net_card *card)
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* spider_net_release_tx_descr - processes a used tx descriptor
|
||||
* @card: card structure
|
||||
* @descr: descriptor to release
|
||||
*
|
||||
* releases a used tx descriptor (unmapping, freeing of skb)
|
||||
*/
|
||||
static void
|
||||
spider_net_release_tx_descr(struct spider_net_card *card,
|
||||
struct spider_net_descr *descr)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
/* unmap the skb */
|
||||
skb = descr->skb;
|
||||
pci_unmap_single(card->pdev, descr->buf_addr, skb->len,
|
||||
PCI_DMA_BIDIRECTIONAL);
|
||||
|
||||
dev_kfree_skb_any(skb);
|
||||
|
||||
/* set status to not used */
|
||||
spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
|
||||
}
|
||||
|
||||
/**
|
||||
* spider_net_release_tx_chain - processes sent tx descriptors
|
||||
* @card: adapter structure
|
||||
* @brutal: if set, don't care about whether descriptor seems to be in use
|
||||
*
|
||||
* returns 0 if the tx ring is empty, otherwise 1.
|
||||
*
|
||||
* spider_net_release_tx_chain releases the tx descriptors that spider has
|
||||
* finished with (if non-brutal) or simply release tx descriptors (if brutal).
|
||||
* If some other context is calling this function, we return 1 so that we're
|
||||
* scheduled again (if we were scheduled) and will not loose initiative.
|
||||
*/
|
||||
static int
|
||||
spider_net_release_tx_chain(struct spider_net_card *card, int brutal)
|
||||
{
|
||||
struct spider_net_descr_chain *tx_chain = &card->tx_chain;
|
||||
enum spider_net_descr_status status;
|
||||
|
||||
if (atomic_inc_return(&card->tx_chain_release) != 1) {
|
||||
atomic_dec(&card->tx_chain_release);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
status = spider_net_get_descr_status(tx_chain->tail);
|
||||
switch (status) {
|
||||
case SPIDER_NET_DESCR_CARDOWNED:
|
||||
if (!brutal)
|
||||
goto out;
|
||||
/* fallthrough, if we release the descriptors
|
||||
* brutally (then we don't care about
|
||||
* SPIDER_NET_DESCR_CARDOWNED) */
|
||||
case SPIDER_NET_DESCR_RESPONSE_ERROR:
|
||||
case SPIDER_NET_DESCR_PROTECTION_ERROR:
|
||||
case SPIDER_NET_DESCR_FORCE_END:
|
||||
if (netif_msg_tx_err(card))
|
||||
pr_err("%s: forcing end of tx descriptor "
|
||||
"with status x%02x\n",
|
||||
card->netdev->name, status);
|
||||
card->netdev_stats.tx_dropped++;
|
||||
break;
|
||||
|
||||
case SPIDER_NET_DESCR_COMPLETE:
|
||||
card->netdev_stats.tx_packets++;
|
||||
card->netdev_stats.tx_bytes +=
|
||||
tx_chain->tail->skb->len;
|
||||
break;
|
||||
|
||||
default: /* any other value (== SPIDER_NET_DESCR_NOT_IN_USE) */
|
||||
goto out;
|
||||
}
|
||||
spider_net_release_tx_descr(card, tx_chain->tail);
|
||||
tx_chain->tail = tx_chain->tail->next;
|
||||
}
|
||||
out:
|
||||
atomic_dec(&card->tx_chain_release);
|
||||
|
||||
netif_wake_queue(card->netdev);
|
||||
|
||||
if (status == SPIDER_NET_DESCR_CARDOWNED)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* spider_net_cleanup_tx_ring - cleans up the TX ring
|
||||
* @card: card structure
|
||||
*
|
||||
* spider_net_cleanup_tx_ring is called by the tx_timer (as we don't use
|
||||
* interrupts to cleanup our TX ring) and returns sent packets to the stack
|
||||
* by freeing them
|
||||
*/
|
||||
static void
|
||||
spider_net_cleanup_tx_ring(struct spider_net_card *card)
|
||||
{
|
||||
if ( (spider_net_release_tx_chain(card, 0)) &&
|
||||
(card->netdev->flags & IFF_UP) ) {
|
||||
mod_timer(&card->tx_timer, jiffies + SPIDER_NET_TX_TIMER);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* spider_net_get_multicast_hash - generates hash for multicast filter table
|
||||
* @addr: multicast address
|
||||
|
@ -760,97 +628,6 @@ spider_net_disable_rxdmac(struct spider_net_card *card)
|
|||
SPIDER_NET_DMA_RX_FEND_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* spider_net_stop - called upon ifconfig down
|
||||
* @netdev: interface device structure
|
||||
*
|
||||
* always returns 0
|
||||
*/
|
||||
int
|
||||
spider_net_stop(struct net_device *netdev)
|
||||
{
|
||||
struct spider_net_card *card = netdev_priv(netdev);
|
||||
|
||||
tasklet_kill(&card->rxram_full_tl);
|
||||
netif_poll_disable(netdev);
|
||||
netif_carrier_off(netdev);
|
||||
netif_stop_queue(netdev);
|
||||
del_timer_sync(&card->tx_timer);
|
||||
|
||||
/* disable/mask all interrupts */
|
||||
spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0);
|
||||
spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0);
|
||||
spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0);
|
||||
|
||||
/* free_irq(netdev->irq, netdev);*/
|
||||
free_irq(to_pci_dev(netdev->class_dev.dev)->irq, netdev);
|
||||
|
||||
spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
|
||||
SPIDER_NET_DMA_TX_FEND_VALUE);
|
||||
|
||||
/* turn off DMA, force end */
|
||||
spider_net_disable_rxdmac(card);
|
||||
|
||||
/* release chains */
|
||||
spider_net_release_tx_chain(card, 1);
|
||||
|
||||
spider_net_free_chain(card, &card->tx_chain);
|
||||
spider_net_free_chain(card, &card->rx_chain);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* spider_net_get_next_tx_descr - returns the next available tx descriptor
|
||||
* @card: device structure to get descriptor from
|
||||
*
|
||||
* returns the address of the next descriptor, or NULL if not available.
|
||||
*/
|
||||
static struct spider_net_descr *
|
||||
spider_net_get_next_tx_descr(struct spider_net_card *card)
|
||||
{
|
||||
/* check, if head points to not-in-use descr */
|
||||
if ( spider_net_get_descr_status(card->tx_chain.head) ==
|
||||
SPIDER_NET_DESCR_NOT_IN_USE ) {
|
||||
return card->tx_chain.head;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* spider_net_set_txdescr_cmdstat - sets the tx descriptor command field
|
||||
* @descr: descriptor structure to fill out
|
||||
* @skb: packet to consider
|
||||
*
|
||||
* fills out the command and status field of the descriptor structure,
|
||||
* depending on hardware checksum settings.
|
||||
*/
|
||||
static void
|
||||
spider_net_set_txdescr_cmdstat(struct spider_net_descr *descr,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
/* make sure the other fields in the descriptor are written */
|
||||
wmb();
|
||||
|
||||
if (skb->ip_summed != CHECKSUM_HW) {
|
||||
descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_NOCS;
|
||||
return;
|
||||
}
|
||||
|
||||
/* is packet ip?
|
||||
* if yes: tcp? udp? */
|
||||
if (skb->protocol == htons(ETH_P_IP)) {
|
||||
if (skb->nh.iph->protocol == IPPROTO_TCP)
|
||||
descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_TCPCS;
|
||||
else if (skb->nh.iph->protocol == IPPROTO_UDP)
|
||||
descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_UDPCS;
|
||||
else /* the stack should checksum non-tcp and non-udp
|
||||
packets on his own: NETIF_F_IP_CSUM */
|
||||
descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_NOCS;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* spider_net_prepare_tx_descr - fill tx descriptor with skb data
|
||||
* @card: card structure
|
||||
|
@ -864,13 +641,12 @@ spider_net_set_txdescr_cmdstat(struct spider_net_descr *descr,
|
|||
*/
|
||||
static int
|
||||
spider_net_prepare_tx_descr(struct spider_net_card *card,
|
||||
struct spider_net_descr *descr,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct spider_net_descr *descr = card->tx_chain.head;
|
||||
dma_addr_t buf;
|
||||
|
||||
buf = pci_map_single(card->pdev, skb->data,
|
||||
skb->len, PCI_DMA_BIDIRECTIONAL);
|
||||
buf = pci_map_single(card->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
|
||||
if (buf == DMA_ERROR_CODE) {
|
||||
if (netif_msg_tx_err(card) && net_ratelimit())
|
||||
pr_err("could not iommu-map packet (%p, %i). "
|
||||
|
@ -880,10 +656,101 @@ spider_net_prepare_tx_descr(struct spider_net_card *card,
|
|||
|
||||
descr->buf_addr = buf;
|
||||
descr->buf_size = skb->len;
|
||||
descr->next_descr_addr = 0;
|
||||
descr->skb = skb;
|
||||
descr->data_status = 0;
|
||||
|
||||
spider_net_set_txdescr_cmdstat(descr,skb);
|
||||
descr->dmac_cmd_status =
|
||||
SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_NOCS;
|
||||
if (skb->protocol == htons(ETH_P_IP))
|
||||
switch (skb->nh.iph->protocol) {
|
||||
case IPPROTO_TCP:
|
||||
descr->dmac_cmd_status |= SPIDER_NET_DMAC_TCP;
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
descr->dmac_cmd_status |= SPIDER_NET_DMAC_UDP;
|
||||
break;
|
||||
}
|
||||
|
||||
descr->prev->next_descr_addr = descr->bus_addr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* spider_net_release_tx_descr - processes a used tx descriptor
|
||||
* @card: card structure
|
||||
* @descr: descriptor to release
|
||||
*
|
||||
* releases a used tx descriptor (unmapping, freeing of skb)
|
||||
*/
|
||||
static inline void
|
||||
spider_net_release_tx_descr(struct spider_net_card *card)
|
||||
{
|
||||
struct spider_net_descr *descr = card->tx_chain.tail;
|
||||
struct sk_buff *skb;
|
||||
|
||||
card->tx_chain.tail = card->tx_chain.tail->next;
|
||||
descr->dmac_cmd_status |= SPIDER_NET_DESCR_NOT_IN_USE;
|
||||
|
||||
/* unmap the skb */
|
||||
skb = descr->skb;
|
||||
pci_unmap_single(card->pdev, descr->buf_addr, skb->len,
|
||||
PCI_DMA_TODEVICE);
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
/**
|
||||
* spider_net_release_tx_chain - processes sent tx descriptors
|
||||
* @card: adapter structure
|
||||
* @brutal: if set, don't care about whether descriptor seems to be in use
|
||||
*
|
||||
* returns 0 if the tx ring is empty, otherwise 1.
|
||||
*
|
||||
* spider_net_release_tx_chain releases the tx descriptors that spider has
|
||||
* finished with (if non-brutal) or simply release tx descriptors (if brutal).
|
||||
* If some other context is calling this function, we return 1 so that we're
|
||||
* scheduled again (if we were scheduled) and will not loose initiative.
|
||||
*/
|
||||
static int
|
||||
spider_net_release_tx_chain(struct spider_net_card *card, int brutal)
|
||||
{
|
||||
struct spider_net_descr_chain *chain = &card->tx_chain;
|
||||
int status;
|
||||
|
||||
spider_net_read_reg(card, SPIDER_NET_GDTDMACCNTR);
|
||||
|
||||
while (chain->tail != chain->head) {
|
||||
status = spider_net_get_descr_status(chain->tail);
|
||||
switch (status) {
|
||||
case SPIDER_NET_DESCR_COMPLETE:
|
||||
card->netdev_stats.tx_packets++;
|
||||
card->netdev_stats.tx_bytes += chain->tail->skb->len;
|
||||
break;
|
||||
|
||||
case SPIDER_NET_DESCR_CARDOWNED:
|
||||
if (!brutal)
|
||||
return 1;
|
||||
/* fallthrough, if we release the descriptors
|
||||
* brutally (then we don't care about
|
||||
* SPIDER_NET_DESCR_CARDOWNED) */
|
||||
|
||||
case SPIDER_NET_DESCR_RESPONSE_ERROR:
|
||||
case SPIDER_NET_DESCR_PROTECTION_ERROR:
|
||||
case SPIDER_NET_DESCR_FORCE_END:
|
||||
if (netif_msg_tx_err(card))
|
||||
pr_err("%s: forcing end of tx descriptor "
|
||||
"with status x%02x\n",
|
||||
card->netdev->name, status);
|
||||
card->netdev_stats.tx_errors++;
|
||||
break;
|
||||
|
||||
default:
|
||||
card->netdev_stats.tx_dropped++;
|
||||
return 1;
|
||||
}
|
||||
spider_net_release_tx_descr(card);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -896,18 +763,32 @@ spider_net_prepare_tx_descr(struct spider_net_card *card,
|
|||
* spider_net_kick_tx_dma writes the current tx chain head as start address
|
||||
* of the tx descriptor chain and enables the transmission DMA engine
|
||||
*/
|
||||
static void
|
||||
spider_net_kick_tx_dma(struct spider_net_card *card,
|
||||
struct spider_net_descr *descr)
|
||||
static inline void
|
||||
spider_net_kick_tx_dma(struct spider_net_card *card)
|
||||
{
|
||||
/* this is the only descriptor in the output chain.
|
||||
* Enable TX DMA */
|
||||
struct spider_net_descr *descr;
|
||||
|
||||
spider_net_write_reg(card, SPIDER_NET_GDTDCHA,
|
||||
descr->bus_addr);
|
||||
if (spider_net_read_reg(card, SPIDER_NET_GDTDMACCNTR) &
|
||||
SPIDER_NET_TX_DMA_EN)
|
||||
goto out;
|
||||
|
||||
spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
|
||||
SPIDER_NET_DMA_TX_VALUE);
|
||||
descr = card->tx_chain.tail;
|
||||
for (;;) {
|
||||
if (spider_net_get_descr_status(descr) ==
|
||||
SPIDER_NET_DESCR_CARDOWNED) {
|
||||
spider_net_write_reg(card, SPIDER_NET_GDTDCHA,
|
||||
descr->bus_addr);
|
||||
spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
|
||||
SPIDER_NET_DMA_TX_VALUE);
|
||||
break;
|
||||
}
|
||||
if (descr == card->tx_chain.head)
|
||||
break;
|
||||
descr = descr->next;
|
||||
}
|
||||
|
||||
out:
|
||||
mod_timer(&card->tx_timer, jiffies + SPIDER_NET_TX_TIMER);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -915,47 +796,69 @@ spider_net_kick_tx_dma(struct spider_net_card *card,
|
|||
* @skb: packet to send out
|
||||
* @netdev: interface device structure
|
||||
*
|
||||
* returns 0 on success, <0 on failure
|
||||
* returns 0 on success, !0 on failure
|
||||
*/
|
||||
static int
|
||||
spider_net_xmit(struct sk_buff *skb, struct net_device *netdev)
|
||||
{
|
||||
struct spider_net_card *card = netdev_priv(netdev);
|
||||
struct spider_net_descr *descr;
|
||||
struct spider_net_descr_chain *chain = &card->tx_chain;
|
||||
struct spider_net_descr *descr = chain->head;
|
||||
unsigned long flags;
|
||||
int result;
|
||||
|
||||
spin_lock_irqsave(&chain->lock, flags);
|
||||
|
||||
spider_net_release_tx_chain(card, 0);
|
||||
|
||||
descr = spider_net_get_next_tx_descr(card);
|
||||
|
||||
if (!descr)
|
||||
goto error;
|
||||
|
||||
result = spider_net_prepare_tx_descr(card, descr, skb);
|
||||
if (result)
|
||||
goto error;
|
||||
|
||||
card->tx_chain.head = card->tx_chain.head->next;
|
||||
|
||||
if (spider_net_get_descr_status(descr->prev) !=
|
||||
SPIDER_NET_DESCR_CARDOWNED) {
|
||||
/* make sure the current descriptor is in memory. Then
|
||||
* kicking it on again makes sense, if the previous is not
|
||||
* card-owned anymore. Check the previous descriptor twice
|
||||
* to omit an mb() in heavy traffic cases */
|
||||
mb();
|
||||
if (spider_net_get_descr_status(descr->prev) !=
|
||||
SPIDER_NET_DESCR_CARDOWNED)
|
||||
spider_net_kick_tx_dma(card, descr);
|
||||
if (chain->head->next == chain->tail->prev) {
|
||||
card->netdev_stats.tx_dropped++;
|
||||
result = NETDEV_TX_LOCKED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
mod_timer(&card->tx_timer, jiffies + SPIDER_NET_TX_TIMER);
|
||||
if (spider_net_get_descr_status(descr) != SPIDER_NET_DESCR_NOT_IN_USE) {
|
||||
result = NETDEV_TX_LOCKED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
if (spider_net_prepare_tx_descr(card, skb) != 0) {
|
||||
card->netdev_stats.tx_dropped++;
|
||||
result = NETDEV_TX_BUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
error:
|
||||
card->netdev_stats.tx_dropped++;
|
||||
return NETDEV_TX_BUSY;
|
||||
result = NETDEV_TX_OK;
|
||||
|
||||
spider_net_kick_tx_dma(card);
|
||||
card->tx_chain.head = card->tx_chain.head->next;
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&chain->lock, flags);
|
||||
netif_wake_queue(netdev);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* spider_net_cleanup_tx_ring - cleans up the TX ring
|
||||
* @card: card structure
|
||||
*
|
||||
* spider_net_cleanup_tx_ring is called by the tx_timer (as we don't use
|
||||
* interrupts to cleanup our TX ring) and returns sent packets to the stack
|
||||
* by freeing them
|
||||
*/
|
||||
static void
|
||||
spider_net_cleanup_tx_ring(struct spider_net_card *card)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&card->tx_chain.lock, flags);
|
||||
|
||||
if ((spider_net_release_tx_chain(card, 0) != 0) &&
|
||||
(card->netdev->flags & IFF_UP))
|
||||
spider_net_kick_tx_dma(card);
|
||||
|
||||
spin_unlock_irqrestore(&card->tx_chain.lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1002,7 +905,7 @@ spider_net_pass_skb_up(struct spider_net_descr *descr,
|
|||
|
||||
/* unmap descriptor */
|
||||
pci_unmap_single(card->pdev, descr->buf_addr, SPIDER_NET_MAX_FRAME,
|
||||
PCI_DMA_BIDIRECTIONAL);
|
||||
PCI_DMA_FROMDEVICE);
|
||||
|
||||
/* the cases we'll throw away the packet immediately */
|
||||
if (data_error & SPIDER_NET_DESTROY_RX_FLAGS) {
|
||||
|
@ -1067,14 +970,11 @@ spider_net_pass_skb_up(struct spider_net_descr *descr,
|
|||
static int
|
||||
spider_net_decode_one_descr(struct spider_net_card *card, int napi)
|
||||
{
|
||||
enum spider_net_descr_status status;
|
||||
struct spider_net_descr *descr;
|
||||
struct spider_net_descr_chain *chain;
|
||||
struct spider_net_descr_chain *chain = &card->rx_chain;
|
||||
struct spider_net_descr *descr = chain->tail;
|
||||
int status;
|
||||
int result;
|
||||
|
||||
chain = &card->rx_chain;
|
||||
descr = chain->tail;
|
||||
|
||||
status = spider_net_get_descr_status(descr);
|
||||
|
||||
if (status == SPIDER_NET_DESCR_CARDOWNED) {
|
||||
|
@ -1103,7 +1003,7 @@ spider_net_decode_one_descr(struct spider_net_card *card, int napi)
|
|||
card->netdev->name, status);
|
||||
card->netdev_stats.rx_dropped++;
|
||||
pci_unmap_single(card->pdev, descr->buf_addr,
|
||||
SPIDER_NET_MAX_FRAME, PCI_DMA_BIDIRECTIONAL);
|
||||
SPIDER_NET_MAX_FRAME, PCI_DMA_FROMDEVICE);
|
||||
dev_kfree_skb_irq(descr->skb);
|
||||
goto refill;
|
||||
}
|
||||
|
@ -1119,7 +1019,7 @@ spider_net_decode_one_descr(struct spider_net_card *card, int napi)
|
|||
/* ok, we've got a packet in descr */
|
||||
result = spider_net_pass_skb_up(descr, card, napi);
|
||||
refill:
|
||||
spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
|
||||
descr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
|
||||
/* change the descriptor state: */
|
||||
if (!napi)
|
||||
spider_net_refill_rx_chain(card);
|
||||
|
@ -1290,21 +1190,6 @@ spider_net_set_mac(struct net_device *netdev, void *p)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* spider_net_enable_txdmac - enables a TX DMA controller
|
||||
* @card: card structure
|
||||
*
|
||||
* spider_net_enable_txdmac enables the TX DMA controller by setting the
|
||||
* descriptor chain tail address
|
||||
*/
|
||||
static void
|
||||
spider_net_enable_txdmac(struct spider_net_card *card)
|
||||
{
|
||||
/* assume chain is aligned correctly */
|
||||
spider_net_write_reg(card, SPIDER_NET_GDTDCHA,
|
||||
card->tx_chain.tail->bus_addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* spider_net_handle_rxram_full - cleans up RX ring upon RX RAM full interrupt
|
||||
* @card: card structure
|
||||
|
@ -1653,7 +1538,6 @@ spider_net_enable_card(struct spider_net_card *card)
|
|||
{ SPIDER_NET_GMRWOLCTRL, 0 },
|
||||
{ SPIDER_NET_GTESTMD, 0x10000000 },
|
||||
{ SPIDER_NET_GTTQMSK, 0x00400040 },
|
||||
{ SPIDER_NET_GTESTMD, 0 },
|
||||
|
||||
{ SPIDER_NET_GMACINTEN, 0 },
|
||||
|
||||
|
@ -1692,9 +1576,6 @@ spider_net_enable_card(struct spider_net_card *card)
|
|||
|
||||
spider_net_write_reg(card, SPIDER_NET_GRXDMAEN, SPIDER_NET_WOL_VALUE);
|
||||
|
||||
/* set chain tail adress for TX chain */
|
||||
spider_net_enable_txdmac(card);
|
||||
|
||||
spider_net_write_reg(card, SPIDER_NET_GMACLENLMT,
|
||||
SPIDER_NET_LENLMT_VALUE);
|
||||
spider_net_write_reg(card, SPIDER_NET_GMACMODE,
|
||||
|
@ -1709,6 +1590,9 @@ spider_net_enable_card(struct spider_net_card *card)
|
|||
SPIDER_NET_INT1_MASK_VALUE);
|
||||
spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK,
|
||||
SPIDER_NET_INT2_MASK_VALUE);
|
||||
|
||||
spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
|
||||
SPIDER_NET_GDTDCEIDIS);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1728,10 +1612,12 @@ spider_net_open(struct net_device *netdev)
|
|||
|
||||
result = -ENOMEM;
|
||||
if (spider_net_init_chain(card, &card->tx_chain,
|
||||
card->descr, tx_descriptors))
|
||||
card->descr,
|
||||
PCI_DMA_TODEVICE, tx_descriptors))
|
||||
goto alloc_tx_failed;
|
||||
if (spider_net_init_chain(card, &card->rx_chain,
|
||||
card->descr + tx_descriptors, rx_descriptors))
|
||||
card->descr + tx_descriptors,
|
||||
PCI_DMA_FROMDEVICE, rx_descriptors))
|
||||
goto alloc_rx_failed;
|
||||
|
||||
/* allocate rx skbs */
|
||||
|
@ -1938,7 +1824,7 @@ spider_net_workaround_rxramfull(struct spider_net_card *card)
|
|||
/* empty sequencer data */
|
||||
for (sequencer = 0; sequencer < SPIDER_NET_FIRMWARE_SEQS;
|
||||
sequencer++) {
|
||||
spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT +
|
||||
spider_net_write_reg(card, SPIDER_NET_GSnPRGADR +
|
||||
sequencer * 8, 0x0);
|
||||
for (i = 0; i < SPIDER_NET_FIRMWARE_SEQWORDS; i++) {
|
||||
spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT +
|
||||
|
@ -1954,6 +1840,49 @@ spider_net_workaround_rxramfull(struct spider_net_card *card)
|
|||
SPIDER_NET_CKRCTRL_STOP_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* spider_net_stop - called upon ifconfig down
|
||||
* @netdev: interface device structure
|
||||
*
|
||||
* always returns 0
|
||||
*/
|
||||
int
|
||||
spider_net_stop(struct net_device *netdev)
|
||||
{
|
||||
struct spider_net_card *card = netdev_priv(netdev);
|
||||
|
||||
tasklet_kill(&card->rxram_full_tl);
|
||||
netif_poll_disable(netdev);
|
||||
netif_carrier_off(netdev);
|
||||
netif_stop_queue(netdev);
|
||||
del_timer_sync(&card->tx_timer);
|
||||
|
||||
/* disable/mask all interrupts */
|
||||
spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0);
|
||||
spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0);
|
||||
spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0);
|
||||
|
||||
/* free_irq(netdev->irq, netdev);*/
|
||||
free_irq(to_pci_dev(netdev->class_dev.dev)->irq, netdev);
|
||||
|
||||
spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
|
||||
SPIDER_NET_DMA_TX_FEND_VALUE);
|
||||
|
||||
/* turn off DMA, force end */
|
||||
spider_net_disable_rxdmac(card);
|
||||
|
||||
/* release chains */
|
||||
if (spin_trylock(&card->tx_chain.lock)) {
|
||||
spider_net_release_tx_chain(card, 1);
|
||||
spin_unlock(&card->tx_chain.lock);
|
||||
}
|
||||
|
||||
spider_net_free_chain(card, &card->tx_chain);
|
||||
spider_net_free_chain(card, &card->rx_chain);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* spider_net_tx_timeout_task - task scheduled by the watchdog timeout
|
||||
* function (to be called not under interrupt status)
|
||||
|
@ -1982,7 +1911,7 @@ spider_net_tx_timeout_task(void *data)
|
|||
goto out;
|
||||
|
||||
spider_net_open(netdev);
|
||||
spider_net_kick_tx_dma(card, card->tx_chain.head);
|
||||
spider_net_kick_tx_dma(card);
|
||||
netif_device_attach(netdev);
|
||||
|
||||
out:
|
||||
|
@ -2065,7 +1994,6 @@ spider_net_setup_netdev(struct spider_net_card *card)
|
|||
|
||||
pci_set_drvdata(card->pdev, netdev);
|
||||
|
||||
atomic_set(&card->tx_chain_release,0);
|
||||
card->rxram_full_tl.data = (unsigned long) card;
|
||||
card->rxram_full_tl.func =
|
||||
(void (*)(unsigned long)) spider_net_handle_rxram_full;
|
||||
|
@ -2079,7 +2007,7 @@ spider_net_setup_netdev(struct spider_net_card *card)
|
|||
|
||||
spider_net_setup_netdev_ops(netdev);
|
||||
|
||||
netdev->features = NETIF_F_HW_CSUM;
|
||||
netdev->features = NETIF_F_HW_CSUM | NETIF_F_LLTX;
|
||||
/* some time: NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX |
|
||||
* NETIF_F_HW_VLAN_FILTER */
|
||||
|
||||
|
|
|
@ -208,7 +208,10 @@ extern char spider_net_driver_name[];
|
|||
#define SPIDER_NET_DMA_RX_VALUE 0x80000000
|
||||
#define SPIDER_NET_DMA_RX_FEND_VALUE 0x00030003
|
||||
/* to set TX_DMA_EN */
|
||||
#define SPIDER_NET_DMA_TX_VALUE 0x80000000
|
||||
#define SPIDER_NET_TX_DMA_EN 0x80000000
|
||||
#define SPIDER_NET_GDTDCEIDIS 0x00000002
|
||||
#define SPIDER_NET_DMA_TX_VALUE SPIDER_NET_TX_DMA_EN | \
|
||||
SPIDER_NET_GDTDCEIDIS
|
||||
#define SPIDER_NET_DMA_TX_FEND_VALUE 0x00030003
|
||||
|
||||
/* SPIDER_NET_UA_DESCR_VALUE is OR'ed with the unicast address */
|
||||
|
@ -329,55 +332,23 @@ enum spider_net_int2_status {
|
|||
(~SPIDER_NET_TXINT) & \
|
||||
(~SPIDER_NET_RXINT) )
|
||||
|
||||
#define SPIDER_NET_GPREXEC 0x80000000
|
||||
#define SPIDER_NET_GPRDAT_MASK 0x0000ffff
|
||||
#define SPIDER_NET_GPREXEC 0x80000000
|
||||
#define SPIDER_NET_GPRDAT_MASK 0x0000ffff
|
||||
|
||||
/* descriptor bits
|
||||
*
|
||||
* 1010 descriptor ready
|
||||
* 0 descr in middle of chain
|
||||
* 000 fixed to 0
|
||||
*
|
||||
* 0 no interrupt on completion
|
||||
* 000 fixed to 0
|
||||
* 1 no ipsec processing
|
||||
* 1 last descriptor for this frame
|
||||
* 00 no checksum
|
||||
* 10 tcp checksum
|
||||
* 11 udp checksum
|
||||
*
|
||||
* 00 fixed to 0
|
||||
* 0 fixed to 0
|
||||
* 0 no interrupt on response errors
|
||||
* 0 no interrupt on invalid descr
|
||||
* 0 no interrupt on dma process termination
|
||||
* 0 no interrupt on descr chain end
|
||||
* 0 no interrupt on descr complete
|
||||
*
|
||||
* 000 fixed to 0
|
||||
* 0 response error interrupt status
|
||||
* 0 invalid descr status
|
||||
* 0 dma termination status
|
||||
* 0 descr chain end status
|
||||
* 0 descr complete status */
|
||||
#define SPIDER_NET_DMAC_CMDSTAT_NOCS 0xa00c0000
|
||||
#define SPIDER_NET_DMAC_CMDSTAT_TCPCS 0xa00e0000
|
||||
#define SPIDER_NET_DMAC_CMDSTAT_UDPCS 0xa00f0000
|
||||
#define SPIDER_NET_DESCR_IND_PROC_SHIFT 28
|
||||
#define SPIDER_NET_DESCR_IND_PROC_MASKO 0x0fffffff
|
||||
#define SPIDER_NET_DMAC_NOINTR_COMPLETE 0x00800000
|
||||
#define SPIDER_NET_DMAC_NOCS 0x00040000
|
||||
#define SPIDER_NET_DMAC_TCP 0x00020000
|
||||
#define SPIDER_NET_DMAC_UDP 0x00030000
|
||||
#define SPIDER_NET_TXDCEST 0x08000000
|
||||
|
||||
/* descr ready, descr is in middle of chain, get interrupt on completion */
|
||||
#define SPIDER_NET_DMAC_RX_CARDOWNED 0xa0800000
|
||||
|
||||
enum spider_net_descr_status {
|
||||
SPIDER_NET_DESCR_COMPLETE = 0x00, /* used in rx and tx */
|
||||
SPIDER_NET_DESCR_RESPONSE_ERROR = 0x01, /* used in rx and tx */
|
||||
SPIDER_NET_DESCR_PROTECTION_ERROR = 0x02, /* used in rx and tx */
|
||||
SPIDER_NET_DESCR_FRAME_END = 0x04, /* used in rx */
|
||||
SPIDER_NET_DESCR_FORCE_END = 0x05, /* used in rx and tx */
|
||||
SPIDER_NET_DESCR_CARDOWNED = 0x0a, /* used in rx and tx */
|
||||
SPIDER_NET_DESCR_NOT_IN_USE /* any other value */
|
||||
};
|
||||
#define SPIDER_NET_DESCR_IND_PROC_MASK 0xF0000000
|
||||
#define SPIDER_NET_DESCR_COMPLETE 0x00000000 /* used in rx and tx */
|
||||
#define SPIDER_NET_DESCR_RESPONSE_ERROR 0x10000000 /* used in rx and tx */
|
||||
#define SPIDER_NET_DESCR_PROTECTION_ERROR 0x20000000 /* used in rx and tx */
|
||||
#define SPIDER_NET_DESCR_FRAME_END 0x40000000 /* used in rx */
|
||||
#define SPIDER_NET_DESCR_FORCE_END 0x50000000 /* used in rx and tx */
|
||||
#define SPIDER_NET_DESCR_CARDOWNED 0xA0000000 /* used in rx and tx */
|
||||
#define SPIDER_NET_DESCR_NOT_IN_USE 0xF0000000
|
||||
|
||||
struct spider_net_descr {
|
||||
/* as defined by the hardware */
|
||||
|
@ -398,7 +369,7 @@ struct spider_net_descr {
|
|||
} __attribute__((aligned(32)));
|
||||
|
||||
struct spider_net_descr_chain {
|
||||
/* we walk from tail to head */
|
||||
spinlock_t lock;
|
||||
struct spider_net_descr *head;
|
||||
struct spider_net_descr *tail;
|
||||
};
|
||||
|
@ -453,8 +424,6 @@ struct spider_net_card {
|
|||
|
||||
struct spider_net_descr_chain tx_chain;
|
||||
struct spider_net_descr_chain rx_chain;
|
||||
atomic_t rx_chain_refill;
|
||||
atomic_t tx_chain_release;
|
||||
|
||||
struct net_device_stats netdev_stats;
|
||||
|
||||
|
|
|
@ -3255,12 +3255,7 @@ static void __devexit happy_meal_pci_remove(struct pci_dev *pdev)
|
|||
}
|
||||
|
||||
static struct pci_device_id happymeal_pci_ids[] = {
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_SUN,
|
||||
.device = PCI_DEVICE_ID_SUN_HAPPYMEAL,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
},
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_HAPPYMEAL) },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
|
@ -3275,7 +3270,7 @@ static struct pci_driver hme_pci_driver = {
|
|||
|
||||
static int __init happy_meal_pci_init(void)
|
||||
{
|
||||
return pci_module_init(&hme_pci_driver);
|
||||
return pci_register_driver(&hme_pci_driver);
|
||||
}
|
||||
|
||||
static void happy_meal_pci_exit(void)
|
||||
|
|
|
@ -197,7 +197,6 @@ static int c101_open(struct net_device *dev)
|
|||
sca_out(IE0_TXINT, MSCI0_OFFSET + IE0, port);
|
||||
|
||||
set_carrier(port);
|
||||
printk(KERN_DEBUG "0x%X\n", sca_in(MSCI1_OFFSET + ST3, port));
|
||||
|
||||
/* enable MSCI1 CDCD interrupt */
|
||||
sca_out(IE1_CDCD, MSCI1_OFFSET + IE1, port);
|
||||
|
@ -449,4 +448,5 @@ module_exit(c101_cleanup);
|
|||
MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
|
||||
MODULE_DESCRIPTION("Moxa C101 serial port driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
module_param(hw, charp, 0444); /* hw=irq,ram:irq,... */
|
||||
module_param(hw, charp, 0444);
|
||||
MODULE_PARM_DESC(hw, "irq,ram:irq,...");
|
||||
|
|
|
@ -107,6 +107,7 @@ int hdlc_ppp_ioctl(struct net_device *dev, struct ifreq *ifr)
|
|||
dev->hard_header = NULL;
|
||||
dev->type = ARPHRD_PPP;
|
||||
dev->addr_len = 0;
|
||||
netif_dormant_off(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -82,6 +82,7 @@ int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr)
|
|||
dev->type = ARPHRD_RAWHDLC;
|
||||
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
|
||||
dev->addr_len = 0;
|
||||
netif_dormant_off(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -100,6 +100,7 @@ int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr)
|
|||
dev->tx_queue_len = old_qlen;
|
||||
memcpy(dev->dev_addr, "\x00\x01", 2);
|
||||
get_random_bytes(dev->dev_addr + 2, ETH_ALEN - 2);
|
||||
netif_dormant_off(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -212,6 +212,7 @@ int hdlc_x25_ioctl(struct net_device *dev, struct ifreq *ifr)
|
|||
dev->hard_header = NULL;
|
||||
dev->type = ARPHRD_X25;
|
||||
dev->addr_len = 0;
|
||||
netif_dormant_off(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -564,4 +564,5 @@ module_exit(n2_cleanup);
|
|||
MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
|
||||
MODULE_DESCRIPTION("RISCom/N2 serial port driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
module_param(hw, charp, 0444); /* hw=io,irq,ram,ports:io,irq,... */
|
||||
module_param(hw, charp, 0444);
|
||||
MODULE_PARM_DESC(hw, "io,irq,ram,ports:io,irq,...");
|
||||
|
|
|
@ -304,6 +304,7 @@ static int __init xpram_setup_sizes(unsigned long pages)
|
|||
{
|
||||
unsigned long mem_needed;
|
||||
unsigned long mem_auto;
|
||||
unsigned long long size;
|
||||
int mem_auto_no;
|
||||
int i;
|
||||
|
||||
|
@ -321,9 +322,19 @@ static int __init xpram_setup_sizes(unsigned long pages)
|
|||
mem_needed = 0;
|
||||
mem_auto_no = 0;
|
||||
for (i = 0; i < xpram_devs; i++) {
|
||||
if (sizes[i])
|
||||
xpram_sizes[i] =
|
||||
(memparse(sizes[i], &sizes[i]) + 3) & -4UL;
|
||||
if (sizes[i]) {
|
||||
size = simple_strtoull(sizes[i], &sizes[i], 0);
|
||||
switch (sizes[i][0]) {
|
||||
case 'g':
|
||||
case 'G':
|
||||
size <<= 20;
|
||||
break;
|
||||
case 'm':
|
||||
case 'M':
|
||||
size <<= 10;
|
||||
}
|
||||
xpram_sizes[i] = (size + 3) & -4UL;
|
||||
}
|
||||
if (xpram_sizes[i])
|
||||
mem_needed += xpram_sizes[i];
|
||||
else
|
||||
|
|
|
@ -1106,10 +1106,10 @@ raw3270_delete_device(struct raw3270 *rp)
|
|||
|
||||
/* Remove from device chain. */
|
||||
mutex_lock(&raw3270_mutex);
|
||||
if (rp->clttydev)
|
||||
if (rp->clttydev && !IS_ERR(rp->clttydev))
|
||||
class_device_destroy(class3270,
|
||||
MKDEV(IBM_TTY3270_MAJOR, rp->minor));
|
||||
if (rp->cltubdev)
|
||||
if (rp->cltubdev && !IS_ERR(rp->cltubdev))
|
||||
class_device_destroy(class3270,
|
||||
MKDEV(IBM_FS3270_MAJOR, rp->minor));
|
||||
list_del_init(&rp->list);
|
||||
|
@ -1173,21 +1173,37 @@ static struct attribute_group raw3270_attr_group = {
|
|||
.attrs = raw3270_attrs,
|
||||
};
|
||||
|
||||
static void
|
||||
raw3270_create_attributes(struct raw3270 *rp)
|
||||
static int raw3270_create_attributes(struct raw3270 *rp)
|
||||
{
|
||||
//FIXME: check return code
|
||||
sysfs_create_group(&rp->cdev->dev.kobj, &raw3270_attr_group);
|
||||
rp->clttydev =
|
||||
class_device_create(class3270, NULL,
|
||||
MKDEV(IBM_TTY3270_MAJOR, rp->minor),
|
||||
&rp->cdev->dev, "tty%s",
|
||||
rp->cdev->dev.bus_id);
|
||||
rp->cltubdev =
|
||||
class_device_create(class3270, NULL,
|
||||
MKDEV(IBM_FS3270_MAJOR, rp->minor),
|
||||
&rp->cdev->dev, "tub%s",
|
||||
rp->cdev->dev.bus_id);
|
||||
int rc;
|
||||
|
||||
rc = sysfs_create_group(&rp->cdev->dev.kobj, &raw3270_attr_group);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
rp->clttydev = class_device_create(class3270, NULL,
|
||||
MKDEV(IBM_TTY3270_MAJOR, rp->minor),
|
||||
&rp->cdev->dev, "tty%s",
|
||||
rp->cdev->dev.bus_id);
|
||||
if (IS_ERR(rp->clttydev)) {
|
||||
rc = PTR_ERR(rp->clttydev);
|
||||
goto out_ttydev;
|
||||
}
|
||||
|
||||
rp->cltubdev = class_device_create(class3270, NULL,
|
||||
MKDEV(IBM_FS3270_MAJOR, rp->minor),
|
||||
&rp->cdev->dev, "tub%s",
|
||||
rp->cdev->dev.bus_id);
|
||||
if (!IS_ERR(rp->cltubdev))
|
||||
goto out;
|
||||
|
||||
rc = PTR_ERR(rp->cltubdev);
|
||||
class_device_destroy(class3270, MKDEV(IBM_TTY3270_MAJOR, rp->minor));
|
||||
|
||||
out_ttydev:
|
||||
sysfs_remove_group(&rp->cdev->dev.kobj, &raw3270_attr_group);
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1255,7 +1271,9 @@ raw3270_set_online (struct ccw_device *cdev)
|
|||
rc = raw3270_reset_device(rp);
|
||||
if (rc)
|
||||
goto failure;
|
||||
raw3270_create_attributes(rp);
|
||||
rc = raw3270_create_attributes(rp);
|
||||
if (rc)
|
||||
goto failure;
|
||||
set_bit(RAW3270_FLAGS_READY, &rp->flags);
|
||||
mutex_lock(&raw3270_mutex);
|
||||
list_for_each_entry(np, &raw3270_notifier, list)
|
||||
|
|
|
@ -76,14 +76,22 @@ struct tape_class_device *register_tape_dev(
|
|||
device,
|
||||
"%s", tcd->device_name
|
||||
);
|
||||
sysfs_create_link(
|
||||
rc = PTR_ERR(tcd->class_device);
|
||||
if (rc)
|
||||
goto fail_with_cdev;
|
||||
rc = sysfs_create_link(
|
||||
&device->kobj,
|
||||
&tcd->class_device->kobj,
|
||||
tcd->mode_name
|
||||
);
|
||||
if (rc)
|
||||
goto fail_with_class_device;
|
||||
|
||||
return tcd;
|
||||
|
||||
fail_with_class_device:
|
||||
class_device_destroy(tape_class, tcd->char_device->dev);
|
||||
|
||||
fail_with_cdev:
|
||||
cdev_del(tcd->char_device);
|
||||
|
||||
|
|
|
@ -543,20 +543,24 @@ int
|
|||
tape_generic_probe(struct ccw_device *cdev)
|
||||
{
|
||||
struct tape_device *device;
|
||||
int ret;
|
||||
|
||||
device = tape_alloc_device();
|
||||
if (IS_ERR(device))
|
||||
return -ENODEV;
|
||||
PRINT_INFO("tape device %s found\n", cdev->dev.bus_id);
|
||||
ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP);
|
||||
ret = sysfs_create_group(&cdev->dev.kobj, &tape_attr_group);
|
||||
if (ret) {
|
||||
tape_put_device(device);
|
||||
PRINT_ERR("probe failed for tape device %s\n", cdev->dev.bus_id);
|
||||
return ret;
|
||||
}
|
||||
cdev->dev.driver_data = device;
|
||||
cdev->handler = __tape_do_irq;
|
||||
device->cdev = cdev;
|
||||
device->cdev_id = busid_to_int(cdev->dev.bus_id);
|
||||
cdev->handler = __tape_do_irq;
|
||||
|
||||
ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP);
|
||||
sysfs_create_group(&cdev->dev.kobj, &tape_attr_group);
|
||||
|
||||
return 0;
|
||||
PRINT_INFO("tape device %s found\n", cdev->dev.bus_id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
|
@ -1068,6 +1068,7 @@ cmb_show_avg_sample_interval(struct device *dev, struct device_attribute *attr,
|
|||
if (count) {
|
||||
interval = cmb_data->last_update -
|
||||
cdev->private->cmb_start_time;
|
||||
interval = (interval * 1000) >> 12;
|
||||
interval /= count;
|
||||
} else
|
||||
interval = -1;
|
||||
|
|
|
@ -2686,9 +2686,17 @@ static struct attribute_group ctc_attr_group = {
|
|||
static int
|
||||
ctc_add_attributes(struct device *dev)
|
||||
{
|
||||
device_create_file(dev, &dev_attr_loglevel);
|
||||
device_create_file(dev, &dev_attr_stats);
|
||||
return 0;
|
||||
int rc;
|
||||
|
||||
rc = device_create_file(dev, &dev_attr_loglevel);
|
||||
if (rc)
|
||||
goto out;
|
||||
rc = device_create_file(dev, &dev_attr_stats);
|
||||
if (!rc)
|
||||
goto out;
|
||||
device_remove_file(dev, &dev_attr_loglevel);
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2901,7 +2909,12 @@ ctc_new_device(struct ccwgroup_device *cgdev)
|
|||
goto out;
|
||||
}
|
||||
|
||||
ctc_add_attributes(&cgdev->dev);
|
||||
if (ctc_add_attributes(&cgdev->dev)) {
|
||||
ctc_netdev_unregister(dev);
|
||||
dev->priv = NULL;
|
||||
ctc_free_netdevice(dev, 1);
|
||||
goto out;
|
||||
}
|
||||
|
||||
strlcpy(privptr->fsm->name, dev->name, sizeof (privptr->fsm->name));
|
||||
|
||||
|
|
|
@ -8451,10 +8451,11 @@ __qeth_reboot_event_card(struct device *dev, void *data)
|
|||
static int
|
||||
qeth_reboot_event(struct notifier_block *this, unsigned long event, void *ptr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
driver_for_each_device(&qeth_ccwgroup_driver.driver, NULL, NULL,
|
||||
__qeth_reboot_event_card);
|
||||
return NOTIFY_DONE;
|
||||
ret = driver_for_each_device(&qeth_ccwgroup_driver.driver, NULL, NULL,
|
||||
__qeth_reboot_event_card);
|
||||
return ret ? NOTIFY_BAD : NOTIFY_DONE;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -233,7 +233,7 @@ static void __init build_one_sbus(struct device_node *dp, int num_sbus)
|
|||
sbus->ofdev.node = dp;
|
||||
sbus->ofdev.dev.parent = NULL;
|
||||
sbus->ofdev.dev.bus = &sbus_bus_type;
|
||||
strcpy(sbus->ofdev.dev.bus_id, dp->path_component_name);
|
||||
sprintf(sbus->ofdev.dev.bus_id, "sbus%d", num_sbus);
|
||||
|
||||
if (of_device_register(&sbus->ofdev) != 0)
|
||||
printk(KERN_DEBUG "sbus: device registration error for %s!\n",
|
||||
|
|
|
@ -3451,12 +3451,12 @@ create_cmd (Scsi_Cmnd *cmd) {
|
|||
for (i = 0; cmd->use_sg ? (i < cmd->use_sg) : !i; cmd_datain += 4,
|
||||
cmd_dataout += 4, ++i) {
|
||||
u32 vbuf = cmd->use_sg
|
||||
? (u32)page_address(((struct scatterlist *)cmd->buffer)[i].page)+
|
||||
((struct scatterlist *)cmd->buffer)[i].offset
|
||||
? (u32)page_address(((struct scatterlist *)cmd->request_buffer)[i].page)+
|
||||
((struct scatterlist *)cmd->request_buffer)[i].offset
|
||||
: (u32)(cmd->request_buffer);
|
||||
u32 bbuf = virt_to_bus((void *)vbuf);
|
||||
u32 count = cmd->use_sg ?
|
||||
((struct scatterlist *)cmd->buffer)[i].length :
|
||||
((struct scatterlist *)cmd->request_buffer)[i].length :
|
||||
cmd->request_bufflen;
|
||||
|
||||
/*
|
||||
|
@ -5417,7 +5417,7 @@ insn_to_offset (Scsi_Cmnd *cmd, u32 *insn) {
|
|||
|
||||
if ((buffers = cmd->use_sg)) {
|
||||
for (offset = 0,
|
||||
segment = (struct scatterlist *) cmd->buffer;
|
||||
segment = (struct scatterlist *) cmd->request_buffer;
|
||||
buffers && !((found = ((ptr >= (char *)page_address(segment->page)+segment->offset) &&
|
||||
(ptr < ((char *)page_address(segment->page)+segment->offset+segment->length)))));
|
||||
--buffers, offset += segment->length, ++segment)
|
||||
|
|
|
@ -911,7 +911,7 @@ static void esp_get_dmabufs(struct NCR_ESP *esp, Scsi_Cmnd *sp)
|
|||
sp->SCp.ptr =
|
||||
(char *) virt_to_phys(sp->request_buffer);
|
||||
} else {
|
||||
sp->SCp.buffer = (struct scatterlist *) sp->buffer;
|
||||
sp->SCp.buffer = (struct scatterlist *) sp->request_buffer;
|
||||
sp->SCp.buffers_residual = sp->use_sg - 1;
|
||||
sp->SCp.this_residual = sp->SCp.buffer->length;
|
||||
if (esp->dma_mmu_get_scsi_sgl)
|
||||
|
|
|
@ -114,7 +114,7 @@ MODULE_DESCRIPTION("NCR Dual700 SCSI Driver");
|
|||
MODULE_LICENSE("GPL");
|
||||
module_param(NCR_D700, charp, 0);
|
||||
|
||||
static __u8 __initdata id_array[2*(MCA_MAX_SLOT_NR + 1)] =
|
||||
static __u8 __devinitdata id_array[2*(MCA_MAX_SLOT_NR + 1)] =
|
||||
{ [0 ... 2*(MCA_MAX_SLOT_NR + 1)-1] = 7 };
|
||||
|
||||
#ifdef MODULE
|
||||
|
@ -173,7 +173,7 @@ struct NCR_D700_private {
|
|||
char pad;
|
||||
};
|
||||
|
||||
static int
|
||||
static int __devinit
|
||||
NCR_D700_probe_one(struct NCR_D700_private *p, int siop, int irq,
|
||||
int slot, u32 region, int differential)
|
||||
{
|
||||
|
@ -243,7 +243,7 @@ NCR_D700_intr(int irq, void *data, struct pt_regs *regs)
|
|||
* essentially connectecd to the MCA bus independently, it is easier
|
||||
* to set them up as two separate host adapters, rather than one
|
||||
* adapter with two channels */
|
||||
static int
|
||||
static int __devinit
|
||||
NCR_D700_probe(struct device *dev)
|
||||
{
|
||||
struct NCR_D700_private *p;
|
||||
|
@ -329,7 +329,7 @@ NCR_D700_probe(struct device *dev)
|
|||
for (i = 0; i < 2; i++) {
|
||||
int err;
|
||||
|
||||
if ((err = NCR_D700_probe_one(p, i, slot, irq,
|
||||
if ((err = NCR_D700_probe_one(p, i, irq, slot,
|
||||
offset_addr + (0x80 * i),
|
||||
differential)) != 0)
|
||||
printk("D700: SIOP%d: probe failed, error = %d\n",
|
||||
|
@ -349,7 +349,7 @@ NCR_D700_probe(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
static void __devexit
|
||||
NCR_D700_remove_one(struct Scsi_Host *host)
|
||||
{
|
||||
scsi_remove_host(host);
|
||||
|
@ -359,7 +359,7 @@ NCR_D700_remove_one(struct Scsi_Host *host)
|
|||
release_region(host->base, 64);
|
||||
}
|
||||
|
||||
static int
|
||||
static int __devexit
|
||||
NCR_D700_remove(struct device *dev)
|
||||
{
|
||||
struct NCR_D700_private *p = dev_get_drvdata(dev);
|
||||
|
@ -380,7 +380,7 @@ static struct mca_driver NCR_D700_driver = {
|
|||
.name = "NCR_D700",
|
||||
.bus = &mca_bus_type,
|
||||
.probe = NCR_D700_probe,
|
||||
.remove = NCR_D700_remove,
|
||||
.remove = __devexit_p(NCR_D700_remove),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -551,6 +551,11 @@ struct aha152x_hostdata {
|
|||
struct aha152x_scdata {
|
||||
Scsi_Cmnd *next; /* next sc in queue */
|
||||
struct semaphore *sem; /* semaphore to block on */
|
||||
unsigned char cmd_len;
|
||||
unsigned char cmnd[MAX_COMMAND_SIZE];
|
||||
unsigned short use_sg;
|
||||
unsigned request_bufflen;
|
||||
void *request_buffer;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1006,11 +1011,20 @@ static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct semaphore *sem, int p
|
|||
return FAILED;
|
||||
}
|
||||
} else {
|
||||
struct aha152x_scdata *sc;
|
||||
|
||||
SCpnt->host_scribble = kmalloc(sizeof(struct aha152x_scdata), GFP_ATOMIC);
|
||||
if(SCpnt->host_scribble==0) {
|
||||
printk(ERR_LEAD "allocation failed\n", CMDINFO(SCpnt));
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
sc = SCDATA(SCpnt);
|
||||
memcpy(sc->cmnd, SCpnt->cmnd, sizeof(sc->cmnd));
|
||||
sc->request_buffer = SCpnt->request_buffer;
|
||||
sc->request_bufflen = SCpnt->request_bufflen;
|
||||
sc->use_sg = SCpnt->use_sg;
|
||||
sc->cmd_len = SCpnt->cmd_len;
|
||||
}
|
||||
|
||||
SCNEXT(SCpnt) = NULL;
|
||||
|
@ -1165,6 +1179,10 @@ static int aha152x_device_reset(Scsi_Cmnd * SCpnt)
|
|||
DECLARE_MUTEX_LOCKED(sem);
|
||||
struct timer_list timer;
|
||||
int ret, issued, disconnected;
|
||||
unsigned char old_cmd_len = SCpnt->cmd_len;
|
||||
unsigned short old_use_sg = SCpnt->use_sg;
|
||||
void *old_buffer = SCpnt->request_buffer;
|
||||
unsigned old_bufflen = SCpnt->request_bufflen;
|
||||
unsigned long flags;
|
||||
|
||||
#if defined(AHA152X_DEBUG)
|
||||
|
@ -1198,11 +1216,11 @@ static int aha152x_device_reset(Scsi_Cmnd * SCpnt)
|
|||
add_timer(&timer);
|
||||
down(&sem);
|
||||
del_timer(&timer);
|
||||
|
||||
SCpnt->cmd_len = SCpnt->old_cmd_len;
|
||||
SCpnt->use_sg = SCpnt->old_use_sg;
|
||||
SCpnt->request_buffer = SCpnt->buffer;
|
||||
SCpnt->request_bufflen = SCpnt->bufflen;
|
||||
|
||||
SCpnt->cmd_len = old_cmd_len;
|
||||
SCpnt->use_sg = old_use_sg;
|
||||
SCpnt->request_buffer = old_buffer;
|
||||
SCpnt->request_bufflen = old_bufflen;
|
||||
|
||||
DO_LOCK(flags);
|
||||
|
||||
|
@ -1565,6 +1583,9 @@ static void busfree_run(struct Scsi_Host *shpnt)
|
|||
#endif
|
||||
|
||||
if(DONE_SC->SCp.phase & check_condition) {
|
||||
struct scsi_cmnd *cmd = HOSTDATA(shpnt)->done_SC;
|
||||
struct aha152x_scdata *sc = SCDATA(cmd);
|
||||
|
||||
#if 0
|
||||
if(HOSTDATA(shpnt)->debug & debug_eh) {
|
||||
printk(ERR_LEAD "received sense: ", CMDINFO(DONE_SC));
|
||||
|
@ -1573,13 +1594,13 @@ static void busfree_run(struct Scsi_Host *shpnt)
|
|||
#endif
|
||||
|
||||
/* restore old command */
|
||||
memcpy((void *) DONE_SC->cmnd, (void *) DONE_SC->data_cmnd, sizeof(DONE_SC->data_cmnd));
|
||||
DONE_SC->request_buffer = DONE_SC->buffer;
|
||||
DONE_SC->request_bufflen = DONE_SC->bufflen;
|
||||
DONE_SC->use_sg = DONE_SC->old_use_sg;
|
||||
DONE_SC->cmd_len = DONE_SC->old_cmd_len;
|
||||
memcpy(cmd->cmnd, sc->cmnd, sizeof(sc->cmnd));
|
||||
cmd->request_buffer = sc->request_buffer;
|
||||
cmd->request_bufflen = sc->request_bufflen;
|
||||
cmd->use_sg = sc->use_sg;
|
||||
cmd->cmd_len = sc->cmd_len;
|
||||
|
||||
DONE_SC->SCp.Status = 0x02;
|
||||
cmd->SCp.Status = 0x02;
|
||||
|
||||
HOSTDATA(shpnt)->commands--;
|
||||
if (!HOSTDATA(shpnt)->commands)
|
||||
|
|
|
@ -7289,7 +7289,7 @@ ahd_reset_cmds_pending(struct ahd_softc *ahd)
|
|||
ahd->flags &= ~AHD_UPDATE_PEND_CMDS;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
ahd_done_with_status(struct ahd_softc *ahd, struct scb *scb, uint32_t status)
|
||||
{
|
||||
cam_status ostat;
|
||||
|
|
|
@ -242,25 +242,6 @@ ahd_print_path(struct ahd_softc *ahd, struct scb *scb)
|
|||
*/
|
||||
static uint32_t aic79xx_no_reset;
|
||||
|
||||
/*
|
||||
* Certain PCI motherboards will scan PCI devices from highest to lowest,
|
||||
* others scan from lowest to highest, and they tend to do all kinds of
|
||||
* strange things when they come into contact with PCI bridge chips. The
|
||||
* net result of all this is that the PCI card that is actually used to boot
|
||||
* the machine is very hard to detect. Most motherboards go from lowest
|
||||
* PCI slot number to highest, and the first SCSI controller found is the
|
||||
* one you boot from. The only exceptions to this are when a controller
|
||||
* has its BIOS disabled. So, we by default sort all of our SCSI controllers
|
||||
* from lowest PCI slot number to highest PCI slot number. We also force
|
||||
* all controllers with their BIOS disabled to the end of the list. This
|
||||
* works on *almost* all computers. Where it doesn't work, we have this
|
||||
* option. Setting this option to non-0 will reverse the order of the sort
|
||||
* to highest first, then lowest, but will still leave cards with their BIOS
|
||||
* disabled at the very end. That should fix everyone up unless there are
|
||||
* really strange cirumstances.
|
||||
*/
|
||||
static uint32_t aic79xx_reverse_scan;
|
||||
|
||||
/*
|
||||
* Should we force EXTENDED translation on a controller.
|
||||
* 0 == Use whatever is in the SEEPROM or default to off
|
||||
|
@ -350,7 +331,6 @@ MODULE_PARM_DESC(aic79xx,
|
|||
" periodically to prevent tag starvation.\n"
|
||||
" This may be required by some older disk\n"
|
||||
" or drives/RAID arrays.\n"
|
||||
" reverse_scan Sort PCI devices highest Bus/Slot to lowest\n"
|
||||
" tag_info:<tag_str> Set per-target tag depth\n"
|
||||
" global_tag_depth:<int> Global tag depth for all targets on all buses\n"
|
||||
" slewrate:<slewrate_list>Set the signal slew rate (0-15).\n"
|
||||
|
@ -1031,7 +1011,6 @@ aic79xx_setup(char *s)
|
|||
#ifdef AHD_DEBUG
|
||||
{ "debug", &ahd_debug },
|
||||
#endif
|
||||
{ "reverse_scan", &aic79xx_reverse_scan },
|
||||
{ "periodic_otag", &aic79xx_periodic_otag },
|
||||
{ "pci_parity", &aic79xx_pci_parity },
|
||||
{ "seltime", &aic79xx_seltime },
|
||||
|
|
|
@ -353,7 +353,6 @@ MODULE_PARM_DESC(aic7xxx,
|
|||
" periodically to prevent tag starvation.\n"
|
||||
" This may be required by some older disk\n"
|
||||
" drives or RAID arrays.\n"
|
||||
" reverse_scan Sort PCI devices highest Bus/Slot to lowest\n"
|
||||
" tag_info:<tag_str> Set per-target tag depth\n"
|
||||
" global_tag_depth:<int> Global tag depth for every target\n"
|
||||
" on every bus\n"
|
||||
|
|
|
@ -507,7 +507,7 @@ static __inline__ void initialize_SCp(Scsi_Cmnd *cmd)
|
|||
*/
|
||||
|
||||
if (cmd->use_sg) {
|
||||
cmd->SCp.buffer = (struct scatterlist *) cmd->buffer;
|
||||
cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer;
|
||||
cmd->SCp.buffers_residual = cmd->use_sg - 1;
|
||||
cmd->SCp.ptr = (char *)page_address(cmd->SCp.buffer->page)+
|
||||
cmd->SCp.buffer->offset;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* Additions for SCSI 3+ (SPC-3 T10/1416-D Rev 07 3 May 2002)
|
||||
* by D. Gilbert and aeb (20020609)
|
||||
* Additions for SPC-3 T10/1416-D Rev 21 22 Sept 2004, D. Gilbert 20041025
|
||||
* Update to SPC-4 T10/1713-D Rev 5a, 14 June 2006, D. Gilbert 20060702
|
||||
*/
|
||||
|
||||
#include <linux/blkdev.h>
|
||||
|
@ -36,55 +37,56 @@ static const char * cdb_byte0_names[] = {
|
|||
/* 00-03 */ "Test Unit Ready", "Rezero Unit/Rewind", NULL, "Request Sense",
|
||||
/* 04-07 */ "Format Unit/Medium", "Read Block Limits", NULL,
|
||||
"Reasssign Blocks",
|
||||
/* 08-0d */ "Read (6)", NULL, "Write (6)", "Seek (6)", NULL, NULL,
|
||||
/* 08-0d */ "Read(6)", NULL, "Write(6)", "Seek(6)", NULL, NULL,
|
||||
/* 0e-12 */ NULL, "Read Reverse", "Write Filemarks", "Space", "Inquiry",
|
||||
/* 13-16 */ "Verify (6)", "Recover Buffered Data", "Mode Select (6)",
|
||||
"Reserve (6)",
|
||||
/* 17-1a */ "Release (6)", "Copy", "Erase", "Mode Sense (6)",
|
||||
/* 13-16 */ "Verify(6)", "Recover Buffered Data", "Mode Select(6)",
|
||||
"Reserve(6)",
|
||||
/* 17-1a */ "Release(6)", "Copy", "Erase", "Mode Sense(6)",
|
||||
/* 1b-1d */ "Start/Stop Unit", "Receive Diagnostic", "Send Diagnostic",
|
||||
/* 1e-1f */ "Prevent/Allow Medium Removal", NULL,
|
||||
/* 20-22 */ NULL, NULL, NULL,
|
||||
/* 23-28 */ "Read Format Capacities", "Set Window",
|
||||
"Read Capacity (10)", NULL, NULL, "Read (10)",
|
||||
/* 29-2d */ "Read Generation", "Write (10)", "Seek (10)", "Erase (10)",
|
||||
"Read updated block",
|
||||
/* 2e-31 */ "Write Verify (10)", "Verify (10)", "Search High", "Search Equal",
|
||||
"Read Capacity(10)", NULL, NULL, "Read(10)",
|
||||
/* 29-2d */ "Read Generation", "Write(10)", "Seek(10)", "Erase(10)",
|
||||
"Read updated block",
|
||||
/* 2e-31 */ "Write Verify(10)", "Verify(10)", "Search High", "Search Equal",
|
||||
/* 32-34 */ "Search Low", "Set Limits", "Prefetch/Read Position",
|
||||
/* 35-37 */ "Synchronize Cache (10)", "Lock/Unlock Cache (10)",
|
||||
/* 35-37 */ "Synchronize Cache(10)", "Lock/Unlock Cache(10)",
|
||||
"Read Defect Data(10)",
|
||||
/* 38-3c */ "Medium Scan", "Compare", "Copy Verify", "Write Buffer",
|
||||
"Read Buffer",
|
||||
/* 3d-3f */ "Update Block", "Read Long (10)", "Write Long (10)",
|
||||
/* 40-41 */ "Change Definition", "Write Same (10)",
|
||||
/* 3d-3f */ "Update Block", "Read Long(10)", "Write Long(10)",
|
||||
/* 40-41 */ "Change Definition", "Write Same(10)",
|
||||
/* 42-48 */ "Read sub-channel", "Read TOC/PMA/ATIP", "Read density support",
|
||||
"Play audio (10)", "Get configuration", "Play audio msf",
|
||||
"Play audio(10)", "Get configuration", "Play audio msf",
|
||||
"Play audio track/index",
|
||||
/* 49-4f */ "Play track relative (10)", "Get event status notification",
|
||||
/* 49-4f */ "Play track relative(10)", "Get event status notification",
|
||||
"Pause/resume", "Log Select", "Log Sense", "Stop play/scan",
|
||||
NULL,
|
||||
/* 50-55 */ "Xdwrite", "Xpwrite, Read disk info", "Xdread, Read track info",
|
||||
"Reserve track", "Send OPC info", "Mode Select (10)",
|
||||
/* 56-5b */ "Reserve (10)", "Release (10)", "Repair track", "Read master cue",
|
||||
"Mode Sense (10)", "Close track/session",
|
||||
"Reserve track", "Send OPC info", "Mode Select(10)",
|
||||
/* 56-5b */ "Reserve(10)", "Release(10)", "Repair track", "Read master cue",
|
||||
"Mode Sense(10)", "Close track/session",
|
||||
/* 5c-5f */ "Read buffer capacity", "Send cue sheet", "Persistent reserve in",
|
||||
"Persistent reserve out",
|
||||
/* 60-67 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/* 68-6f */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/* 70-77 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/* 78-7f */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, "Variable length",
|
||||
/* 80-84 */ "Xdwrite (16)", "Rebuild (16)", "Regenerate (16)", "Extended copy",
|
||||
/* 80-84 */ "Xdwrite(16)", "Rebuild(16)", "Regenerate(16)", "Extended copy",
|
||||
"Receive copy results",
|
||||
/* 85-89 */ "Memory Export In (16)", "Access control in", "Access control out",
|
||||
"Read (16)", "Memory Export Out (16)",
|
||||
/* 8a-8f */ "Write (16)", NULL, "Read attributes", "Write attributes",
|
||||
"Write and verify (16)", "Verify (16)",
|
||||
/* 90-94 */ "Pre-fetch (16)", "Synchronize cache (16)",
|
||||
"Lock/unlock cache (16)", "Write same (16)", NULL,
|
||||
/* 85-89 */ "ATA command pass through(16)", "Access control in",
|
||||
"Access control out", "Read(16)", "Memory Export Out(16)",
|
||||
/* 8a-8f */ "Write(16)", NULL, "Read attributes", "Write attributes",
|
||||
"Write and verify(16)", "Verify(16)",
|
||||
/* 90-94 */ "Pre-fetch(16)", "Synchronize cache(16)",
|
||||
"Lock/unlock cache(16)", "Write same(16)", NULL,
|
||||
/* 95-99 */ NULL, NULL, NULL, NULL, NULL,
|
||||
/* 9a-9f */ NULL, NULL, NULL, NULL, "Service action in (16)",
|
||||
"Service action out (16)",
|
||||
/* a0-a5 */ "Report luns", "Blank", "Send event", "Maintenance in",
|
||||
"Maintenance out", "Move medium/play audio(12)",
|
||||
/* 9a-9f */ NULL, NULL, NULL, NULL, "Service action in(16)",
|
||||
"Service action out(16)",
|
||||
/* a0-a5 */ "Report luns", "ATA command pass through(12)/Blank",
|
||||
"Security protocol in", "Maintenance in", "Maintenance out",
|
||||
"Move medium/play audio(12)",
|
||||
/* a6-a9 */ "Exchange medium", "Move medium attached", "Read(12)",
|
||||
"Play track relative(12)",
|
||||
/* aa-ae */ "Write(12)", NULL, "Erase(12), Get Performance",
|
||||
|
@ -92,12 +94,12 @@ static const char * cdb_byte0_names[] = {
|
|||
/* af-b1 */ "Verify(12)", "Search data high(12)", "Search data equal(12)",
|
||||
/* b2-b4 */ "Search data low(12)", "Set limits(12)",
|
||||
"Read element status attached",
|
||||
/* b5-b6 */ "Request volume element address", "Send volume tag, set streaming",
|
||||
/* b5-b6 */ "Security protocol out", "Send volume tag, set streaming",
|
||||
/* b7-b9 */ "Read defect data(12)", "Read element status", "Read CD msf",
|
||||
/* ba-bc */ "Redundancy group (in), Scan",
|
||||
"Redundancy group (out), Set cd-rom speed", "Spare in, Play cd",
|
||||
/* bd-bf */ "Spare out, Mechanism status", "Volume set in, Read cd",
|
||||
"Volume set out, Send DVD structure",
|
||||
"Redundancy group (out), Set cd-rom speed", "Spare (in), Play cd",
|
||||
/* bd-bf */ "Spare (out), Mechanism status", "Volume set (in), Read cd",
|
||||
"Volume set (out), Send DVD structure",
|
||||
};
|
||||
|
||||
struct value_name_pair {
|
||||
|
@ -112,6 +114,7 @@ static const struct value_name_pair maint_in_arr[] = {
|
|||
{0xc, "Report supported operation codes"},
|
||||
{0xd, "Report supported task management functions"},
|
||||
{0xe, "Report priority"},
|
||||
{0xf, "Report timestamp"},
|
||||
};
|
||||
#define MAINT_IN_SZ ARRAY_SIZE(maint_in_arr)
|
||||
|
||||
|
@ -120,6 +123,7 @@ static const struct value_name_pair maint_out_arr[] = {
|
|||
{0xa, "Set target port groups"},
|
||||
{0xb, "Change aliases"},
|
||||
{0xe, "Set priority"},
|
||||
{0xe, "Set timestamp"},
|
||||
};
|
||||
#define MAINT_OUT_SZ ARRAY_SIZE(maint_out_arr)
|
||||
|
||||
|
@ -427,6 +431,7 @@ static struct error_info additional[] =
|
|||
{0x001A, "Rewind operation in progress"},
|
||||
{0x001B, "Set capacity operation in progress"},
|
||||
{0x001C, "Verify operation in progress"},
|
||||
{0x001D, "ATA pass through information available"},
|
||||
|
||||
{0x0100, "No index/sector signal"},
|
||||
|
||||
|
@ -438,7 +443,7 @@ static struct error_info additional[] =
|
|||
|
||||
{0x0400, "Logical unit not ready, cause not reportable"},
|
||||
{0x0401, "Logical unit is in process of becoming ready"},
|
||||
{0x0402, "Logical unit not ready, initializing cmd. required"},
|
||||
{0x0402, "Logical unit not ready, initializing command required"},
|
||||
{0x0403, "Logical unit not ready, manual intervention required"},
|
||||
{0x0404, "Logical unit not ready, format in progress"},
|
||||
{0x0405, "Logical unit not ready, rebuild in progress"},
|
||||
|
@ -478,6 +483,9 @@ static struct error_info additional[] =
|
|||
{0x0B00, "Warning"},
|
||||
{0x0B01, "Warning - specified temperature exceeded"},
|
||||
{0x0B02, "Warning - enclosure degraded"},
|
||||
{0x0B03, "Warning - background self-test failed"},
|
||||
{0x0B04, "Warning - background pre-scan detected medium error"},
|
||||
{0x0B05, "Warning - background medium scan detected medium error"},
|
||||
|
||||
{0x0C00, "Write error"},
|
||||
{0x0C01, "Write error - recovered with auto reallocation"},
|
||||
|
@ -493,6 +501,7 @@ static struct error_info additional[] =
|
|||
{0x0C0B, "Auxiliary memory write error"},
|
||||
{0x0C0C, "Write error - unexpected unsolicited data"},
|
||||
{0x0C0D, "Write error - not enough unsolicited data"},
|
||||
{0x0C0F, "Defects in error window"},
|
||||
|
||||
{0x0D00, "Error detected by third party temporary initiator"},
|
||||
{0x0D01, "Third party device failure"},
|
||||
|
@ -504,11 +513,12 @@ static struct error_info additional[] =
|
|||
{0x0E00, "Invalid information unit"},
|
||||
{0x0E01, "Information unit too short"},
|
||||
{0x0E02, "Information unit too long"},
|
||||
{0x0E03, "Invalid field in command information unit"},
|
||||
|
||||
{0x1000, "Id CRC or ECC error"},
|
||||
{0x1001, "Data block guard check failed"},
|
||||
{0x1002, "Data block application tag check failed"},
|
||||
{0x1003, "Data block reference tag check failed"},
|
||||
{0x1001, "Logical block guard check failed"},
|
||||
{0x1002, "Logical block application tag check failed"},
|
||||
{0x1003, "Logical block reference tag check failed"},
|
||||
|
||||
{0x1100, "Unrecovered read error"},
|
||||
{0x1101, "Read retries exhausted"},
|
||||
|
@ -530,6 +540,7 @@ static struct error_info additional[] =
|
|||
{0x1111, "Read error - loss of streaming"},
|
||||
{0x1112, "Auxiliary memory read error"},
|
||||
{0x1113, "Read error - failed retransmission request"},
|
||||
{0x1114, "Read error - lba marked bad by application client"},
|
||||
|
||||
{0x1200, "Address mark not found for id field"},
|
||||
|
||||
|
@ -610,11 +621,14 @@ static struct error_info additional[] =
|
|||
{0x2100, "Logical block address out of range"},
|
||||
{0x2101, "Invalid element address"},
|
||||
{0x2102, "Invalid address for write"},
|
||||
{0x2103, "Invalid write crossing layer jump"},
|
||||
|
||||
{0x2200, "Illegal function (use 20 00, 24 00, or 26 00)"},
|
||||
|
||||
{0x2400, "Invalid field in cdb"},
|
||||
{0x2401, "CDB decryption error"},
|
||||
{0x2402, "Obsolete"},
|
||||
{0x2403, "Obsolete"},
|
||||
{0x2404, "Security audit value frozen"},
|
||||
{0x2405, "Security working key frozen"},
|
||||
{0x2406, "Nonce not unique"},
|
||||
|
@ -637,7 +651,10 @@ static struct error_info additional[] =
|
|||
{0x260C, "Invalid operation for copy source or destination"},
|
||||
{0x260D, "Copy segment granularity violation"},
|
||||
{0x260E, "Invalid parameter while port is enabled"},
|
||||
{0x260F, "Invalid data-out buffer integrity"},
|
||||
{0x260F, "Invalid data-out buffer integrity check value"},
|
||||
{0x2610, "Data decryption key fail limit reached"},
|
||||
{0x2611, "Incomplete key-associated data set"},
|
||||
{0x2612, "Vendor specific key reference not found"},
|
||||
|
||||
{0x2700, "Write protected"},
|
||||
{0x2701, "Hardware write protected"},
|
||||
|
@ -649,6 +666,7 @@ static struct error_info additional[] =
|
|||
|
||||
{0x2800, "Not ready to ready change, medium may have changed"},
|
||||
{0x2801, "Import or export element accessed"},
|
||||
{0x2802, "Format-layer may have changed"},
|
||||
|
||||
{0x2900, "Power on, reset, or bus device reset occurred"},
|
||||
{0x2901, "Power on occurred"},
|
||||
|
@ -669,6 +687,11 @@ static struct error_info additional[] =
|
|||
{0x2A07, "Implicit asymmetric access state transition failed"},
|
||||
{0x2A08, "Priority changed"},
|
||||
{0x2A09, "Capacity data has changed"},
|
||||
{0x2A10, "Timestamp changed"},
|
||||
{0x2A11, "Data encryption parameters changed by another i_t nexus"},
|
||||
{0x2A12, "Data encryption parameters changed by vendor specific "
|
||||
"event"},
|
||||
{0x2A13, "Data encryption key instance counter has changed"},
|
||||
|
||||
{0x2B00, "Copy cannot execute since host cannot disconnect"},
|
||||
|
||||
|
@ -690,6 +713,7 @@ static struct error_info additional[] =
|
|||
{0x2E00, "Insufficient time for operation"},
|
||||
|
||||
{0x2F00, "Commands cleared by another initiator"},
|
||||
{0x2F01, "Commands cleared by power loss notification"},
|
||||
|
||||
{0x3000, "Incompatible medium installed"},
|
||||
{0x3001, "Cannot read medium - unknown format"},
|
||||
|
@ -702,7 +726,8 @@ static struct error_info additional[] =
|
|||
{0x3008, "Cannot write - application code mismatch"},
|
||||
{0x3009, "Current session not fixated for append"},
|
||||
{0x300A, "Cleaning request rejected"},
|
||||
{0x300C, "WORM medium, overwrite attempted"},
|
||||
{0x300C, "WORM medium - overwrite attempted"},
|
||||
{0x300D, "WORM medium - integrity check"},
|
||||
{0x3010, "Medium not formatted"},
|
||||
|
||||
{0x3100, "Medium format corrupted"},
|
||||
|
@ -790,6 +815,9 @@ static struct error_info additional[] =
|
|||
{0x3F0F, "Echo buffer overwritten"},
|
||||
{0x3F10, "Medium loadable"},
|
||||
{0x3F11, "Medium auxiliary memory accessible"},
|
||||
{0x3F12, "iSCSI IP address added"},
|
||||
{0x3F13, "iSCSI IP address removed"},
|
||||
{0x3F14, "iSCSI IP address changed"},
|
||||
/*
|
||||
* {0x40NN, "Ram failure"},
|
||||
* {0x40NN, "Diagnostic failure on component nn"},
|
||||
|
@ -799,6 +827,7 @@ static struct error_info additional[] =
|
|||
{0x4300, "Message error"},
|
||||
|
||||
{0x4400, "Internal target failure"},
|
||||
{0x4471, "ATA device failed set features"},
|
||||
|
||||
{0x4500, "Select or reselect failure"},
|
||||
|
||||
|
@ -807,9 +836,10 @@ static struct error_info additional[] =
|
|||
{0x4700, "Scsi parity error"},
|
||||
{0x4701, "Data phase CRC error detected"},
|
||||
{0x4702, "Scsi parity error detected during st data phase"},
|
||||
{0x4703, "Information unit CRC error detected"},
|
||||
{0x4703, "Information unit iuCRC error detected"},
|
||||
{0x4704, "Asynchronous information protection error detected"},
|
||||
{0x4705, "Protocol service CRC error"},
|
||||
{0x4706, "Phy test function in progress"},
|
||||
{0x477f, "Some commands cleared by iSCSI Protocol event"},
|
||||
|
||||
{0x4800, "Initiator detected error message received"},
|
||||
|
@ -844,6 +874,8 @@ static struct error_info additional[] =
|
|||
{0x5300, "Media load or eject failed"},
|
||||
{0x5301, "Unload tape failure"},
|
||||
{0x5302, "Medium removal prevented"},
|
||||
{0x5303, "Medium removal prevented by data transfer element"},
|
||||
{0x5304, "Medium thread or unthread failure"},
|
||||
|
||||
{0x5400, "Scsi to host system interface failure"},
|
||||
|
||||
|
@ -855,6 +887,7 @@ static struct error_info additional[] =
|
|||
{0x5505, "Insufficient access control resources"},
|
||||
{0x5506, "Auxiliary memory out of space"},
|
||||
{0x5507, "Quota error"},
|
||||
{0x5508, "Maximum number of supplemental decryption keys exceeded"},
|
||||
|
||||
{0x5700, "Unable to recover table-of-contents"},
|
||||
|
||||
|
@ -1004,6 +1037,7 @@ static struct error_info additional[] =
|
|||
{0x6708, "Assign failure occurred"},
|
||||
{0x6709, "Multiply assigned logical unit"},
|
||||
{0x670A, "Set target port groups command failed"},
|
||||
{0x670B, "ATA device feature not enabled"},
|
||||
|
||||
{0x6800, "Logical unit not configured"},
|
||||
|
||||
|
@ -1030,6 +1064,8 @@ static struct error_info additional[] =
|
|||
{0x6F03, "Read of scrambled sector without authentication"},
|
||||
{0x6F04, "Media region code is mismatched to logical unit region"},
|
||||
{0x6F05, "Drive region must be permanent/region reset count error"},
|
||||
{0x6F06, "Insufficient block count for binding nonce recording"},
|
||||
{0x6F07, "Conflict in binding nonce recording"},
|
||||
/*
|
||||
* {0x70NN, "Decompression exception short algorithm id of nn"},
|
||||
*/
|
||||
|
@ -1041,6 +1077,8 @@ static struct error_info additional[] =
|
|||
{0x7203, "Session fixation error - incomplete track in session"},
|
||||
{0x7204, "Empty or partially written reserved track"},
|
||||
{0x7205, "No more track reservations allowed"},
|
||||
{0x7206, "RMZ extension is not allowed"},
|
||||
{0x7207, "No more test zone extensions are allowed"},
|
||||
|
||||
{0x7300, "Cd control error"},
|
||||
{0x7301, "Power calibration area almost full"},
|
||||
|
@ -1049,6 +1087,18 @@ static struct error_info additional[] =
|
|||
{0x7304, "Program memory area update failure"},
|
||||
{0x7305, "Program memory area is full"},
|
||||
{0x7306, "RMA/PMA is almost full"},
|
||||
{0x7310, "Current power calibration area almost full"},
|
||||
{0x7311, "Current power calibration area is full"},
|
||||
{0x7317, "RDZ is full"},
|
||||
|
||||
{0x7400, "Security error"},
|
||||
{0x7401, "Unable to decrypt data"},
|
||||
{0x7402, "Unencrypted data encountered while decrypting"},
|
||||
{0x7403, "Incorrect data encryption key"},
|
||||
{0x7404, "Cryptographic integrity validation failed"},
|
||||
{0x7405, "Error decrypting data"},
|
||||
{0x7471, "Logical unit access not authorized"},
|
||||
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
|
|
|
@ -1397,7 +1397,7 @@ static void esp_get_dmabufs(struct esp *esp, struct scsi_cmnd *sp)
|
|||
sp->SCp.ptr = NULL;
|
||||
}
|
||||
} else {
|
||||
sp->SCp.buffer = (struct scatterlist *) sp->buffer;
|
||||
sp->SCp.buffer = (struct scatterlist *) sp->request_buffer;
|
||||
sp->SCp.buffers_residual = sbus_map_sg(esp->sdev,
|
||||
sp->SCp.buffer,
|
||||
sp->use_sg,
|
||||
|
@ -1410,7 +1410,7 @@ static void esp_get_dmabufs(struct esp *esp, struct scsi_cmnd *sp)
|
|||
static void esp_release_dmabufs(struct esp *esp, struct scsi_cmnd *sp)
|
||||
{
|
||||
if (sp->use_sg) {
|
||||
sbus_unmap_sg(esp->sdev, sp->buffer, sp->use_sg,
|
||||
sbus_unmap_sg(esp->sdev, sp->request_buffer, sp->use_sg,
|
||||
sp->sc_data_direction);
|
||||
} else if (sp->request_bufflen) {
|
||||
sbus_unmap_single(esp->sdev,
|
||||
|
|
|
@ -81,7 +81,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
|
|||
int rc;
|
||||
|
||||
single_host_data = hostdata;
|
||||
rc = viopath_open(viopath_hostLp, viomajorsubtype_scsi, 0);
|
||||
rc = viopath_open(viopath_hostLp, viomajorsubtype_scsi, max_requests);
|
||||
if (rc < 0) {
|
||||
printk("viopath_open failed with rc %d in open_event_path\n",
|
||||
rc);
|
||||
|
|
|
@ -238,6 +238,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
|
|||
if (rc == 2) {
|
||||
/* Adapter is good, but other end is not ready */
|
||||
printk(KERN_WARNING "ibmvscsi: Partner adapter not ready\n");
|
||||
retrc = 0;
|
||||
} else if (rc != 0) {
|
||||
printk(KERN_WARNING "ibmvscsi: Error %d opening adapter\n", rc);
|
||||
goto reg_crq_failed;
|
||||
|
|
|
@ -257,7 +257,7 @@ static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, struct scsi_cmnd *sp)
|
|||
static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, struct scsi_cmnd *sp)
|
||||
{
|
||||
int sz = sp->use_sg - 1;
|
||||
struct scatterlist *sg = (struct scatterlist *)sp->buffer;
|
||||
struct scatterlist *sg = (struct scatterlist *)sp->request_buffer;
|
||||
|
||||
while(sz >= 0) {
|
||||
vdma_free(sg[sz].dma_address);
|
||||
|
|
|
@ -21,10 +21,12 @@
|
|||
|
||||
struct lpfc_sli2_slim;
|
||||
|
||||
#define LPFC_MAX_TARGET 256 /* max targets supported */
|
||||
#define LPFC_MAX_DISC_THREADS 64 /* max outstanding discovery els req */
|
||||
#define LPFC_MAX_NS_RETRY 3 /* max NameServer retries */
|
||||
|
||||
#define LPFC_MAX_TARGET 256 /* max number of targets supported */
|
||||
#define LPFC_MAX_DISC_THREADS 64 /* max outstanding discovery els
|
||||
requests */
|
||||
#define LPFC_MAX_NS_RETRY 3 /* Number of retry attempts to contact
|
||||
the NameServer before giving up. */
|
||||
#define LPFC_DFT_HBA_Q_DEPTH 2048 /* max cmds per hba */
|
||||
#define LPFC_LC_HBA_Q_DEPTH 1024 /* max cmds per low cost hba */
|
||||
#define LPFC_LP101_HBA_Q_DEPTH 128 /* max cmds per low cost hba */
|
||||
|
@ -41,7 +43,6 @@ struct lpfc_sli2_slim;
|
|||
(( (u64)(high)<<16 ) << 16)|( (u64)(low))))
|
||||
/* Provide maximum configuration definitions. */
|
||||
#define LPFC_DRVR_TIMEOUT 16 /* driver iocb timeout value in sec */
|
||||
#define MAX_FCP_TARGET 256 /* max num of FCP targets supported */
|
||||
#define FC_MAX_ADPTMSG 64
|
||||
|
||||
#define MAX_HBAEVT 32
|
||||
|
|
|
@ -219,9 +219,19 @@ lpfc_issue_lip(struct Scsi_Host *host)
|
|||
return -ENOMEM;
|
||||
|
||||
memset((void *)pmboxq, 0, sizeof (LPFC_MBOXQ_t));
|
||||
lpfc_init_link(phba, pmboxq, phba->cfg_topology, phba->cfg_link_speed);
|
||||
pmboxq->mb.mbxCommand = MBX_DOWN_LINK;
|
||||
pmboxq->mb.mbxOwner = OWN_HOST;
|
||||
|
||||
mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
|
||||
|
||||
if ((mbxstatus == MBX_SUCCESS) && (pmboxq->mb.mbxStatus == 0)) {
|
||||
memset((void *)pmboxq, 0, sizeof (LPFC_MBOXQ_t));
|
||||
lpfc_init_link(phba, pmboxq, phba->cfg_topology,
|
||||
phba->cfg_link_speed);
|
||||
mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq,
|
||||
phba->fc_ratov * 2);
|
||||
}
|
||||
|
||||
if (mbxstatus == MBX_TIMEOUT)
|
||||
pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
|
||||
else
|
||||
|
@ -233,6 +243,47 @@ lpfc_issue_lip(struct Scsi_Host *host)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
lpfc_selective_reset(struct lpfc_hba *phba)
|
||||
{
|
||||
struct completion online_compl;
|
||||
int status = 0;
|
||||
|
||||
init_completion(&online_compl);
|
||||
lpfc_workq_post_event(phba, &status, &online_compl,
|
||||
LPFC_EVT_OFFLINE);
|
||||
wait_for_completion(&online_compl);
|
||||
|
||||
if (status != 0)
|
||||
return -EIO;
|
||||
|
||||
init_completion(&online_compl);
|
||||
lpfc_workq_post_event(phba, &status, &online_compl,
|
||||
LPFC_EVT_ONLINE);
|
||||
wait_for_completion(&online_compl);
|
||||
|
||||
if (status != 0)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
lpfc_issue_reset(struct class_device *cdev, const char *buf, size_t count)
|
||||
{
|
||||
struct Scsi_Host *host = class_to_shost(cdev);
|
||||
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
|
||||
int status = -EINVAL;
|
||||
|
||||
if (strncmp(buf, "selective", sizeof("selective") - 1) == 0)
|
||||
status = lpfc_selective_reset(phba);
|
||||
|
||||
if (status == 0)
|
||||
return strlen(buf);
|
||||
else
|
||||
return status;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
lpfc_nport_evt_cnt_show(struct class_device *cdev, char *buf)
|
||||
{
|
||||
|
@ -241,45 +292,6 @@ lpfc_nport_evt_cnt_show(struct class_device *cdev, char *buf)
|
|||
return snprintf(buf, PAGE_SIZE, "%d\n", phba->nport_event_cnt);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
lpfc_board_online_show(struct class_device *cdev, char *buf)
|
||||
{
|
||||
struct Scsi_Host *host = class_to_shost(cdev);
|
||||
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
|
||||
|
||||
if (phba->fc_flag & FC_OFFLINE_MODE)
|
||||
return snprintf(buf, PAGE_SIZE, "0\n");
|
||||
else
|
||||
return snprintf(buf, PAGE_SIZE, "1\n");
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
lpfc_board_online_store(struct class_device *cdev, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct Scsi_Host *host = class_to_shost(cdev);
|
||||
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
|
||||
struct completion online_compl;
|
||||
int val=0, status=0;
|
||||
|
||||
if (sscanf(buf, "%d", &val) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
init_completion(&online_compl);
|
||||
|
||||
if (val)
|
||||
lpfc_workq_post_event(phba, &status, &online_compl,
|
||||
LPFC_EVT_ONLINE);
|
||||
else
|
||||
lpfc_workq_post_event(phba, &status, &online_compl,
|
||||
LPFC_EVT_OFFLINE);
|
||||
wait_for_completion(&online_compl);
|
||||
if (!status)
|
||||
return strlen(buf);
|
||||
else
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
lpfc_board_mode_show(struct class_device *cdev, char *buf)
|
||||
{
|
||||
|
@ -532,10 +544,9 @@ static CLASS_DEVICE_ATTR(lpfc_drvr_version, S_IRUGO, lpfc_drvr_version_show,
|
|||
NULL);
|
||||
static CLASS_DEVICE_ATTR(management_version, S_IRUGO, management_version_show,
|
||||
NULL);
|
||||
static CLASS_DEVICE_ATTR(board_online, S_IRUGO | S_IWUSR,
|
||||
lpfc_board_online_show, lpfc_board_online_store);
|
||||
static CLASS_DEVICE_ATTR(board_mode, S_IRUGO | S_IWUSR,
|
||||
lpfc_board_mode_show, lpfc_board_mode_store);
|
||||
static CLASS_DEVICE_ATTR(issue_reset, S_IWUSR, NULL, lpfc_issue_reset);
|
||||
|
||||
static int lpfc_poll = 0;
|
||||
module_param(lpfc_poll, int, 0);
|
||||
|
@ -695,12 +706,12 @@ LPFC_ATTR(discovery_threads, 32, 1, 64, "Maximum number of ELS commands "
|
|||
"during discovery");
|
||||
|
||||
/*
|
||||
# lpfc_max_luns: maximum number of LUNs per target driver will support
|
||||
# Value range is [1,32768]. Default value is 256.
|
||||
# NOTE: The SCSI layer will scan each target for this many luns
|
||||
# lpfc_max_luns: maximum allowed LUN.
|
||||
# Value range is [0,65535]. Default value is 255.
|
||||
# NOTE: The SCSI layer might probe all allowed LUN on some old targets.
|
||||
*/
|
||||
LPFC_ATTR_R(max_luns, 256, 1, 32768,
|
||||
"Maximum number of LUNs per target driver will support");
|
||||
LPFC_ATTR_R(max_luns, 255, 0, 65535,
|
||||
"Maximum allowed LUN");
|
||||
|
||||
/*
|
||||
# lpfc_poll_tmo: .Milliseconds driver will wait between polling FCP ring.
|
||||
|
@ -739,8 +750,8 @@ struct class_device_attribute *lpfc_host_attrs[] = {
|
|||
&class_device_attr_lpfc_max_luns,
|
||||
&class_device_attr_nport_evt_cnt,
|
||||
&class_device_attr_management_version,
|
||||
&class_device_attr_board_online,
|
||||
&class_device_attr_board_mode,
|
||||
&class_device_attr_issue_reset,
|
||||
&class_device_attr_lpfc_poll,
|
||||
&class_device_attr_lpfc_poll_tmo,
|
||||
NULL,
|
||||
|
|
|
@ -147,6 +147,7 @@ int lpfc_sli_hba_setup(struct lpfc_hba *);
|
|||
int lpfc_sli_hba_down(struct lpfc_hba *);
|
||||
int lpfc_sli_issue_mbox(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);
|
||||
int lpfc_sli_handle_mb_event(struct lpfc_hba *);
|
||||
int lpfc_sli_flush_mbox_queue(struct lpfc_hba *);
|
||||
int lpfc_sli_handle_slow_ring_event(struct lpfc_hba *,
|
||||
struct lpfc_sli_ring *, uint32_t);
|
||||
void lpfc_sli_def_mbox_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
|
|
|
@ -648,33 +648,32 @@ lpfc_more_plogi(struct lpfc_hba * phba)
|
|||
}
|
||||
|
||||
static struct lpfc_nodelist *
|
||||
lpfc_plogi_confirm_nport(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
|
||||
lpfc_plogi_confirm_nport(struct lpfc_hba * phba, struct lpfc_dmabuf *prsp,
|
||||
struct lpfc_nodelist *ndlp)
|
||||
{
|
||||
struct lpfc_nodelist *new_ndlp;
|
||||
struct lpfc_dmabuf *pcmd, *prsp;
|
||||
uint32_t *lp;
|
||||
struct serv_parm *sp;
|
||||
uint8_t name[sizeof (struct lpfc_name)];
|
||||
uint32_t rc;
|
||||
|
||||
pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
|
||||
prsp = (struct lpfc_dmabuf *) pcmd->list.next;
|
||||
lp = (uint32_t *) prsp->virt;
|
||||
sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
|
||||
memset(name, 0, sizeof (struct lpfc_name));
|
||||
|
||||
/* Now we to find out if the NPort we are logging into, matches the WWPN
|
||||
* we have for that ndlp. If not, we have some work to do.
|
||||
*/
|
||||
new_ndlp = lpfc_findnode_wwpn(phba, NLP_SEARCH_ALL, &sp->portName);
|
||||
|
||||
memset(name, 0, sizeof (struct lpfc_name));
|
||||
rc = memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name));
|
||||
if (!rc || (new_ndlp == ndlp)) {
|
||||
if (new_ndlp == ndlp)
|
||||
return ndlp;
|
||||
}
|
||||
|
||||
if (!new_ndlp) {
|
||||
rc =
|
||||
memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name));
|
||||
if (!rc)
|
||||
return ndlp;
|
||||
new_ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC);
|
||||
if (!new_ndlp)
|
||||
return ndlp;
|
||||
|
@ -683,17 +682,21 @@ lpfc_plogi_confirm_nport(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
|
|||
}
|
||||
|
||||
lpfc_unreg_rpi(phba, new_ndlp);
|
||||
new_ndlp->nlp_prev_state = ndlp->nlp_state;
|
||||
new_ndlp->nlp_DID = ndlp->nlp_DID;
|
||||
new_ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
|
||||
lpfc_nlp_list(phba, new_ndlp, NLP_PLOGI_LIST);
|
||||
new_ndlp->nlp_prev_state = ndlp->nlp_prev_state;
|
||||
new_ndlp->nlp_state = ndlp->nlp_state;
|
||||
lpfc_nlp_list(phba, new_ndlp, ndlp->nlp_flag & NLP_LIST_MASK);
|
||||
|
||||
/* Move this back to NPR list */
|
||||
lpfc_unreg_rpi(phba, ndlp);
|
||||
ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */
|
||||
ndlp->nlp_state = NLP_STE_NPR_NODE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
|
||||
|
||||
if (memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)) == 0) {
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
}
|
||||
else {
|
||||
lpfc_unreg_rpi(phba, ndlp);
|
||||
ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */
|
||||
ndlp->nlp_state = NLP_STE_NPR_NODE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
|
||||
}
|
||||
return new_ndlp;
|
||||
}
|
||||
|
||||
|
@ -703,6 +706,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
|
|||
{
|
||||
IOCB_t *irsp;
|
||||
struct lpfc_nodelist *ndlp;
|
||||
struct lpfc_dmabuf *prsp;
|
||||
int disc, rc, did, type;
|
||||
|
||||
|
||||
|
@ -769,7 +773,10 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
|
|||
}
|
||||
} else {
|
||||
/* Good status, call state machine */
|
||||
ndlp = lpfc_plogi_confirm_nport(phba, cmdiocb, ndlp);
|
||||
prsp = list_entry(((struct lpfc_dmabuf *)
|
||||
cmdiocb->context2)->list.next,
|
||||
struct lpfc_dmabuf, list);
|
||||
ndlp = lpfc_plogi_confirm_nport(phba, prsp, ndlp);
|
||||
rc = lpfc_disc_state_machine(phba, ndlp, cmdiocb,
|
||||
NLP_EVT_CMPL_PLOGI);
|
||||
}
|
||||
|
@ -3282,10 +3289,9 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba)
|
|||
} else
|
||||
lpfc_sli_release_iocbq(phba, piocb);
|
||||
}
|
||||
if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt) {
|
||||
phba->els_tmofunc.expires = jiffies + HZ * timeout;
|
||||
add_timer(&phba->els_tmofunc);
|
||||
}
|
||||
if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt)
|
||||
mod_timer(&phba->els_tmofunc, jiffies + HZ * timeout);
|
||||
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
}
|
||||
|
||||
|
@ -3442,6 +3448,8 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
|
|||
if ((did & Fabric_DID_MASK) == Fabric_DID_MASK) {
|
||||
ndlp->nlp_type |= NLP_FABRIC;
|
||||
}
|
||||
ndlp->nlp_state = NLP_STE_UNUSED_NODE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST);
|
||||
}
|
||||
|
||||
phba->fc_stat.elsRcvFrame++;
|
||||
|
@ -3463,13 +3471,14 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
|
|||
rjt_err = 1;
|
||||
break;
|
||||
}
|
||||
ndlp = lpfc_plogi_confirm_nport(phba, mp, ndlp);
|
||||
lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PLOGI);
|
||||
break;
|
||||
case ELS_CMD_FLOGI:
|
||||
phba->fc_stat.elsRcvFLOGI++;
|
||||
lpfc_els_rcv_flogi(phba, elsiocb, ndlp, newnode);
|
||||
if (newnode) {
|
||||
mempool_free( ndlp, phba->nlp_mem_pool);
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
}
|
||||
break;
|
||||
case ELS_CMD_LOGO:
|
||||
|
@ -3492,7 +3501,7 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
|
|||
phba->fc_stat.elsRcvRSCN++;
|
||||
lpfc_els_rcv_rscn(phba, elsiocb, ndlp, newnode);
|
||||
if (newnode) {
|
||||
mempool_free( ndlp, phba->nlp_mem_pool);
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
}
|
||||
break;
|
||||
case ELS_CMD_ADISC:
|
||||
|
@ -3535,28 +3544,28 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
|
|||
phba->fc_stat.elsRcvLIRR++;
|
||||
lpfc_els_rcv_lirr(phba, elsiocb, ndlp);
|
||||
if (newnode) {
|
||||
mempool_free( ndlp, phba->nlp_mem_pool);
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
}
|
||||
break;
|
||||
case ELS_CMD_RPS:
|
||||
phba->fc_stat.elsRcvRPS++;
|
||||
lpfc_els_rcv_rps(phba, elsiocb, ndlp);
|
||||
if (newnode) {
|
||||
mempool_free( ndlp, phba->nlp_mem_pool);
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
}
|
||||
break;
|
||||
case ELS_CMD_RPL:
|
||||
phba->fc_stat.elsRcvRPL++;
|
||||
lpfc_els_rcv_rpl(phba, elsiocb, ndlp);
|
||||
if (newnode) {
|
||||
mempool_free( ndlp, phba->nlp_mem_pool);
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
}
|
||||
break;
|
||||
case ELS_CMD_RNID:
|
||||
phba->fc_stat.elsRcvRNID++;
|
||||
lpfc_els_rcv_rnid(phba, elsiocb, ndlp);
|
||||
if (newnode) {
|
||||
mempool_free( ndlp, phba->nlp_mem_pool);
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -3568,7 +3577,7 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
|
|||
"%d:0115 Unknown ELS command x%x received from "
|
||||
"NPORT x%x\n", phba->brd_no, cmd, did);
|
||||
if (newnode) {
|
||||
mempool_free( ndlp, phba->nlp_mem_pool);
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1084,7 +1084,7 @@ lpfc_register_remote_port(struct lpfc_hba * phba,
|
|||
fc_remote_port_rolechg(rport, rport_ids.roles);
|
||||
|
||||
if ((rport->scsi_target_id != -1) &&
|
||||
(rport->scsi_target_id < MAX_FCP_TARGET)) {
|
||||
(rport->scsi_target_id < LPFC_MAX_TARGET)) {
|
||||
ndlp->nlp_sid = rport->scsi_target_id;
|
||||
}
|
||||
|
||||
|
@ -1313,7 +1313,7 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
|
|||
if ((rport_add == mapped) &&
|
||||
((!nlp->rport) ||
|
||||
(nlp->rport->scsi_target_id == -1) ||
|
||||
(nlp->rport->scsi_target_id >= MAX_FCP_TARGET))) {
|
||||
(nlp->rport->scsi_target_id >= LPFC_MAX_TARGET))) {
|
||||
nlp->nlp_state = NLP_STE_UNMAPPED_NODE;
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
nlp->nlp_flag |= NLP_TGT_NO_SCSIID;
|
||||
|
|
|
@ -71,6 +71,7 @@ lpfc_config_port_prep(struct lpfc_hba * phba)
|
|||
uint16_t offset = 0;
|
||||
static char licensed[56] =
|
||||
"key unlock for use with gnu public licensed code only\0";
|
||||
static int init_key = 1;
|
||||
|
||||
pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
|
||||
if (!pmb) {
|
||||
|
@ -82,10 +83,13 @@ lpfc_config_port_prep(struct lpfc_hba * phba)
|
|||
phba->hba_state = LPFC_INIT_MBX_CMDS;
|
||||
|
||||
if (lpfc_is_LC_HBA(phba->pcidev->device)) {
|
||||
uint32_t *ptext = (uint32_t *) licensed;
|
||||
if (init_key) {
|
||||
uint32_t *ptext = (uint32_t *) licensed;
|
||||
|
||||
for (i = 0; i < 56; i += sizeof (uint32_t), ptext++)
|
||||
*ptext = cpu_to_be32(*ptext);
|
||||
for (i = 0; i < 56; i += sizeof (uint32_t), ptext++)
|
||||
*ptext = cpu_to_be32(*ptext);
|
||||
init_key = 0;
|
||||
}
|
||||
|
||||
lpfc_read_nv(phba, pmb);
|
||||
memset((char*)mb->un.varRDnvp.rsvd3, 0,
|
||||
|
@ -405,19 +409,26 @@ lpfc_config_port_post(struct lpfc_hba * phba)
|
|||
}
|
||||
/* MBOX buffer will be freed in mbox compl */
|
||||
|
||||
i = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
lpfc_discovery_wait(struct lpfc_hba *phba)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while ((phba->hba_state != LPFC_HBA_READY) ||
|
||||
(phba->num_disc_nodes) || (phba->fc_prli_sent) ||
|
||||
((phba->fc_map_cnt == 0) && (i<2)) ||
|
||||
(psli->sli_flag & LPFC_SLI_MBOX_ACTIVE)) {
|
||||
(phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE)) {
|
||||
/* Check every second for 30 retries. */
|
||||
i++;
|
||||
if (i > 30) {
|
||||
break;
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
if ((i >= 15) && (phba->hba_state <= LPFC_LINK_DOWN)) {
|
||||
/* The link is down. Set linkdown timeout */
|
||||
break;
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/* Delay for 1 second to give discovery time to complete. */
|
||||
|
@ -425,12 +436,7 @@ lpfc_config_port_post(struct lpfc_hba * phba)
|
|||
|
||||
}
|
||||
|
||||
/* Since num_disc_nodes keys off of PLOGI, delay a bit to let
|
||||
* any potential PRLIs to flush thru the SLI sub-system.
|
||||
*/
|
||||
msleep(50);
|
||||
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
@ -1339,7 +1345,8 @@ lpfc_offline(struct lpfc_hba * phba)
|
|||
struct lpfc_sli_ring *pring;
|
||||
struct lpfc_sli *psli;
|
||||
unsigned long iflag;
|
||||
int i = 0;
|
||||
int i;
|
||||
int cnt = 0;
|
||||
|
||||
if (!phba)
|
||||
return 0;
|
||||
|
@ -1348,17 +1355,27 @@ lpfc_offline(struct lpfc_hba * phba)
|
|||
return 0;
|
||||
|
||||
psli = &phba->sli;
|
||||
pring = &psli->ring[psli->fcp_ring];
|
||||
|
||||
lpfc_linkdown(phba);
|
||||
lpfc_sli_flush_mbox_queue(phba);
|
||||
|
||||
/* The linkdown event takes 30 seconds to timeout. */
|
||||
while (pring->txcmplq_cnt) {
|
||||
mdelay(10);
|
||||
if (i++ > 3000)
|
||||
break;
|
||||
for (i = 0; i < psli->num_rings; i++) {
|
||||
pring = &psli->ring[i];
|
||||
/* The linkdown event takes 30 seconds to timeout. */
|
||||
while (pring->txcmplq_cnt) {
|
||||
mdelay(10);
|
||||
if (cnt++ > 3000) {
|
||||
lpfc_printf_log(phba,
|
||||
KERN_WARNING, LOG_INIT,
|
||||
"%d:0466 Outstanding IO when "
|
||||
"bringing Adapter offline\n",
|
||||
phba->brd_no);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* stop all timers associated with this hba */
|
||||
lpfc_stop_timer(phba);
|
||||
phba->work_hba_events = 0;
|
||||
|
@ -1639,6 +1656,8 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
|
|||
goto out_free_irq;
|
||||
}
|
||||
|
||||
lpfc_discovery_wait(phba);
|
||||
|
||||
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
lpfc_poll_start_timer(phba);
|
||||
|
|
|
@ -133,6 +133,11 @@ lpfc_mem_free(struct lpfc_hba * phba)
|
|||
|
||||
pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool);
|
||||
pci_pool_destroy(phba->lpfc_mbuf_pool);
|
||||
|
||||
/* Free the iocb lookup array */
|
||||
kfree(psli->iocbq_lookup);
|
||||
psli->iocbq_lookup = NULL;
|
||||
|
||||
}
|
||||
|
||||
void *
|
||||
|
|
|
@ -1110,6 +1110,17 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_hba * phba,
|
|||
phba->brd_no,
|
||||
did, mb->mbxStatus, phba->hba_state);
|
||||
|
||||
/*
|
||||
* If RegLogin failed due to lack of HBA resources do not
|
||||
* retry discovery.
|
||||
*/
|
||||
if (mb->mbxStatus == MBXERR_RPI_FULL) {
|
||||
ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE;
|
||||
ndlp->nlp_state = NLP_STE_UNUSED_NODE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST);
|
||||
return ndlp->nlp_state;
|
||||
}
|
||||
|
||||
/* Put ndlp in npr list set plogi timer for 1 sec */
|
||||
mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
|
|
|
@ -153,22 +153,6 @@ static void
|
|||
lpfc_release_scsi_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb)
|
||||
{
|
||||
unsigned long iflag = 0;
|
||||
/*
|
||||
* There are only two special cases to consider. (1) the scsi command
|
||||
* requested scatter-gather usage or (2) the scsi command allocated
|
||||
* a request buffer, but did not request use_sg. There is a third
|
||||
* case, but it does not require resource deallocation.
|
||||
*/
|
||||
if ((psb->seg_cnt > 0) && (psb->pCmd->use_sg)) {
|
||||
dma_unmap_sg(&phba->pcidev->dev, psb->pCmd->request_buffer,
|
||||
psb->seg_cnt, psb->pCmd->sc_data_direction);
|
||||
} else {
|
||||
if ((psb->nonsg_phys) && (psb->pCmd->request_bufflen)) {
|
||||
dma_unmap_single(&phba->pcidev->dev, psb->nonsg_phys,
|
||||
psb->pCmd->request_bufflen,
|
||||
psb->pCmd->sc_data_direction);
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
|
||||
psb->pCmd = NULL;
|
||||
|
@ -281,6 +265,27 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
lpfc_scsi_unprep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb)
|
||||
{
|
||||
/*
|
||||
* There are only two special cases to consider. (1) the scsi command
|
||||
* requested scatter-gather usage or (2) the scsi command allocated
|
||||
* a request buffer, but did not request use_sg. There is a third
|
||||
* case, but it does not require resource deallocation.
|
||||
*/
|
||||
if ((psb->seg_cnt > 0) && (psb->pCmd->use_sg)) {
|
||||
dma_unmap_sg(&phba->pcidev->dev, psb->pCmd->request_buffer,
|
||||
psb->seg_cnt, psb->pCmd->sc_data_direction);
|
||||
} else {
|
||||
if ((psb->nonsg_phys) && (psb->pCmd->request_bufflen)) {
|
||||
dma_unmap_single(&phba->pcidev->dev, psb->nonsg_phys,
|
||||
psb->pCmd->request_bufflen,
|
||||
psb->pCmd->sc_data_direction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd)
|
||||
{
|
||||
|
@ -454,6 +459,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
|
|||
cmd->scsi_done(cmd);
|
||||
|
||||
if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
|
||||
lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
|
||||
lpfc_release_scsi_buf(phba, lpfc_cmd);
|
||||
return;
|
||||
}
|
||||
|
@ -511,6 +517,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
|
|||
}
|
||||
}
|
||||
|
||||
lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
|
||||
lpfc_release_scsi_buf(phba, lpfc_cmd);
|
||||
}
|
||||
|
||||
|
@ -609,6 +616,7 @@ lpfc_scsi_prep_cmnd(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd,
|
|||
static int
|
||||
lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
|
||||
struct lpfc_scsi_buf *lpfc_cmd,
|
||||
unsigned int lun,
|
||||
uint8_t task_mgmt_cmd)
|
||||
{
|
||||
struct lpfc_sli *psli;
|
||||
|
@ -627,8 +635,7 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
|
|||
piocb = &piocbq->iocb;
|
||||
|
||||
fcp_cmnd = lpfc_cmd->fcp_cmnd;
|
||||
int_to_scsilun(lpfc_cmd->pCmd->device->lun,
|
||||
&lpfc_cmd->fcp_cmnd->fcp_lun);
|
||||
int_to_scsilun(lun, &lpfc_cmd->fcp_cmnd->fcp_lun);
|
||||
fcp_cmnd->fcpCntl2 = task_mgmt_cmd;
|
||||
|
||||
piocb->ulpCommand = CMD_FCP_ICMND64_CR;
|
||||
|
@ -655,14 +662,16 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
|
|||
|
||||
static int
|
||||
lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba,
|
||||
unsigned tgt_id, struct lpfc_rport_data *rdata)
|
||||
unsigned tgt_id, unsigned int lun,
|
||||
struct lpfc_rport_data *rdata)
|
||||
{
|
||||
struct lpfc_iocbq *iocbq;
|
||||
struct lpfc_iocbq *iocbqrsp;
|
||||
int ret;
|
||||
|
||||
lpfc_cmd->rdata = rdata;
|
||||
ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, FCP_TARGET_RESET);
|
||||
ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, lun,
|
||||
FCP_TARGET_RESET);
|
||||
if (!ret)
|
||||
return FAILED;
|
||||
|
||||
|
@ -822,6 +831,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
|
|||
return 0;
|
||||
|
||||
out_host_busy_free_buf:
|
||||
lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
|
||||
lpfc_release_scsi_buf(phba, lpfc_cmd);
|
||||
out_host_busy:
|
||||
return SCSI_MLQUEUE_HOST_BUSY;
|
||||
|
@ -969,12 +979,12 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
|
|||
if (lpfc_cmd == NULL)
|
||||
goto out;
|
||||
|
||||
lpfc_cmd->pCmd = cmnd;
|
||||
lpfc_cmd->timeout = 60;
|
||||
lpfc_cmd->scsi_hba = phba;
|
||||
lpfc_cmd->rdata = rdata;
|
||||
|
||||
ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, FCP_LUN_RESET);
|
||||
ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, cmnd->device->lun,
|
||||
FCP_LUN_RESET);
|
||||
if (!ret)
|
||||
goto out_free_scsi_buf;
|
||||
|
||||
|
@ -1001,7 +1011,6 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
|
|||
cmd_status = iocbqrsp->iocb.ulpStatus;
|
||||
|
||||
lpfc_sli_release_iocbq(phba, iocbqrsp);
|
||||
lpfc_release_scsi_buf(phba, lpfc_cmd);
|
||||
|
||||
/*
|
||||
* All outstanding txcmplq I/Os should have been aborted by the device.
|
||||
|
@ -1040,6 +1049,8 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
|
|||
}
|
||||
|
||||
out_free_scsi_buf:
|
||||
lpfc_release_scsi_buf(phba, lpfc_cmd);
|
||||
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
|
||||
"%d:0713 SCSI layer issued LUN reset (%d, %d) "
|
||||
"Data: x%x x%x x%x\n",
|
||||
|
@ -1070,7 +1081,6 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
|
|||
|
||||
/* The lpfc_cmd storage is reused. Set all loop invariants. */
|
||||
lpfc_cmd->timeout = 60;
|
||||
lpfc_cmd->pCmd = cmnd;
|
||||
lpfc_cmd->scsi_hba = phba;
|
||||
|
||||
/*
|
||||
|
@ -1078,7 +1088,7 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
|
|||
* targets known to the driver. Should any target reset
|
||||
* fail, this routine returns failure to the midlayer.
|
||||
*/
|
||||
for (i = 0; i < MAX_FCP_TARGET; i++) {
|
||||
for (i = 0; i < LPFC_MAX_TARGET; i++) {
|
||||
/* Search the mapped list for this target ID */
|
||||
match = 0;
|
||||
list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) {
|
||||
|
@ -1090,8 +1100,8 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
|
|||
if (!match)
|
||||
continue;
|
||||
|
||||
ret = lpfc_scsi_tgt_reset(lpfc_cmd, phba,
|
||||
i, ndlp->rport->dd_data);
|
||||
ret = lpfc_scsi_tgt_reset(lpfc_cmd, phba, i, cmnd->device->lun,
|
||||
ndlp->rport->dd_data);
|
||||
if (ret != SUCCESS) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
|
||||
"%d:0713 Bus Reset on target %d failed\n",
|
||||
|
|
|
@ -191,35 +191,12 @@ static int
|
|||
lpfc_sli_ringtxcmpl_put(struct lpfc_hba * phba,
|
||||
struct lpfc_sli_ring * pring, struct lpfc_iocbq * piocb)
|
||||
{
|
||||
uint16_t iotag;
|
||||
|
||||
list_add_tail(&piocb->list, &pring->txcmplq);
|
||||
pring->txcmplq_cnt++;
|
||||
if (unlikely(pring->ringno == LPFC_ELS_RING))
|
||||
mod_timer(&phba->els_tmofunc,
|
||||
jiffies + HZ * (phba->fc_ratov << 1));
|
||||
|
||||
if (pring->fast_lookup) {
|
||||
/* Setup fast lookup based on iotag for completion */
|
||||
iotag = piocb->iocb.ulpIoTag;
|
||||
if (iotag && (iotag < pring->fast_iotag))
|
||||
*(pring->fast_lookup + iotag) = piocb;
|
||||
else {
|
||||
|
||||
/* Cmd ring <ringno> put: iotag <iotag> greater then
|
||||
configured max <fast_iotag> wd0 <icmd> */
|
||||
lpfc_printf_log(phba,
|
||||
KERN_ERR,
|
||||
LOG_SLI,
|
||||
"%d:0316 Cmd ring %d put: iotag x%x "
|
||||
"greater then configured max x%x "
|
||||
"wd0 x%x\n",
|
||||
phba->brd_no,
|
||||
pring->ringno, iotag,
|
||||
pring->fast_iotag,
|
||||
*(((uint32_t *)(&piocb->iocb)) + 7));
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -601,7 +578,7 @@ lpfc_sli_handle_mb_event(struct lpfc_hba * phba)
|
|||
/* Stray Mailbox Interrupt, mbxCommand <cmd> mbxStatus
|
||||
<status> */
|
||||
lpfc_printf_log(phba,
|
||||
KERN_ERR,
|
||||
KERN_WARNING,
|
||||
LOG_MBOX | LOG_SLI,
|
||||
"%d:0304 Stray Mailbox Interrupt "
|
||||
"mbxCommand x%x mbxStatus x%x\n",
|
||||
|
@ -1570,8 +1547,8 @@ lpfc_sli_brdready(struct lpfc_hba * phba, uint32_t mask)
|
|||
|
||||
void lpfc_reset_barrier(struct lpfc_hba * phba)
|
||||
{
|
||||
uint32_t * resp_buf;
|
||||
uint32_t * mbox_buf;
|
||||
uint32_t __iomem *resp_buf;
|
||||
uint32_t __iomem *mbox_buf;
|
||||
volatile uint32_t mbox;
|
||||
uint32_t hc_copy;
|
||||
int i;
|
||||
|
@ -1587,7 +1564,7 @@ void lpfc_reset_barrier(struct lpfc_hba * phba)
|
|||
* Tell the other part of the chip to suspend temporarily all
|
||||
* its DMA activity.
|
||||
*/
|
||||
resp_buf = (uint32_t *)phba->MBslimaddr;
|
||||
resp_buf = phba->MBslimaddr;
|
||||
|
||||
/* Disable the error attention */
|
||||
hc_copy = readl(phba->HCregaddr);
|
||||
|
@ -1605,7 +1582,7 @@ void lpfc_reset_barrier(struct lpfc_hba * phba)
|
|||
((MAILBOX_t *)&mbox)->mbxOwner = OWN_CHIP;
|
||||
|
||||
writel(BARRIER_TEST_PATTERN, (resp_buf + 1));
|
||||
mbox_buf = (uint32_t *)phba->MBslimaddr;
|
||||
mbox_buf = phba->MBslimaddr;
|
||||
writel(mbox, mbox_buf);
|
||||
|
||||
for (i = 0;
|
||||
|
@ -1805,7 +1782,7 @@ lpfc_sli_brdrestart(struct lpfc_hba * phba)
|
|||
skip_post = 0;
|
||||
word0 = 0; /* This is really setting up word1 */
|
||||
}
|
||||
to_slim = (uint8_t *) phba->MBslimaddr + sizeof (uint32_t);
|
||||
to_slim = phba->MBslimaddr + sizeof (uint32_t);
|
||||
writel(*(uint32_t *) mb, to_slim);
|
||||
readl(to_slim); /* flush */
|
||||
|
||||
|
@ -2659,8 +2636,6 @@ lpfc_sli_hba_down(struct lpfc_hba * phba)
|
|||
|
||||
INIT_LIST_HEAD(&(pring->txq));
|
||||
|
||||
kfree(pring->fast_lookup);
|
||||
pring->fast_lookup = NULL;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(phba->host->host_lock, flags);
|
||||
|
@ -3110,6 +3085,24 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq,
|
|||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
lpfc_sli_flush_mbox_queue(struct lpfc_hba * phba)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE && !phba->stopped) {
|
||||
if (i++ > LPFC_MBOX_TMO * 1000)
|
||||
return 1;
|
||||
|
||||
if (lpfc_sli_handle_mb_event(phba) == 0)
|
||||
i = 0;
|
||||
|
||||
msleep(1);
|
||||
}
|
||||
|
||||
return (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE) ? 1 : 0;
|
||||
}
|
||||
|
||||
irqreturn_t
|
||||
lpfc_intr_handler(int irq, void *dev_id, struct pt_regs * regs)
|
||||
{
|
||||
|
|
|
@ -135,8 +135,6 @@ struct lpfc_sli_ring {
|
|||
uint32_t fast_iotag; /* max fastlookup based iotag */
|
||||
uint32_t iotag_ctr; /* keeps track of the next iotag to use */
|
||||
uint32_t iotag_max; /* max iotag value to use */
|
||||
struct lpfc_iocbq ** fast_lookup; /* array of IOCB ptrs indexed by
|
||||
iotag */
|
||||
struct list_head txq;
|
||||
uint16_t txq_cnt; /* current length of queue */
|
||||
uint16_t txq_max; /* max length */
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* included with this package. *
|
||||
*******************************************************************/
|
||||
|
||||
#define LPFC_DRIVER_VERSION "8.1.6"
|
||||
#define LPFC_DRIVER_VERSION "8.1.7"
|
||||
|
||||
#define LPFC_DRIVER_NAME "lpfc"
|
||||
|
||||
|
|
|
@ -378,7 +378,7 @@ static void set_dma_cmds(struct fsc_state *state, struct scsi_cmnd *cmd)
|
|||
int nseg;
|
||||
|
||||
total = 0;
|
||||
scl = (struct scatterlist *) cmd->buffer;
|
||||
scl = (struct scatterlist *) cmd->request_buffer;
|
||||
nseg = pci_map_sg(state->pdev, scl, cmd->use_sg,
|
||||
cmd->sc_data_direction);
|
||||
for (i = 0; i < nseg; ++i) {
|
||||
|
|
|
@ -1268,7 +1268,7 @@ static void set_dma_cmds(struct mesh_state *ms, struct scsi_cmnd *cmd)
|
|||
if (cmd->use_sg > 0) {
|
||||
int nseg;
|
||||
total = 0;
|
||||
scl = (struct scatterlist *) cmd->buffer;
|
||||
scl = (struct scatterlist *) cmd->request_buffer;
|
||||
off = ms->data_ptr;
|
||||
nseg = pci_map_sg(ms->pdev, scl, cmd->use_sg,
|
||||
cmd->sc_data_direction);
|
||||
|
|
|
@ -169,8 +169,6 @@ int __init pluto_detect(struct scsi_host_template *tpnt)
|
|||
SCpnt->request->rq_status = RQ_SCSI_BUSY;
|
||||
|
||||
SCpnt->done = pluto_detect_done;
|
||||
SCpnt->bufflen = 256;
|
||||
SCpnt->buffer = fcs[i].inquiry;
|
||||
SCpnt->request_bufflen = 256;
|
||||
SCpnt->request_buffer = fcs[i].inquiry;
|
||||
PLD(("set up %d %08lx\n", i, (long)SCpnt))
|
||||
|
|
|
@ -874,7 +874,7 @@ static inline int load_cmd(struct scsi_cmnd *Cmnd, struct Command_Entry *cmd,
|
|||
if (Cmnd->use_sg) {
|
||||
int sg_count;
|
||||
|
||||
sg = (struct scatterlist *) Cmnd->buffer;
|
||||
sg = (struct scatterlist *) Cmnd->request_buffer;
|
||||
sg_count = sbus_map_sg(qpti->sdev, sg, Cmnd->use_sg, Cmnd->sc_data_direction);
|
||||
|
||||
ds = cmd->dataseg;
|
||||
|
@ -1278,7 +1278,7 @@ static struct scsi_cmnd *qlogicpti_intr_handler(struct qlogicpti *qpti)
|
|||
|
||||
if (Cmnd->use_sg) {
|
||||
sbus_unmap_sg(qpti->sdev,
|
||||
(struct scatterlist *)Cmnd->buffer,
|
||||
(struct scatterlist *)Cmnd->request_buffer,
|
||||
Cmnd->use_sg,
|
||||
Cmnd->sc_data_direction);
|
||||
} else {
|
||||
|
|
|
@ -346,7 +346,7 @@ void scsi_log_send(struct scsi_cmnd *cmd)
|
|||
if (level > 3) {
|
||||
printk(KERN_INFO "buffer = 0x%p, bufflen = %d,"
|
||||
" done = 0x%p, queuecommand 0x%p\n",
|
||||
cmd->buffer, cmd->bufflen,
|
||||
cmd->request_buffer, cmd->request_bufflen,
|
||||
cmd->done,
|
||||
sdev->host->hostt->queuecommand);
|
||||
|
||||
|
@ -661,11 +661,6 @@ void __scsi_done(struct scsi_cmnd *cmd)
|
|||
*/
|
||||
int scsi_retry_command(struct scsi_cmnd *cmd)
|
||||
{
|
||||
/*
|
||||
* Restore the SCSI command state.
|
||||
*/
|
||||
scsi_setup_cmd_retry(cmd);
|
||||
|
||||
/*
|
||||
* Zero the sense information from the last time we tried
|
||||
* this command.
|
||||
|
@ -711,10 +706,6 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
|
|||
"Notifying upper driver of completion "
|
||||
"(result %x)\n", cmd->result));
|
||||
|
||||
/*
|
||||
* We can get here with use_sg=0, causing a panic in the upper level
|
||||
*/
|
||||
cmd->use_sg = cmd->old_use_sg;
|
||||
cmd->done(cmd);
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_finish_command);
|
||||
|
|
|
@ -286,7 +286,7 @@ static int inquiry_evpd_83(unsigned char * arr, int target_dev_id,
|
|||
int dev_id_num, const char * dev_id_str,
|
||||
int dev_id_str_len);
|
||||
static int inquiry_evpd_88(unsigned char * arr, int target_dev_id);
|
||||
static void do_create_driverfs_files(void);
|
||||
static int do_create_driverfs_files(void);
|
||||
static void do_remove_driverfs_files(void);
|
||||
|
||||
static int sdebug_add_adapter(void);
|
||||
|
@ -2487,19 +2487,22 @@ static ssize_t sdebug_add_host_store(struct device_driver * ddp,
|
|||
DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, sdebug_add_host_show,
|
||||
sdebug_add_host_store);
|
||||
|
||||
static void do_create_driverfs_files(void)
|
||||
static int do_create_driverfs_files(void)
|
||||
{
|
||||
driver_create_file(&sdebug_driverfs_driver, &driver_attr_add_host);
|
||||
driver_create_file(&sdebug_driverfs_driver, &driver_attr_delay);
|
||||
driver_create_file(&sdebug_driverfs_driver, &driver_attr_dev_size_mb);
|
||||
driver_create_file(&sdebug_driverfs_driver, &driver_attr_dsense);
|
||||
driver_create_file(&sdebug_driverfs_driver, &driver_attr_every_nth);
|
||||
driver_create_file(&sdebug_driverfs_driver, &driver_attr_max_luns);
|
||||
driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_tgts);
|
||||
driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_parts);
|
||||
driver_create_file(&sdebug_driverfs_driver, &driver_attr_ptype);
|
||||
driver_create_file(&sdebug_driverfs_driver, &driver_attr_opts);
|
||||
driver_create_file(&sdebug_driverfs_driver, &driver_attr_scsi_level);
|
||||
int ret;
|
||||
|
||||
ret = driver_create_file(&sdebug_driverfs_driver, &driver_attr_add_host);
|
||||
ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_delay);
|
||||
ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_dev_size_mb);
|
||||
ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_dsense);
|
||||
ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_every_nth);
|
||||
ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_max_luns);
|
||||
ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_tgts);
|
||||
ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_parts);
|
||||
ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_ptype);
|
||||
ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_opts);
|
||||
ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_scsi_level);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void do_remove_driverfs_files(void)
|
||||
|
@ -2522,6 +2525,7 @@ static int __init scsi_debug_init(void)
|
|||
unsigned int sz;
|
||||
int host_to_add;
|
||||
int k;
|
||||
int ret;
|
||||
|
||||
if (scsi_debug_dev_size_mb < 1)
|
||||
scsi_debug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */
|
||||
|
@ -2560,12 +2564,32 @@ static int __init scsi_debug_init(void)
|
|||
if (scsi_debug_num_parts > 0)
|
||||
sdebug_build_parts(fake_storep);
|
||||
|
||||
init_all_queued();
|
||||
ret = device_register(&pseudo_primary);
|
||||
if (ret < 0) {
|
||||
printk(KERN_WARNING "scsi_debug: device_register error: %d\n",
|
||||
ret);
|
||||
goto free_vm;
|
||||
}
|
||||
ret = bus_register(&pseudo_lld_bus);
|
||||
if (ret < 0) {
|
||||
printk(KERN_WARNING "scsi_debug: bus_register error: %d\n",
|
||||
ret);
|
||||
goto dev_unreg;
|
||||
}
|
||||
ret = driver_register(&sdebug_driverfs_driver);
|
||||
if (ret < 0) {
|
||||
printk(KERN_WARNING "scsi_debug: driver_register error: %d\n",
|
||||
ret);
|
||||
goto bus_unreg;
|
||||
}
|
||||
ret = do_create_driverfs_files();
|
||||
if (ret < 0) {
|
||||
printk(KERN_WARNING "scsi_debug: driver_create_file error: %d\n",
|
||||
ret);
|
||||
goto del_files;
|
||||
}
|
||||
|
||||
device_register(&pseudo_primary);
|
||||
bus_register(&pseudo_lld_bus);
|
||||
driver_register(&sdebug_driverfs_driver);
|
||||
do_create_driverfs_files();
|
||||
init_all_queued();
|
||||
|
||||
sdebug_driver_template.proc_name = (char *)sdebug_proc_name;
|
||||
|
||||
|
@ -2585,6 +2609,18 @@ static int __init scsi_debug_init(void)
|
|||
scsi_debug_add_host);
|
||||
}
|
||||
return 0;
|
||||
|
||||
del_files:
|
||||
do_remove_driverfs_files();
|
||||
driver_unregister(&sdebug_driverfs_driver);
|
||||
bus_unreg:
|
||||
bus_unregister(&pseudo_lld_bus);
|
||||
dev_unreg:
|
||||
device_unregister(&pseudo_primary);
|
||||
free_vm:
|
||||
vfree(fake_storep);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit scsi_debug_exit(void)
|
||||
|
|
|
@ -460,19 +460,67 @@ static void scsi_eh_done(struct scsi_cmnd *scmd)
|
|||
* Return value:
|
||||
* SUCCESS or FAILED or NEEDS_RETRY
|
||||
**/
|
||||
static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout)
|
||||
static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout, int copy_sense)
|
||||
{
|
||||
struct scsi_device *sdev = scmd->device;
|
||||
struct Scsi_Host *shost = sdev->host;
|
||||
int old_result = scmd->result;
|
||||
DECLARE_COMPLETION(done);
|
||||
unsigned long timeleft;
|
||||
unsigned long flags;
|
||||
unsigned char old_cmnd[MAX_COMMAND_SIZE];
|
||||
enum dma_data_direction old_data_direction;
|
||||
unsigned short old_use_sg;
|
||||
unsigned char old_cmd_len;
|
||||
unsigned old_bufflen;
|
||||
void *old_buffer;
|
||||
int rtn;
|
||||
|
||||
/*
|
||||
* We need saved copies of a number of fields - this is because
|
||||
* error handling may need to overwrite these with different values
|
||||
* to run different commands, and once error handling is complete,
|
||||
* we will need to restore these values prior to running the actual
|
||||
* command.
|
||||
*/
|
||||
old_buffer = scmd->request_buffer;
|
||||
old_bufflen = scmd->request_bufflen;
|
||||
memcpy(old_cmnd, scmd->cmnd, sizeof(scmd->cmnd));
|
||||
old_data_direction = scmd->sc_data_direction;
|
||||
old_cmd_len = scmd->cmd_len;
|
||||
old_use_sg = scmd->use_sg;
|
||||
|
||||
if (copy_sense) {
|
||||
int gfp_mask = GFP_ATOMIC;
|
||||
|
||||
if (shost->hostt->unchecked_isa_dma)
|
||||
gfp_mask |= __GFP_DMA;
|
||||
|
||||
scmd->sc_data_direction = DMA_FROM_DEVICE;
|
||||
scmd->request_bufflen = 252;
|
||||
scmd->request_buffer = kzalloc(scmd->request_bufflen, gfp_mask);
|
||||
if (!scmd->request_buffer)
|
||||
return FAILED;
|
||||
} else {
|
||||
scmd->request_buffer = NULL;
|
||||
scmd->request_bufflen = 0;
|
||||
scmd->sc_data_direction = DMA_NONE;
|
||||
}
|
||||
|
||||
scmd->underflow = 0;
|
||||
scmd->use_sg = 0;
|
||||
scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
|
||||
|
||||
if (sdev->scsi_level <= SCSI_2)
|
||||
scmd->cmnd[1] = (scmd->cmnd[1] & 0x1f) |
|
||||
(sdev->lun << 5 & 0xe0);
|
||||
|
||||
/*
|
||||
* Zero the sense buffer. The scsi spec mandates that any
|
||||
* untransferred sense data should be interpreted as being zero.
|
||||
*/
|
||||
memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer));
|
||||
|
||||
shost->eh_action = &done;
|
||||
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
|
@ -522,6 +570,29 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout)
|
|||
rtn = FAILED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Last chance to have valid sense data.
|
||||
*/
|
||||
if (copy_sense) {
|
||||
if (!SCSI_SENSE_VALID(scmd)) {
|
||||
memcpy(scmd->sense_buffer, scmd->request_buffer,
|
||||
sizeof(scmd->sense_buffer));
|
||||
}
|
||||
kfree(scmd->request_buffer);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Restore original data
|
||||
*/
|
||||
scmd->request_buffer = old_buffer;
|
||||
scmd->request_bufflen = old_bufflen;
|
||||
memcpy(scmd->cmnd, old_cmnd, sizeof(scmd->cmnd));
|
||||
scmd->sc_data_direction = old_data_direction;
|
||||
scmd->cmd_len = old_cmd_len;
|
||||
scmd->use_sg = old_use_sg;
|
||||
scmd->result = old_result;
|
||||
return rtn;
|
||||
}
|
||||
|
||||
|
@ -537,56 +608,10 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout)
|
|||
static int scsi_request_sense(struct scsi_cmnd *scmd)
|
||||
{
|
||||
static unsigned char generic_sense[6] =
|
||||
{REQUEST_SENSE, 0, 0, 0, 252, 0};
|
||||
unsigned char *scsi_result;
|
||||
int saved_result;
|
||||
int rtn;
|
||||
{REQUEST_SENSE, 0, 0, 0, 252, 0};
|
||||
|
||||
memcpy(scmd->cmnd, generic_sense, sizeof(generic_sense));
|
||||
|
||||
scsi_result = kmalloc(252, GFP_ATOMIC | ((scmd->device->host->hostt->unchecked_isa_dma) ? __GFP_DMA : 0));
|
||||
|
||||
|
||||
if (unlikely(!scsi_result)) {
|
||||
printk(KERN_ERR "%s: cannot allocate scsi_result.\n",
|
||||
__FUNCTION__);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
/*
|
||||
* zero the sense buffer. some host adapters automatically always
|
||||
* request sense, so it is not a good idea that
|
||||
* scmd->request_buffer and scmd->sense_buffer point to the same
|
||||
* address (db). 0 is not a valid sense code.
|
||||
*/
|
||||
memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer));
|
||||
memset(scsi_result, 0, 252);
|
||||
|
||||
saved_result = scmd->result;
|
||||
scmd->request_buffer = scsi_result;
|
||||
scmd->request_bufflen = 252;
|
||||
scmd->use_sg = 0;
|
||||
scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
|
||||
scmd->sc_data_direction = DMA_FROM_DEVICE;
|
||||
scmd->underflow = 0;
|
||||
|
||||
rtn = scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT);
|
||||
|
||||
/* last chance to have valid sense data */
|
||||
if(!SCSI_SENSE_VALID(scmd)) {
|
||||
memcpy(scmd->sense_buffer, scmd->request_buffer,
|
||||
sizeof(scmd->sense_buffer));
|
||||
}
|
||||
|
||||
kfree(scsi_result);
|
||||
|
||||
/*
|
||||
* when we eventually call scsi_finish, we really wish to complete
|
||||
* the original request, so let's restore the original data. (db)
|
||||
*/
|
||||
scsi_setup_cmd_retry(scmd);
|
||||
scmd->result = saved_result;
|
||||
return rtn;
|
||||
return scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -605,12 +630,6 @@ void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, struct list_head *done_q)
|
|||
{
|
||||
scmd->device->host->host_failed--;
|
||||
scmd->eh_eflags = 0;
|
||||
|
||||
/*
|
||||
* set this back so that the upper level can correctly free up
|
||||
* things.
|
||||
*/
|
||||
scsi_setup_cmd_retry(scmd);
|
||||
list_move_tail(&scmd->eh_entry, done_q);
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_eh_finish_cmd);
|
||||
|
@ -715,47 +734,26 @@ static int scsi_eh_tur(struct scsi_cmnd *scmd)
|
|||
{
|
||||
static unsigned char tur_command[6] = {TEST_UNIT_READY, 0, 0, 0, 0, 0};
|
||||
int retry_cnt = 1, rtn;
|
||||
int saved_result;
|
||||
|
||||
retry_tur:
|
||||
memcpy(scmd->cmnd, tur_command, sizeof(tur_command));
|
||||
|
||||
/*
|
||||
* zero the sense buffer. the scsi spec mandates that any
|
||||
* untransferred sense data should be interpreted as being zero.
|
||||
*/
|
||||
memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer));
|
||||
|
||||
saved_result = scmd->result;
|
||||
scmd->request_buffer = NULL;
|
||||
scmd->request_bufflen = 0;
|
||||
scmd->use_sg = 0;
|
||||
scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
|
||||
scmd->underflow = 0;
|
||||
scmd->sc_data_direction = DMA_NONE;
|
||||
rtn = scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT, 0);
|
||||
|
||||
rtn = scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT);
|
||||
|
||||
/*
|
||||
* when we eventually call scsi_finish, we really wish to complete
|
||||
* the original request, so let's restore the original data. (db)
|
||||
*/
|
||||
scsi_setup_cmd_retry(scmd);
|
||||
scmd->result = saved_result;
|
||||
|
||||
/*
|
||||
* hey, we are done. let's look to see what happened.
|
||||
*/
|
||||
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd %p rtn %x\n",
|
||||
__FUNCTION__, scmd, rtn));
|
||||
if (rtn == SUCCESS)
|
||||
return 0;
|
||||
else if (rtn == NEEDS_RETRY) {
|
||||
|
||||
switch (rtn) {
|
||||
case NEEDS_RETRY:
|
||||
if (retry_cnt--)
|
||||
goto retry_tur;
|
||||
/*FALLTHRU*/
|
||||
case SUCCESS:
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -837,44 +835,16 @@ static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd)
|
|||
static int scsi_eh_try_stu(struct scsi_cmnd *scmd)
|
||||
{
|
||||
static unsigned char stu_command[6] = {START_STOP, 0, 0, 0, 1, 0};
|
||||
int rtn;
|
||||
int saved_result;
|
||||
|
||||
if (!scmd->device->allow_restart)
|
||||
return 1;
|
||||
if (scmd->device->allow_restart) {
|
||||
int rtn;
|
||||
|
||||
memcpy(scmd->cmnd, stu_command, sizeof(stu_command));
|
||||
memcpy(scmd->cmnd, stu_command, sizeof(stu_command));
|
||||
rtn = scsi_send_eh_cmnd(scmd, START_UNIT_TIMEOUT, 0);
|
||||
if (rtn == SUCCESS)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* zero the sense buffer. the scsi spec mandates that any
|
||||
* untransferred sense data should be interpreted as being zero.
|
||||
*/
|
||||
memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer));
|
||||
|
||||
saved_result = scmd->result;
|
||||
scmd->request_buffer = NULL;
|
||||
scmd->request_bufflen = 0;
|
||||
scmd->use_sg = 0;
|
||||
scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
|
||||
scmd->underflow = 0;
|
||||
scmd->sc_data_direction = DMA_NONE;
|
||||
|
||||
rtn = scsi_send_eh_cmnd(scmd, START_UNIT_TIMEOUT);
|
||||
|
||||
/*
|
||||
* when we eventually call scsi_finish, we really wish to complete
|
||||
* the original request, so let's restore the original data. (db)
|
||||
*/
|
||||
scsi_setup_cmd_retry(scmd);
|
||||
scmd->result = saved_result;
|
||||
|
||||
/*
|
||||
* hey, we are done. let's look to see what happened.
|
||||
*/
|
||||
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd %p rtn %x\n",
|
||||
__FUNCTION__, scmd, rtn));
|
||||
if (rtn == SUCCESS)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1684,8 +1654,6 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
|
|||
|
||||
scmd->scsi_done = scsi_reset_provider_done_command;
|
||||
scmd->done = NULL;
|
||||
scmd->buffer = NULL;
|
||||
scmd->bufflen = 0;
|
||||
scmd->request_buffer = NULL;
|
||||
scmd->request_bufflen = 0;
|
||||
|
||||
|
|
|
@ -436,60 +436,16 @@ EXPORT_SYMBOL_GPL(scsi_execute_async);
|
|||
*
|
||||
* Arguments: cmd - command that is ready to be queued.
|
||||
*
|
||||
* Returns: Nothing
|
||||
*
|
||||
* Notes: This function has the job of initializing a number of
|
||||
* fields related to error handling. Typically this will
|
||||
* be called once for each command, as required.
|
||||
*/
|
||||
static int scsi_init_cmd_errh(struct scsi_cmnd *cmd)
|
||||
static void scsi_init_cmd_errh(struct scsi_cmnd *cmd)
|
||||
{
|
||||
cmd->serial_number = 0;
|
||||
|
||||
memset(cmd->sense_buffer, 0, sizeof cmd->sense_buffer);
|
||||
|
||||
if (cmd->cmd_len == 0)
|
||||
cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
|
||||
|
||||
/*
|
||||
* We need saved copies of a number of fields - this is because
|
||||
* error handling may need to overwrite these with different values
|
||||
* to run different commands, and once error handling is complete,
|
||||
* we will need to restore these values prior to running the actual
|
||||
* command.
|
||||
*/
|
||||
cmd->old_use_sg = cmd->use_sg;
|
||||
cmd->old_cmd_len = cmd->cmd_len;
|
||||
cmd->sc_old_data_direction = cmd->sc_data_direction;
|
||||
cmd->old_underflow = cmd->underflow;
|
||||
memcpy(cmd->data_cmnd, cmd->cmnd, sizeof(cmd->cmnd));
|
||||
cmd->buffer = cmd->request_buffer;
|
||||
cmd->bufflen = cmd->request_bufflen;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function: scsi_setup_cmd_retry()
|
||||
*
|
||||
* Purpose: Restore the command state for a retry
|
||||
*
|
||||
* Arguments: cmd - command to be restored
|
||||
*
|
||||
* Returns: Nothing
|
||||
*
|
||||
* Notes: Immediately prior to retrying a command, we need
|
||||
* to restore certain fields that we saved above.
|
||||
*/
|
||||
void scsi_setup_cmd_retry(struct scsi_cmnd *cmd)
|
||||
{
|
||||
memcpy(cmd->cmnd, cmd->data_cmnd, sizeof(cmd->data_cmnd));
|
||||
cmd->request_buffer = cmd->buffer;
|
||||
cmd->request_bufflen = cmd->bufflen;
|
||||
cmd->use_sg = cmd->old_use_sg;
|
||||
cmd->cmd_len = cmd->old_cmd_len;
|
||||
cmd->sc_data_direction = cmd->sc_old_data_direction;
|
||||
cmd->underflow = cmd->old_underflow;
|
||||
}
|
||||
|
||||
void scsi_device_unbusy(struct scsi_device *sdev)
|
||||
|
@ -807,22 +763,13 @@ static void scsi_free_sgtable(struct scatterlist *sgl, int index)
|
|||
*/
|
||||
static void scsi_release_buffers(struct scsi_cmnd *cmd)
|
||||
{
|
||||
struct request *req = cmd->request;
|
||||
|
||||
/*
|
||||
* Free up any indirection buffers we allocated for DMA purposes.
|
||||
*/
|
||||
if (cmd->use_sg)
|
||||
scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len);
|
||||
else if (cmd->request_buffer != req->buffer)
|
||||
kfree(cmd->request_buffer);
|
||||
|
||||
/*
|
||||
* Zero these out. They now point to freed memory, and it is
|
||||
* dangerous to hang onto the pointers.
|
||||
*/
|
||||
cmd->buffer = NULL;
|
||||
cmd->bufflen = 0;
|
||||
cmd->request_buffer = NULL;
|
||||
cmd->request_bufflen = 0;
|
||||
}
|
||||
|
@ -858,7 +805,7 @@ static void scsi_release_buffers(struct scsi_cmnd *cmd)
|
|||
void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
|
||||
{
|
||||
int result = cmd->result;
|
||||
int this_count = cmd->bufflen;
|
||||
int this_count = cmd->request_bufflen;
|
||||
request_queue_t *q = cmd->device->request_queue;
|
||||
struct request *req = cmd->request;
|
||||
int clear_errors = 1;
|
||||
|
@ -866,28 +813,14 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
|
|||
int sense_valid = 0;
|
||||
int sense_deferred = 0;
|
||||
|
||||
/*
|
||||
* Free up any indirection buffers we allocated for DMA purposes.
|
||||
* For the case of a READ, we need to copy the data out of the
|
||||
* bounce buffer and into the real buffer.
|
||||
*/
|
||||
if (cmd->use_sg)
|
||||
scsi_free_sgtable(cmd->buffer, cmd->sglist_len);
|
||||
else if (cmd->buffer != req->buffer) {
|
||||
if (rq_data_dir(req) == READ) {
|
||||
unsigned long flags;
|
||||
char *to = bio_kmap_irq(req->bio, &flags);
|
||||
memcpy(to, cmd->buffer, cmd->bufflen);
|
||||
bio_kunmap_irq(to, &flags);
|
||||
}
|
||||
kfree(cmd->buffer);
|
||||
}
|
||||
scsi_release_buffers(cmd);
|
||||
|
||||
if (result) {
|
||||
sense_valid = scsi_command_normalize_sense(cmd, &sshdr);
|
||||
if (sense_valid)
|
||||
sense_deferred = scsi_sense_is_deferred(&sshdr);
|
||||
}
|
||||
|
||||
if (blk_pc_request(req)) { /* SG_IO ioctl from block level */
|
||||
req->errors = result;
|
||||
if (result) {
|
||||
|
@ -907,15 +840,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
|
|||
req->data_len = cmd->resid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Zero these out. They now point to freed memory, and it is
|
||||
* dangerous to hang onto the pointers.
|
||||
*/
|
||||
cmd->buffer = NULL;
|
||||
cmd->bufflen = 0;
|
||||
cmd->request_buffer = NULL;
|
||||
cmd->request_bufflen = 0;
|
||||
|
||||
/*
|
||||
* Next deal with any sectors which we were able to correctly
|
||||
* handle.
|
||||
|
@ -1012,7 +936,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
|
|||
if (!(req->flags & REQ_QUIET)) {
|
||||
scmd_printk(KERN_INFO, cmd,
|
||||
"Volume overflow, CDB: ");
|
||||
__scsi_print_command(cmd->data_cmnd);
|
||||
__scsi_print_command(cmd->cmnd);
|
||||
scsi_print_sense("", cmd);
|
||||
}
|
||||
/* See SSC3rXX or current. */
|
||||
|
@ -1143,7 +1067,7 @@ static void scsi_blk_pc_done(struct scsi_cmnd *cmd)
|
|||
* successfully. Since this is a REQ_BLOCK_PC command the
|
||||
* caller should check the request's errors value
|
||||
*/
|
||||
scsi_io_completion(cmd, cmd->bufflen);
|
||||
scsi_io_completion(cmd, cmd->request_bufflen);
|
||||
}
|
||||
|
||||
static void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd)
|
||||
|
|
|
@ -57,7 +57,6 @@ extern int scsi_eh_scmd_add(struct scsi_cmnd *, int);
|
|||
|
||||
/* scsi_lib.c */
|
||||
extern int scsi_maybe_unblock_host(struct scsi_device *sdev);
|
||||
extern void scsi_setup_cmd_retry(struct scsi_cmnd *cmd);
|
||||
extern void scsi_device_unbusy(struct scsi_device *sdev);
|
||||
extern int scsi_queue_insert(struct scsi_cmnd *cmd, int reason);
|
||||
extern void scsi_next_command(struct scsi_cmnd *cmd);
|
||||
|
|
|
@ -41,6 +41,7 @@ struct sas_host_attrs {
|
|||
struct mutex lock;
|
||||
u32 next_target_id;
|
||||
u32 next_expander_id;
|
||||
int next_port_id;
|
||||
};
|
||||
#define to_sas_host_attrs(host) ((struct sas_host_attrs *)(host)->shost_data)
|
||||
|
||||
|
@ -146,6 +147,7 @@ static int sas_host_setup(struct transport_container *tc, struct device *dev,
|
|||
mutex_init(&sas_host->lock);
|
||||
sas_host->next_target_id = 0;
|
||||
sas_host->next_expander_id = 0;
|
||||
sas_host->next_port_id = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -327,7 +329,7 @@ sas_phy_protocol_attr(identify.target_port_protocols,
|
|||
sas_phy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n",
|
||||
unsigned long long);
|
||||
sas_phy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8);
|
||||
//sas_phy_simple_attr(port_identifier, port_identifier, "%d\n", u8);
|
||||
//sas_phy_simple_attr(port_identifier, port_identifier, "%d\n", int);
|
||||
sas_phy_linkspeed_attr(negotiated_linkrate);
|
||||
sas_phy_linkspeed_attr(minimum_linkrate_hw);
|
||||
sas_phy_linkspeed_attr(minimum_linkrate);
|
||||
|
@ -590,6 +592,38 @@ struct sas_port *sas_port_alloc(struct device *parent, int port_id)
|
|||
}
|
||||
EXPORT_SYMBOL(sas_port_alloc);
|
||||
|
||||
/** sas_port_alloc_num - allocate and initialize a SAS port structure
|
||||
*
|
||||
* @parent: parent device
|
||||
*
|
||||
* Allocates a SAS port structure and a number to go with it. This
|
||||
* interface is really for adapters where the port number has no
|
||||
* meansing, so the sas class should manage them. It will be added to
|
||||
* the device tree below the device specified by @parent which must be
|
||||
* either a Scsi_Host or a sas_expander_device.
|
||||
*
|
||||
* Returns %NULL on error
|
||||
*/
|
||||
struct sas_port *sas_port_alloc_num(struct device *parent)
|
||||
{
|
||||
int index;
|
||||
struct Scsi_Host *shost = dev_to_shost(parent);
|
||||
struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
|
||||
|
||||
/* FIXME: use idr for this eventually */
|
||||
mutex_lock(&sas_host->lock);
|
||||
if (scsi_is_sas_expander_device(parent)) {
|
||||
struct sas_rphy *rphy = dev_to_rphy(parent);
|
||||
struct sas_expander_device *exp = rphy_to_expander_device(rphy);
|
||||
|
||||
index = exp->next_port_id++;
|
||||
} else
|
||||
index = sas_host->next_port_id++;
|
||||
mutex_unlock(&sas_host->lock);
|
||||
return sas_port_alloc(parent, index);
|
||||
}
|
||||
EXPORT_SYMBOL(sas_port_alloc_num);
|
||||
|
||||
/**
|
||||
* sas_port_add - add a SAS port to the device hierarchy
|
||||
*
|
||||
|
@ -658,6 +692,13 @@ void sas_port_delete(struct sas_port *port)
|
|||
}
|
||||
mutex_unlock(&port->phy_list_mutex);
|
||||
|
||||
if (port->is_backlink) {
|
||||
struct device *parent = port->dev.parent;
|
||||
|
||||
sysfs_remove_link(&port->dev.kobj, parent->bus_id);
|
||||
port->is_backlink = 0;
|
||||
}
|
||||
|
||||
transport_remove_device(dev);
|
||||
device_del(dev);
|
||||
transport_destroy_device(dev);
|
||||
|
@ -733,6 +774,19 @@ void sas_port_delete_phy(struct sas_port *port, struct sas_phy *phy)
|
|||
}
|
||||
EXPORT_SYMBOL(sas_port_delete_phy);
|
||||
|
||||
void sas_port_mark_backlink(struct sas_port *port)
|
||||
{
|
||||
struct device *parent = port->dev.parent->parent->parent;
|
||||
|
||||
if (port->is_backlink)
|
||||
return;
|
||||
port->is_backlink = 1;
|
||||
sysfs_create_link(&port->dev.kobj, &parent->kobj,
|
||||
parent->bus_id);
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(sas_port_mark_backlink);
|
||||
|
||||
/*
|
||||
* SAS remote PHY attributes.
|
||||
*/
|
||||
|
@ -1140,7 +1194,7 @@ int sas_rphy_add(struct sas_rphy *rphy)
|
|||
|
||||
if (identify->device_type == SAS_END_DEVICE &&
|
||||
rphy->scsi_target_id != -1) {
|
||||
scsi_scan_target(&rphy->dev, parent->port_identifier,
|
||||
scsi_scan_target(&rphy->dev, 0,
|
||||
rphy->scsi_target_id, ~0, 0);
|
||||
}
|
||||
|
||||
|
@ -1242,15 +1296,13 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel,
|
|||
|
||||
mutex_lock(&sas_host->lock);
|
||||
list_for_each_entry(rphy, &sas_host->rphy_list, list) {
|
||||
struct sas_port *parent = dev_to_sas_port(rphy->dev.parent);
|
||||
|
||||
if (rphy->identify.device_type != SAS_END_DEVICE ||
|
||||
rphy->scsi_target_id == -1)
|
||||
continue;
|
||||
|
||||
if ((channel == SCAN_WILD_CARD || channel == parent->port_identifier) &&
|
||||
if ((channel == SCAN_WILD_CARD || channel == 0) &&
|
||||
(id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) {
|
||||
scsi_scan_target(&rphy->dev, parent->port_identifier,
|
||||
scsi_scan_target(&rphy->dev, 0,
|
||||
rphy->scsi_target_id, lun, 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -502,8 +502,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
|
|||
SCpnt->cmnd[4] = (unsigned char) this_count;
|
||||
SCpnt->cmnd[5] = 0;
|
||||
}
|
||||
SCpnt->request_bufflen = SCpnt->bufflen =
|
||||
this_count * sdp->sector_size;
|
||||
SCpnt->request_bufflen = this_count * sdp->sector_size;
|
||||
|
||||
/*
|
||||
* We shouldn't disconnect in the middle of a sector, so with a dumb
|
||||
|
|
|
@ -1002,7 +1002,7 @@ static int internal_command (unsigned char target, unsigned char lun,
|
|||
}
|
||||
#endif
|
||||
|
||||
buffer = (struct scatterlist *) SCint->buffer;
|
||||
buffer = (struct scatterlist *) SCint->request_buffer;
|
||||
len = buffer->length;
|
||||
data = page_address(buffer->page) + buffer->offset;
|
||||
} else {
|
||||
|
|
|
@ -360,7 +360,7 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
|
|||
"mismatch count %d, bytes %d\n",
|
||||
size, SCpnt->request_bufflen);
|
||||
if (SCpnt->request_bufflen > size)
|
||||
SCpnt->request_bufflen = SCpnt->bufflen = size;
|
||||
SCpnt->request_bufflen = size;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -387,8 +387,7 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
|
|||
|
||||
if (this_count > 0xffff) {
|
||||
this_count = 0xffff;
|
||||
SCpnt->request_bufflen = SCpnt->bufflen =
|
||||
this_count * s_size;
|
||||
SCpnt->request_bufflen = this_count * s_size;
|
||||
}
|
||||
|
||||
SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff;
|
||||
|
|
|
@ -368,7 +368,7 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt)
|
|||
SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
|
||||
SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
|
||||
if (cmdstatp->have_sense)
|
||||
__scsi_print_sense("st", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
|
||||
__scsi_print_sense(name, SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
|
||||
} ) /* end DEB */
|
||||
if (!debugging) { /* Abnormal conditions for tape */
|
||||
if (!cmdstatp->have_sense)
|
||||
|
@ -384,9 +384,8 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt)
|
|||
scode != VOLUME_OVERFLOW &&
|
||||
SRpnt->cmd[0] != MODE_SENSE &&
|
||||
SRpnt->cmd[0] != TEST_UNIT_READY) {
|
||||
printk(KERN_WARNING "%s: Error with sense data: ", name);
|
||||
__scsi_print_sense("st", SRpnt->sense,
|
||||
SCSI_SENSE_BUFFERSIZE);
|
||||
|
||||
__scsi_print_sense(name, SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -517,7 +517,7 @@ static __inline__ void initialize_SCp(Scsi_Cmnd *cmd)
|
|||
*/
|
||||
|
||||
if (cmd->use_sg) {
|
||||
cmd->SCp.buffer = (struct scatterlist *) cmd->buffer;
|
||||
cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer;
|
||||
cmd->SCp.buffers_residual = cmd->use_sg - 1;
|
||||
cmd->SCp.ptr = (char *) SGADDR(cmd->SCp.buffer);
|
||||
cmd->SCp.this_residual = cmd->SCp.buffer->length;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue