Merge ../linux-2.6

This commit is contained in:
Mauro Carvalho Chehab 2008-07-27 18:11:53 -03:00
commit eb703027ac
174 changed files with 5276 additions and 1842 deletions

View file

@ -1024,6 +1024,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
intel-mac-v3 Intel Mac Type 3
intel-mac-v4 Intel Mac Type 4
intel-mac-v5 Intel Mac Type 5
intel-mac-auto Intel Mac (detect type according to subsystem id)
macmini Intel Mac Mini (equivalent with type 3)
macbook Intel Mac Book (eq. type 5)
macbook-pro-v1 Intel Mac Book Pro 1st generation (eq. type 3)

View file

@ -73,10 +73,10 @@ recompiled, or use "make C=2" to run sparse on the files whether they need to
be recompiled or not. The latter is a fast way to check the whole tree if you
have already built it.
The optional make variable CHECKFLAGS can be used to pass arguments to sparse.
The build system passes -Wbitwise to sparse automatically. To perform
endianness checks, you may define __CHECK_ENDIAN__:
The optional make variable CF can be used to pass arguments to sparse. The
build system passes -Wbitwise to sparse automatically. To perform endianness
checks, you may define __CHECK_ENDIAN__:
make C=2 CHECKFLAGS="-D__CHECK_ENDIAN__"
make C=2 CF="-D__CHECK_ENDIAN__"
These checks are disabled by default as they generate a host of warnings.

3
Kbuild
View file

@ -43,7 +43,7 @@ $(obj)/$(bounds-file): kernel/bounds.s Kbuild
# 2) Generate asm-offsets.h
#
offsets-file := include/asm-$(SRCARCH)/asm-offsets.h
offsets-file := include/asm/asm-offsets.h
always += $(offsets-file)
targets += $(offsets-file)
@ -81,7 +81,6 @@ arch/$(SRCARCH)/kernel/asm-offsets.s: arch/$(SRCARCH)/kernel/asm-offsets.c \
$(call if_changed_dep,cc_s_c)
$(obj)/$(offsets-file): arch/$(SRCARCH)/kernel/asm-offsets.s Kbuild
$(Q)mkdir -p $(dir $@)
$(call cmd,offsets)
#####

115
Makefile
View file

@ -205,6 +205,9 @@ ifeq ($(ARCH),x86_64)
SRCARCH := x86
endif
# Where to locate arch specific headers
hdr-arch := $(SRCARCH)
KCONFIG_CONFIG ?= .config
# SHELL used by kbuild
@ -326,7 +329,8 @@ AFLAGS_KERNEL =
# Needed to be compatible with the O= option
LINUXINCLUDE := -Iinclude \
$(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) \
-include include/linux/autoconf.h
-I$(srctree)/arch/$(hdr-arch)/include \
-include include/linux/autoconf.h
KBUILD_CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)
@ -922,7 +926,9 @@ ifneq ($(KBUILD_SRC),)
/bin/false; \
fi;
$(Q)if [ ! -d include2 ]; then mkdir -p include2; fi;
$(Q)ln -fsn $(srctree)/include/asm-$(SRCARCH) include2/asm
$(Q)if [ -e $(srctree)/include/asm-$(SRCARCH)/system.h ]; then \
ln -fsn $(srctree)/include/asm-$(SRCARCH) include2/asm; \
fi
endif
# prepare2 creates a makefile if using a separate output directory
@ -948,22 +954,34 @@ export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
# The asm symlink changes when $(ARCH) changes.
# Detect this and ask user to run make mrproper
include/asm: FORCE
$(Q)set -e; asmlink=`readlink include/asm | cut -d '-' -f 2`; \
if [ -L include/asm ]; then \
if [ "$$asmlink" != "$(SRCARCH)" ]; then \
define check-symlink
set -e; \
if [ -L include/asm ]; then \
asmlink=`readlink include/asm | cut -d '-' -f 2`; \
if [ "$$asmlink" != "$(SRCARCH)" ]; then \
echo "ERROR: the symlink $@ points to asm-$$asmlink but asm-$(SRCARCH) was expected"; \
echo " set ARCH or save .config and run 'make mrproper' to fix it"; \
exit 1; \
fi; \
else \
echo ' SYMLINK $@ -> include/asm-$(SRCARCH)'; \
if [ ! -d include ]; then \
mkdir -p include; \
fi; \
ln -fsn asm-$(SRCARCH) $@; \
exit 1; \
fi; \
fi
endef
# We create the target directory of the symlink if it does
# not exist so the test in chack-symlink works and we have a
# directory for generated filesas used by some architectures.
define create-symlink
if [ ! -L include/asm ]; then \
echo ' SYMLINK $@ -> include/asm-$(SRCARCH)'; \
if [ ! -d include/asm-$(SRCARCH) ]; then \
mkdir -p include/asm-$(SRCARCH); \
fi; \
ln -fsn asm-$(SRCARCH) $@; \
fi
endef
include/asm: FORCE
$(Q)$(check-symlink)
$(Q)$(create-symlink)
# Generate some files
# ---------------------------------------------------------------------------
@ -1010,36 +1028,43 @@ firmware_install: FORCE
# ---------------------------------------------------------------------------
# Kernel headers
INSTALL_HDR_PATH=$(objtree)/usr
export INSTALL_HDR_PATH
HDRFILTER=generic i386 x86_64
HDRARCHES=$(filter-out $(HDRFILTER),$(patsubst $(srctree)/include/asm-%/Kbuild,%,$(wildcard $(srctree)/include/asm-*/Kbuild)))
#Default location for installed headers
export INSTALL_HDR_PATH = $(objtree)/usr
hdr-inst := -rR -f $(srctree)/scripts/Makefile.headersinst obj
# Find out where the Kbuild file is located to support
# arch/$(ARCH)/include/asm
hdr-dir = $(strip \
$(if $(wildcard $(srctree)/arch/$(hdr-arch)/include/asm/Kbuild), \
arch/$(hdr-arch)/include/asm, include/asm-$(hdr-arch)))
# If we do an all arch process set dst to asm-$(hdr-arch)
hdr-dst = $(if $(KBUILD_HEADERS), dst=include/asm-$(hdr-arch), dst=include/asm)
PHONY += __headers
__headers: include/linux/version.h scripts_basic FORCE
$(Q)$(MAKE) $(build)=scripts scripts/unifdef
PHONY += headers_install_all
headers_install_all: include/linux/version.h scripts_basic FORCE
$(Q)$(MAKE) $(build)=scripts scripts/unifdef
$(Q)for arch in $(HDRARCHES); do \
$(MAKE) ARCH=$$arch -f $(srctree)/scripts/Makefile.headersinst obj=include BIASMDIR=-bi-$$arch ;\
done
headers_install_all:
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/headers.sh install
PHONY += headers_install
headers_install: include/linux/version.h scripts_basic FORCE
@if [ ! -r $(srctree)/include/asm-$(SRCARCH)/Kbuild ]; then \
echo '*** Error: Headers not exportable for this architecture ($(SRCARCH))'; \
exit 1 ; fi
$(Q)$(MAKE) $(build)=scripts scripts/unifdef
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.headersinst ARCH=$(SRCARCH) obj=include
headers_install: __headers
$(if $(wildcard $(srctree)/$(hdr-dir)/Kbuild),, \
$(error Headers not exportable for the $(SRCARCH) architecture))
$(Q)$(MAKE) $(hdr-inst)=include
$(Q)$(MAKE) $(hdr-inst)=$(hdr-dir) $(hdr-dst)
PHONY += headers_check_all
headers_check_all: headers_install_all
$(Q)for arch in $(HDRARCHES); do \
$(MAKE) ARCH=$$arch -f $(srctree)/scripts/Makefile.headersinst obj=include BIASMDIR=-bi-$$arch HDRCHECK=1 ;\
done
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/headers.sh check
PHONY += headers_check
headers_check: headers_install
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.headersinst ARCH=$(SRCARCH) obj=include HDRCHECK=1
$(Q)$(MAKE) $(hdr-inst)=include HDRCHECK=1
$(Q)$(MAKE) $(hdr-inst)=$(hdr-dir) $(hdr-dst) HDRCHECK=1
# ---------------------------------------------------------------------------
# Modules
@ -1131,7 +1156,7 @@ MRPROPER_FILES += .config .config.old include/asm .version .old_version \
include/linux/autoconf.h include/linux/version.h \
include/linux/utsrelease.h \
include/linux/bounds.h include/asm*/asm-offsets.h \
Module.symvers tags TAGS cscope*
Module.symvers Module.markers tags TAGS cscope*
# clean - Delete most, but leave enough to build external modules
#
@ -1150,7 +1175,7 @@ clean: archclean $(clean-dirs)
\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
-o -name '*.symtypes' -o -name 'modules.order' \
-o -name 'Module.markers' \) \
-o -name 'Module.markers' -o -name '.tmp_*.o.*' \) \
-type f -print | xargs rm -f
# mrproper - Delete all generated files, including .config
@ -1224,21 +1249,17 @@ help:
@echo ' cscope - Generate cscope index'
@echo ' kernelrelease - Output the release version string'
@echo ' kernelversion - Output the version stored in Makefile'
@if [ -r $(srctree)/include/asm-$(SRCARCH)/Kbuild ]; then \
echo ' headers_install - Install sanitised kernel headers to INSTALL_HDR_PATH'; \
@echo ' headers_install - Install sanitised kernel headers to INSTALL_HDR_PATH'; \
echo ' (default: $(INSTALL_HDR_PATH))'; \
fi
@echo ''
echo ''
@echo 'Static analysers'
@echo ' checkstack - Generate a list of stack hogs'
@echo ' namespacecheck - Name space analysis on compiled kernel'
@echo ' versioncheck - Sanity check on version.h usage'
@echo ' includecheck - Check for duplicate included header files'
@echo ' export_report - List the usages of all exported symbols'
@if [ -r $(srctree)/include/asm-$(SRCARCH)/Kbuild ]; then \
echo ' headers_check - Sanity check on exported headers'; \
fi
@echo ''
@echo ' headers_check - Sanity check on exported headers'; \
echo ''
@echo 'Kernel packaging:'
@$(MAKE) $(build)=$(package-dir) help
@echo ''
@ -1411,7 +1432,11 @@ define find-sources
\( -name config -o -name 'asm-*' \) -prune \
-o -name $1 -print; \
for arch in $(ALLINCLUDE_ARCHS) ; do \
find $(__srctree)include/asm-$${arch} $(RCS_FIND_IGNORE) \
test -e $(__srctree)include/asm-$${arch} && \
find $(__srctree)include/asm-$${arch} $(RCS_FIND_IGNORE) \
-name $1 -print; \
test -e $(__srctree)arch/$${arch}/include/asm && \
find $(__srctree)arch/$${arch}/include/asm $(RCS_FIND_IGNORE) \
-name $1 -print; \
done ; \
find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \

View file

@ -21,6 +21,8 @@
#include <asm/io.h>
#include <asm/setup.h>
#include <asm/atmel-mci.h>
#include <asm/arch/at32ap700x.h>
#include <asm/arch/board.h>
#include <asm/arch/init.h>
@ -260,6 +262,21 @@ void __init setup_board(void)
at32_setup_serial_console(0);
}
#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
/* MMC card detect requires MACB0 *NOT* be used */
#ifdef CONFIG_BOARD_ATSTK1002_SW6_CUSTOM
static struct mci_platform_data __initdata mci0_data = {
.detect_pin = GPIO_PIN_PC(14), /* gpio30/sdcd */
.wp_pin = GPIO_PIN_PC(15), /* gpio31/sdwp */
};
#define MCI_PDATA &mci0_data
#else
#define MCI_PDATA NULL
#endif /* SW6 for sd{cd,wp} routing */
#endif /* SW2 for MMC signal routing */
static int __init atstk1002_init(void)
{
/*
@ -309,7 +326,7 @@ static int __init atstk1002_init(void)
at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
#endif
#ifndef CONFIG_BOARD_ATSTK1002_SW2_CUSTOM
at32_add_device_mci(0, NULL);
at32_add_device_mci(0, MCI_PDATA);
#endif
#ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM
set_hw_addr(at32_add_device_eth(1, &eth_data[1]));

View file

@ -154,7 +154,7 @@ static int __init atstk1003_init(void)
at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
#endif
#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
at32_add_device_mci(0);
at32_add_device_mci(0, NULL);
#endif
at32_add_device_usba(0, NULL);
#ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM

View file

@ -137,7 +137,7 @@ static int __init atstk1004_init(void)
at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
#endif
#ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
at32_add_device_mci(0);
at32_add_device_mci(0, NULL);
#endif
at32_add_device_lcdc(0, &atstk1000_lcdc_data,
fbmem_start, fbmem_size, 0);

View file

@ -43,6 +43,9 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id)
{
struct clock_event_device *evdev = dev_id;
if (unlikely(!(intc_get_pending(0) & 1)))
return IRQ_NONE;
/*
* Disable the interrupt until the clockevent subsystem
* reprograms it.
@ -55,7 +58,8 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id)
static struct irqaction timer_irqaction = {
.handler = timer_interrupt,
.flags = IRQF_TIMER | IRQF_DISABLED,
/* Oprofile uses the same irq as the timer, so allow it to be shared */
.flags = IRQF_TIMER | IRQF_DISABLED | IRQF_SHARED,
.name = "avr32_comparator",
};

View file

@ -12,6 +12,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/gpio.h>
#include <linux/spi/spi.h>
#include <linux/usb/atmel_usba_udc.h>
@ -1285,7 +1286,6 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
{
struct mci_platform_data _data;
struct platform_device *pdev;
struct dw_dma_slave *dws;
if (id != 0)
return NULL;
@ -1300,7 +1300,9 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
if (!data) {
data = &_data;
memset(data, 0, sizeof(struct mci_platform_data));
memset(data, -1, sizeof(struct mci_platform_data));
data->detect_pin = GPIO_PIN_NONE;
data->wp_pin = GPIO_PIN_NONE;
}
if (platform_device_add_data(pdev, data,
@ -1314,12 +1316,10 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
select_peripheral(PA(14), PERIPH_A, 0); /* DATA2 */
select_peripheral(PA(15), PERIPH_A, 0); /* DATA3 */
if (data) {
if (data->detect_pin != GPIO_PIN_NONE)
at32_select_gpio(data->detect_pin, 0);
if (data->wp_pin != GPIO_PIN_NONE)
at32_select_gpio(data->wp_pin, 0);
}
if (gpio_is_valid(data->detect_pin))
at32_select_gpio(data->detect_pin, 0);
if (gpio_is_valid(data->wp_pin))
at32_select_gpio(data->wp_pin, 0);
atmel_mci0_pclk.dev = &pdev->dev;
@ -1853,11 +1853,11 @@ at32_add_device_cf(unsigned int id, unsigned int extint,
if (at32_init_ide_or_cf(pdev, data->cs, extint))
goto fail;
if (data->detect_pin != GPIO_PIN_NONE)
if (gpio_is_valid(data->detect_pin))
at32_select_gpio(data->detect_pin, AT32_GPIOF_DEGLITCH);
if (data->reset_pin != GPIO_PIN_NONE)
if (gpio_is_valid(data->reset_pin))
at32_select_gpio(data->reset_pin, 0);
if (data->vcc_pin != GPIO_PIN_NONE)
if (gpio_is_valid(data->vcc_pin))
at32_select_gpio(data->vcc_pin, 0);
/* READY is used as extint, so we can't select it as gpio */
@ -1937,9 +1937,11 @@ static struct clk atmel_ac97c0_pclk = {
.index = 10,
};
struct platform_device *__init at32_add_device_ac97c(unsigned int id)
struct platform_device *__init
at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data)
{
struct platform_device *pdev;
struct ac97c_platform_data _data;
if (id != 0)
return NULL;
@ -1950,19 +1952,37 @@ struct platform_device *__init at32_add_device_ac97c(unsigned int id)
if (platform_device_add_resources(pdev, atmel_ac97c0_resource,
ARRAY_SIZE(atmel_ac97c0_resource)))
goto err_add_resources;
goto fail;
select_peripheral(PB(20), PERIPH_B, 0); /* SYNC */
select_peripheral(PB(21), PERIPH_B, 0); /* SDO */
select_peripheral(PB(22), PERIPH_B, 0); /* SDI */
select_peripheral(PB(23), PERIPH_B, 0); /* SCLK */
if (!data) {
data = &_data;
memset(data, 0, sizeof(struct ac97c_platform_data));
data->reset_pin = GPIO_PIN_NONE;
}
data->dma_rx_periph_id = 3;
data->dma_tx_periph_id = 4;
data->dma_controller_id = 0;
if (platform_device_add_data(pdev, data,
sizeof(struct ac97c_platform_data)))
goto fail;
select_peripheral(PB(20), PERIPH_B, 0); /* SDO */
select_peripheral(PB(21), PERIPH_B, 0); /* SYNC */
select_peripheral(PB(22), PERIPH_B, 0); /* SCLK */
select_peripheral(PB(23), PERIPH_B, 0); /* SDI */
/* TODO: gpio_is_valid(data->reset_pin) with kernel 2.6.26. */
if (data->reset_pin != GPIO_PIN_NONE)
at32_select_gpio(data->reset_pin, 0);
atmel_ac97c0_pclk.dev = &pdev->dev;
platform_device_add(pdev);
return pdev;
err_add_resources:
fail:
platform_device_put(pdev);
return NULL;
}

View file

@ -125,9 +125,9 @@ void kvm_arch_hardware_enable(void *garbage)
PAGE_KERNEL));
local_irq_save(saved_psr);
slot = ia64_itr_entry(0x3, KVM_VMM_BASE, pte, KVM_VMM_SHIFT);
local_irq_restore(saved_psr);
if (slot < 0)
return;
local_irq_restore(saved_psr);
spin_lock(&vp_lock);
status = ia64_pal_vp_init_env(kvm_vsa_base ?
@ -160,9 +160,9 @@ void kvm_arch_hardware_disable(void *garbage)
local_irq_save(saved_psr);
slot = ia64_itr_entry(0x3, KVM_VMM_BASE, pte, KVM_VMM_SHIFT);
local_irq_restore(saved_psr);
if (slot < 0)
return;
local_irq_restore(saved_psr);
status = ia64_pal_vp_exit_env(host_iva);
if (status)
@ -1253,6 +1253,7 @@ static int vti_vcpu_setup(struct kvm_vcpu *vcpu, int id)
uninit:
kvm_vcpu_uninit(vcpu);
fail:
local_irq_restore(psr);
return r;
}

View file

@ -177,7 +177,8 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn, u64 asid,
vcpu->arch.msr & MSR_PR);
}
void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, u64 eaddr, u64 asid)
void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, gva_t eaddr,
gva_t eend, u32 asid)
{
unsigned int pid = asid & 0xff;
int i;
@ -191,7 +192,7 @@ void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, u64 eaddr, u64 asid)
if (!get_tlb_v(stlbe))
continue;
if (eaddr < get_tlb_eaddr(stlbe))
if (eend < get_tlb_eaddr(stlbe))
continue;
if (eaddr > get_tlb_end(stlbe))

View file

@ -137,7 +137,7 @@ static int kvmppc_emul_tlbwe(struct kvm_vcpu *vcpu, u32 inst)
if (tlbe->word0 & PPC44x_TLB_VALID) {
eaddr = get_tlb_eaddr(tlbe);
asid = (tlbe->word0 & PPC44x_TLB_TS) | tlbe->tid;
kvmppc_mmu_invalidate(vcpu, eaddr, asid);
kvmppc_mmu_invalidate(vcpu, eaddr, get_tlb_end(tlbe), asid);
}
switch (ws) {

View file

@ -18,11 +18,11 @@
#include <asm/uaccess.h>
static inline void __user *__guestaddr_to_user(struct kvm_vcpu *vcpu,
u64 guestaddr)
unsigned long guestaddr)
{
u64 prefix = vcpu->arch.sie_block->prefix;
u64 origin = vcpu->kvm->arch.guest_origin;
u64 memsize = vcpu->kvm->arch.guest_memsize;
unsigned long prefix = vcpu->arch.sie_block->prefix;
unsigned long origin = vcpu->kvm->arch.guest_origin;
unsigned long memsize = vcpu->kvm->arch.guest_memsize;
if (guestaddr < 2 * PAGE_SIZE)
guestaddr += prefix;
@ -37,7 +37,7 @@ static inline void __user *__guestaddr_to_user(struct kvm_vcpu *vcpu,
return (void __user *) guestaddr;
}
static inline int get_guest_u64(struct kvm_vcpu *vcpu, u64 guestaddr,
static inline int get_guest_u64(struct kvm_vcpu *vcpu, unsigned long guestaddr,
u64 *result)
{
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
@ -47,10 +47,10 @@ static inline int get_guest_u64(struct kvm_vcpu *vcpu, u64 guestaddr,
if (IS_ERR((void __force *) uptr))
return PTR_ERR((void __force *) uptr);
return get_user(*result, (u64 __user *) uptr);
return get_user(*result, (unsigned long __user *) uptr);
}
static inline int get_guest_u32(struct kvm_vcpu *vcpu, u64 guestaddr,
static inline int get_guest_u32(struct kvm_vcpu *vcpu, unsigned long guestaddr,
u32 *result)
{
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
@ -63,7 +63,7 @@ static inline int get_guest_u32(struct kvm_vcpu *vcpu, u64 guestaddr,
return get_user(*result, (u32 __user *) uptr);
}
static inline int get_guest_u16(struct kvm_vcpu *vcpu, u64 guestaddr,
static inline int get_guest_u16(struct kvm_vcpu *vcpu, unsigned long guestaddr,
u16 *result)
{
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
@ -76,7 +76,7 @@ static inline int get_guest_u16(struct kvm_vcpu *vcpu, u64 guestaddr,
return get_user(*result, (u16 __user *) uptr);
}
static inline int get_guest_u8(struct kvm_vcpu *vcpu, u64 guestaddr,
static inline int get_guest_u8(struct kvm_vcpu *vcpu, unsigned long guestaddr,
u8 *result)
{
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
@ -87,7 +87,7 @@ static inline int get_guest_u8(struct kvm_vcpu *vcpu, u64 guestaddr,
return get_user(*result, (u8 __user *) uptr);
}
static inline int put_guest_u64(struct kvm_vcpu *vcpu, u64 guestaddr,
static inline int put_guest_u64(struct kvm_vcpu *vcpu, unsigned long guestaddr,
u64 value)
{
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
@ -100,7 +100,7 @@ static inline int put_guest_u64(struct kvm_vcpu *vcpu, u64 guestaddr,
return put_user(value, (u64 __user *) uptr);
}
static inline int put_guest_u32(struct kvm_vcpu *vcpu, u64 guestaddr,
static inline int put_guest_u32(struct kvm_vcpu *vcpu, unsigned long guestaddr,
u32 value)
{
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
@ -113,7 +113,7 @@ static inline int put_guest_u32(struct kvm_vcpu *vcpu, u64 guestaddr,
return put_user(value, (u32 __user *) uptr);
}
static inline int put_guest_u16(struct kvm_vcpu *vcpu, u64 guestaddr,
static inline int put_guest_u16(struct kvm_vcpu *vcpu, unsigned long guestaddr,
u16 value)
{
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
@ -126,7 +126,7 @@ static inline int put_guest_u16(struct kvm_vcpu *vcpu, u64 guestaddr,
return put_user(value, (u16 __user *) uptr);
}
static inline int put_guest_u8(struct kvm_vcpu *vcpu, u64 guestaddr,
static inline int put_guest_u8(struct kvm_vcpu *vcpu, unsigned long guestaddr,
u8 value)
{
void __user *uptr = __guestaddr_to_user(vcpu, guestaddr);
@ -138,7 +138,8 @@ static inline int put_guest_u8(struct kvm_vcpu *vcpu, u64 guestaddr,
}
static inline int __copy_to_guest_slow(struct kvm_vcpu *vcpu, u64 guestdest,
static inline int __copy_to_guest_slow(struct kvm_vcpu *vcpu,
unsigned long guestdest,
const void *from, unsigned long n)
{
int rc;
@ -153,12 +154,12 @@ static inline int __copy_to_guest_slow(struct kvm_vcpu *vcpu, u64 guestdest,
return 0;
}
static inline int copy_to_guest(struct kvm_vcpu *vcpu, u64 guestdest,
static inline int copy_to_guest(struct kvm_vcpu *vcpu, unsigned long guestdest,
const void *from, unsigned long n)
{
u64 prefix = vcpu->arch.sie_block->prefix;
u64 origin = vcpu->kvm->arch.guest_origin;
u64 memsize = vcpu->kvm->arch.guest_memsize;
unsigned long prefix = vcpu->arch.sie_block->prefix;
unsigned long origin = vcpu->kvm->arch.guest_origin;
unsigned long memsize = vcpu->kvm->arch.guest_memsize;
if ((guestdest < 2 * PAGE_SIZE) && (guestdest + n > 2 * PAGE_SIZE))
goto slowpath;
@ -189,7 +190,8 @@ slowpath:
}
static inline int __copy_from_guest_slow(struct kvm_vcpu *vcpu, void *to,
u64 guestsrc, unsigned long n)
unsigned long guestsrc,
unsigned long n)
{
int rc;
unsigned long i;
@ -204,11 +206,11 @@ static inline int __copy_from_guest_slow(struct kvm_vcpu *vcpu, void *to,
}
static inline int copy_from_guest(struct kvm_vcpu *vcpu, void *to,
u64 guestsrc, unsigned long n)
unsigned long guestsrc, unsigned long n)
{
u64 prefix = vcpu->arch.sie_block->prefix;
u64 origin = vcpu->kvm->arch.guest_origin;
u64 memsize = vcpu->kvm->arch.guest_memsize;
unsigned long prefix = vcpu->arch.sie_block->prefix;
unsigned long origin = vcpu->kvm->arch.guest_origin;
unsigned long memsize = vcpu->kvm->arch.guest_memsize;
if ((guestsrc < 2 * PAGE_SIZE) && (guestsrc + n > 2 * PAGE_SIZE))
goto slowpath;
@ -238,11 +240,12 @@ slowpath:
return __copy_from_guest_slow(vcpu, to, guestsrc, n);
}
static inline int copy_to_guest_absolute(struct kvm_vcpu *vcpu, u64 guestdest,
static inline int copy_to_guest_absolute(struct kvm_vcpu *vcpu,
unsigned long guestdest,
const void *from, unsigned long n)
{
u64 origin = vcpu->kvm->arch.guest_origin;
u64 memsize = vcpu->kvm->arch.guest_memsize;
unsigned long origin = vcpu->kvm->arch.guest_origin;
unsigned long memsize = vcpu->kvm->arch.guest_memsize;
if (guestdest + n > memsize)
return -EFAULT;
@ -256,10 +259,11 @@ static inline int copy_to_guest_absolute(struct kvm_vcpu *vcpu, u64 guestdest,
}
static inline int copy_from_guest_absolute(struct kvm_vcpu *vcpu, void *to,
u64 guestsrc, unsigned long n)
unsigned long guestsrc,
unsigned long n)
{
u64 origin = vcpu->kvm->arch.guest_origin;
u64 memsize = vcpu->kvm->arch.guest_memsize;
unsigned long origin = vcpu->kvm->arch.guest_origin;
unsigned long memsize = vcpu->kvm->arch.guest_memsize;
if (guestsrc + n > memsize)
return -EFAULT;

View file

@ -20,7 +20,7 @@
#include "kvm-s390.h"
#include "gaccess.h"
static int handle_lctg(struct kvm_vcpu *vcpu)
static int handle_lctlg(struct kvm_vcpu *vcpu)
{
int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
int reg3 = vcpu->arch.sie_block->ipa & 0x000f;
@ -30,7 +30,7 @@ static int handle_lctg(struct kvm_vcpu *vcpu)
u64 useraddr;
int reg, rc;
vcpu->stat.instruction_lctg++;
vcpu->stat.instruction_lctlg++;
if ((vcpu->arch.sie_block->ipb & 0xff) != 0x2f)
return -ENOTSUPP;
@ -38,9 +38,12 @@ static int handle_lctg(struct kvm_vcpu *vcpu)
if (base2)
useraddr += vcpu->arch.guest_gprs[base2];
if (useraddr & 7)
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
reg = reg1;
VCPU_EVENT(vcpu, 5, "lctg r1:%x, r3:%x,b2:%x,d2:%x", reg1, reg3, base2,
VCPU_EVENT(vcpu, 5, "lctlg r1:%x, r3:%x,b2:%x,d2:%x", reg1, reg3, base2,
disp2);
do {
@ -74,6 +77,9 @@ static int handle_lctl(struct kvm_vcpu *vcpu)
if (base2)
useraddr += vcpu->arch.guest_gprs[base2];
if (useraddr & 3)
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
VCPU_EVENT(vcpu, 5, "lctl r1:%x, r3:%x,b2:%x,d2:%x", reg1, reg3, base2,
disp2);
@ -99,7 +105,7 @@ static intercept_handler_t instruction_handlers[256] = {
[0xae] = kvm_s390_handle_sigp,
[0xb2] = kvm_s390_handle_priv,
[0xb7] = handle_lctl,
[0xeb] = handle_lctg,
[0xeb] = handle_lctlg,
};
static int handle_noop(struct kvm_vcpu *vcpu)

View file

@ -13,6 +13,7 @@
#include <asm/lowcore.h>
#include <asm/uaccess.h>
#include <linux/kvm_host.h>
#include <linux/signal.h>
#include "kvm-s390.h"
#include "gaccess.h"
@ -246,15 +247,10 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
default:
BUG();
}
if (exception) {
VCPU_EVENT(vcpu, 1, "%s", "program exception while delivering"
" interrupt");
kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
if (inti->type == KVM_S390_PROGRAM_INT) {
printk(KERN_WARNING "kvm: recursive program check\n");
BUG();
}
printk("kvm: The guest lowcore is not mapped during interrupt "
"delivery, killing userspace\n");
do_exit(SIGKILL);
}
}
@ -277,14 +273,11 @@ static int __try_deliver_ckc_interrupt(struct kvm_vcpu *vcpu)
__LC_EXT_NEW_PSW, sizeof(psw_t));
if (rc == -EFAULT)
exception = 1;
if (exception) {
VCPU_EVENT(vcpu, 1, "%s", "program exception while delivering" \
" ckc interrupt");
kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
return 0;
printk("kvm: The guest lowcore is not mapped during interrupt "
"delivery, killing userspace\n");
do_exit(SIGKILL);
}
return 1;
}

View file

@ -39,7 +39,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
{ "exit_instruction", VCPU_STAT(exit_instruction) },
{ "exit_program_interruption", VCPU_STAT(exit_program_interruption) },
{ "exit_instr_and_program_int", VCPU_STAT(exit_instr_and_program) },
{ "instruction_lctg", VCPU_STAT(instruction_lctg) },
{ "instruction_lctlg", VCPU_STAT(instruction_lctlg) },
{ "instruction_lctl", VCPU_STAT(instruction_lctl) },
{ "deliver_emergency_signal", VCPU_STAT(deliver_emergency_signal) },
{ "deliver_service_signal", VCPU_STAT(deliver_service_signal) },
@ -112,7 +112,12 @@ long kvm_arch_dev_ioctl(struct file *filp,
int kvm_dev_ioctl_check_extension(long ext)
{
return 0;
switch (ext) {
case KVM_CAP_USER_MEMORY:
return 1;
default:
return 0;
}
}
/* Section: vm related */

View file

@ -43,7 +43,8 @@
#define SIGP_STAT_RECEIVER_CHECK 0x00000001UL
static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr, u64 *reg)
static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr,
unsigned long *reg)
{
struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
int rc;
@ -167,7 +168,7 @@ static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter)
}
static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
u64 *reg)
unsigned long *reg)
{
struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
struct kvm_s390_local_interrupt *li;

View file

@ -1814,6 +1814,7 @@ int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva)
spin_unlock(&vcpu->kvm->mmu_lock);
return r;
}
EXPORT_SYMBOL_GPL(kvm_mmu_unprotect_page_virt);
void __kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu)
{
@ -1870,6 +1871,12 @@ void kvm_enable_tdp(void)
}
EXPORT_SYMBOL_GPL(kvm_enable_tdp);
void kvm_disable_tdp(void)
{
tdp_enabled = false;
}
EXPORT_SYMBOL_GPL(kvm_disable_tdp);
static void free_mmu_pages(struct kvm_vcpu *vcpu)
{
struct kvm_mmu_page *sp;

View file

@ -453,7 +453,8 @@ static __init int svm_hardware_setup(void)
if (npt_enabled) {
printk(KERN_INFO "kvm: Nested Paging enabled\n");
kvm_enable_tdp();
}
} else
kvm_disable_tdp();
return 0;
@ -1007,10 +1008,13 @@ static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
struct kvm *kvm = svm->vcpu.kvm;
u64 fault_address;
u32 error_code;
bool event_injection = false;
if (!irqchip_in_kernel(kvm) &&
is_external_interrupt(exit_int_info))
is_external_interrupt(exit_int_info)) {
event_injection = true;
push_irq(&svm->vcpu, exit_int_info & SVM_EVTINJ_VEC_MASK);
}
fault_address = svm->vmcb->control.exit_info_2;
error_code = svm->vmcb->control.exit_info_1;
@ -1024,6 +1028,8 @@ static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
(u32)fault_address, (u32)(fault_address >> 32),
handler);
if (event_injection)
kvm_mmu_unprotect_page_virt(&svm->vcpu, fault_address);
return kvm_mmu_page_fault(&svm->vcpu, fault_address, error_code);
}

View file

@ -2298,6 +2298,8 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
cr2 = vmcs_readl(EXIT_QUALIFICATION);
KVMTRACE_3D(PAGE_FAULT, vcpu, error_code, (u32)cr2,
(u32)((u64)cr2 >> 32), handler);
if (vect_info & VECTORING_INFO_VALID_MASK)
kvm_mmu_unprotect_page_virt(vcpu, cr2);
return kvm_mmu_page_fault(vcpu, cr2, error_code);
}
@ -3116,15 +3118,6 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
return ERR_PTR(-ENOMEM);
allocate_vpid(vmx);
if (id == 0 && vm_need_ept()) {
kvm_mmu_set_base_ptes(VMX_EPT_READABLE_MASK |
VMX_EPT_WRITABLE_MASK |
VMX_EPT_DEFAULT_MT << VMX_EPT_MT_EPTE_SHIFT);
kvm_mmu_set_mask_ptes(0ull, VMX_EPT_FAKE_ACCESSED_MASK,
VMX_EPT_FAKE_DIRTY_MASK, 0ull,
VMX_EPT_EXECUTABLE_MASK);
kvm_enable_tdp();
}
err = kvm_vcpu_init(&vmx->vcpu, kvm, id);
if (err)
@ -3303,8 +3296,17 @@ static int __init vmx_init(void)
vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_IA32_SYSENTER_ESP);
vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_IA32_SYSENTER_EIP);
if (cpu_has_vmx_ept())
if (vm_need_ept()) {
bypass_guest_pf = 0;
kvm_mmu_set_base_ptes(VMX_EPT_READABLE_MASK |
VMX_EPT_WRITABLE_MASK |
VMX_EPT_DEFAULT_MT << VMX_EPT_MT_EPTE_SHIFT);
kvm_mmu_set_mask_ptes(0ull, VMX_EPT_FAKE_ACCESSED_MASK,
VMX_EPT_FAKE_DIRTY_MASK, 0ull,
VMX_EPT_EXECUTABLE_MASK);
kvm_enable_tdp();
} else
kvm_disable_tdp();
if (bypass_guest_pf)
kvm_mmu_set_nonpresent_ptes(~0xffeull, 0ull);

View file

@ -3184,6 +3184,10 @@ static void seg_desct_to_kvm_desct(struct desc_struct *seg_desc, u16 selector,
kvm_desct->base |= seg_desc->base2 << 24;
kvm_desct->limit = seg_desc->limit0;
kvm_desct->limit |= seg_desc->limit << 16;
if (seg_desc->g) {
kvm_desct->limit <<= 12;
kvm_desct->limit |= 0xfff;
}
kvm_desct->selector = selector;
kvm_desct->type = seg_desc->type;
kvm_desct->present = seg_desc->p;
@ -3223,6 +3227,7 @@ static void get_segment_descritptor_dtable(struct kvm_vcpu *vcpu,
static int load_guest_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector,
struct desc_struct *seg_desc)
{
gpa_t gpa;
struct descriptor_table dtable;
u16 index = selector >> 3;
@ -3232,13 +3237,16 @@ static int load_guest_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector,
kvm_queue_exception_e(vcpu, GP_VECTOR, selector & 0xfffc);
return 1;
}
return kvm_read_guest(vcpu->kvm, dtable.base + index * 8, seg_desc, 8);
gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, dtable.base);
gpa += index * 8;
return kvm_read_guest(vcpu->kvm, gpa, seg_desc, 8);
}
/* allowed just for 8 bytes segments */
static int save_guest_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector,
struct desc_struct *seg_desc)
{
gpa_t gpa;
struct descriptor_table dtable;
u16 index = selector >> 3;
@ -3246,7 +3254,9 @@ static int save_guest_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector,
if (dtable.limit < index * 8 + 7)
return 1;
return kvm_write_guest(vcpu->kvm, dtable.base + index * 8, seg_desc, 8);
gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, dtable.base);
gpa += index * 8;
return kvm_write_guest(vcpu->kvm, gpa, seg_desc, 8);
}
static u32 get_tss_base_addr(struct kvm_vcpu *vcpu,
@ -3258,55 +3268,7 @@ static u32 get_tss_base_addr(struct kvm_vcpu *vcpu,
base_addr |= (seg_desc->base1 << 16);
base_addr |= (seg_desc->base2 << 24);
return base_addr;
}
static int load_tss_segment32(struct kvm_vcpu *vcpu,
struct desc_struct *seg_desc,
struct tss_segment_32 *tss)
{
u32 base_addr;
base_addr = get_tss_base_addr(vcpu, seg_desc);
return kvm_read_guest(vcpu->kvm, base_addr, tss,
sizeof(struct tss_segment_32));
}
static int save_tss_segment32(struct kvm_vcpu *vcpu,
struct desc_struct *seg_desc,
struct tss_segment_32 *tss)
{
u32 base_addr;
base_addr = get_tss_base_addr(vcpu, seg_desc);
return kvm_write_guest(vcpu->kvm, base_addr, tss,
sizeof(struct tss_segment_32));
}
static int load_tss_segment16(struct kvm_vcpu *vcpu,
struct desc_struct *seg_desc,
struct tss_segment_16 *tss)
{
u32 base_addr;
base_addr = get_tss_base_addr(vcpu, seg_desc);
return kvm_read_guest(vcpu->kvm, base_addr, tss,
sizeof(struct tss_segment_16));
}
static int save_tss_segment16(struct kvm_vcpu *vcpu,
struct desc_struct *seg_desc,
struct tss_segment_16 *tss)
{
u32 base_addr;
base_addr = get_tss_base_addr(vcpu, seg_desc);
return kvm_write_guest(vcpu->kvm, base_addr, tss,
sizeof(struct tss_segment_16));
return vcpu->arch.mmu.gva_to_gpa(vcpu, base_addr);
}
static u16 get_segment_selector(struct kvm_vcpu *vcpu, int seg)
@ -3466,20 +3428,26 @@ static int load_state_from_tss16(struct kvm_vcpu *vcpu,
}
static int kvm_task_switch_16(struct kvm_vcpu *vcpu, u16 tss_selector,
struct desc_struct *cseg_desc,
u32 old_tss_base,
struct desc_struct *nseg_desc)
{
struct tss_segment_16 tss_segment_16;
int ret = 0;
if (load_tss_segment16(vcpu, cseg_desc, &tss_segment_16))
if (kvm_read_guest(vcpu->kvm, old_tss_base, &tss_segment_16,
sizeof tss_segment_16))
goto out;
save_state_to_tss16(vcpu, &tss_segment_16);
save_tss_segment16(vcpu, cseg_desc, &tss_segment_16);
if (load_tss_segment16(vcpu, nseg_desc, &tss_segment_16))
if (kvm_write_guest(vcpu->kvm, old_tss_base, &tss_segment_16,
sizeof tss_segment_16))
goto out;
if (kvm_read_guest(vcpu->kvm, get_tss_base_addr(vcpu, nseg_desc),
&tss_segment_16, sizeof tss_segment_16))
goto out;
if (load_state_from_tss16(vcpu, &tss_segment_16))
goto out;
@ -3489,20 +3457,26 @@ out:
}
static int kvm_task_switch_32(struct kvm_vcpu *vcpu, u16 tss_selector,
struct desc_struct *cseg_desc,
u32 old_tss_base,
struct desc_struct *nseg_desc)
{
struct tss_segment_32 tss_segment_32;
int ret = 0;
if (load_tss_segment32(vcpu, cseg_desc, &tss_segment_32))
if (kvm_read_guest(vcpu->kvm, old_tss_base, &tss_segment_32,
sizeof tss_segment_32))
goto out;
save_state_to_tss32(vcpu, &tss_segment_32);
save_tss_segment32(vcpu, cseg_desc, &tss_segment_32);
if (load_tss_segment32(vcpu, nseg_desc, &tss_segment_32))
if (kvm_write_guest(vcpu->kvm, old_tss_base, &tss_segment_32,
sizeof tss_segment_32))
goto out;
if (kvm_read_guest(vcpu->kvm, get_tss_base_addr(vcpu, nseg_desc),
&tss_segment_32, sizeof tss_segment_32))
goto out;
if (load_state_from_tss32(vcpu, &tss_segment_32))
goto out;
@ -3517,16 +3491,20 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason)
struct desc_struct cseg_desc;
struct desc_struct nseg_desc;
int ret = 0;
u32 old_tss_base = get_segment_base(vcpu, VCPU_SREG_TR);
u16 old_tss_sel = get_segment_selector(vcpu, VCPU_SREG_TR);
kvm_get_segment(vcpu, &tr_seg, VCPU_SREG_TR);
old_tss_base = vcpu->arch.mmu.gva_to_gpa(vcpu, old_tss_base);
/* FIXME: Handle errors. Failure to read either TSS or their
* descriptors should generate a pagefault.
*/
if (load_guest_segment_descriptor(vcpu, tss_selector, &nseg_desc))
goto out;
if (load_guest_segment_descriptor(vcpu, tr_seg.selector, &cseg_desc))
if (load_guest_segment_descriptor(vcpu, old_tss_sel, &cseg_desc))
goto out;
if (reason != TASK_SWITCH_IRET) {
int cpl;
@ -3544,8 +3522,7 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason)
if (reason == TASK_SWITCH_IRET || reason == TASK_SWITCH_JMP) {
cseg_desc.type &= ~(1 << 1); //clear the B flag
save_guest_segment_descriptor(vcpu, tr_seg.selector,
&cseg_desc);
save_guest_segment_descriptor(vcpu, old_tss_sel, &cseg_desc);
}
if (reason == TASK_SWITCH_IRET) {
@ -3557,10 +3534,10 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason)
kvm_x86_ops->cache_regs(vcpu);
if (nseg_desc.type & 8)
ret = kvm_task_switch_32(vcpu, tss_selector, &cseg_desc,
ret = kvm_task_switch_32(vcpu, tss_selector, old_tss_base,
&nseg_desc);
else
ret = kvm_task_switch_16(vcpu, tss_selector, &cseg_desc,
ret = kvm_task_switch_16(vcpu, tss_selector, old_tss_base,
&nseg_desc);
if (reason == TASK_SWITCH_CALL || reason == TASK_SWITCH_GATE) {

View file

@ -99,6 +99,9 @@ struct talitos_private {
/* next channel to be assigned next incoming descriptor */
atomic_t last_chan;
/* per-channel number of requests pending in channel h/w fifo */
atomic_t *submit_count;
/* per-channel request fifo */
struct talitos_request **fifo;
@ -263,15 +266,15 @@ static int talitos_submit(struct device *dev, struct talitos_desc *desc,
spin_lock_irqsave(&priv->head_lock[ch], flags);
head = priv->head[ch];
request = &priv->fifo[ch][head];
if (request->desc) {
/* request queue is full */
if (!atomic_inc_not_zero(&priv->submit_count[ch])) {
/* h/w fifo is full */
spin_unlock_irqrestore(&priv->head_lock[ch], flags);
return -EAGAIN;
}
head = priv->head[ch];
request = &priv->fifo[ch][head];
/* map descriptor and save caller data */
request->dma_desc = dma_map_single(dev, desc, sizeof(*desc),
DMA_BIDIRECTIONAL);
@ -335,6 +338,9 @@ static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
priv->tail[ch] = (tail + 1) & (priv->fifo_len - 1);
spin_unlock_irqrestore(&priv->tail_lock[ch], flags);
atomic_dec(&priv->submit_count[ch]);
saved_req.callback(dev, saved_req.desc, saved_req.context,
status);
/* channel may resume processing in single desc error case */
@ -842,7 +848,7 @@ static int sg_to_link_tbl(struct scatterlist *sg, int sg_count,
/* adjust (decrease) last one (or two) entry's len to cryptlen */
link_tbl_ptr--;
while (link_tbl_ptr->len <= (-cryptlen)) {
while (be16_to_cpu(link_tbl_ptr->len) <= (-cryptlen)) {
/* Empty this entry, and move to previous one */
cryptlen += be16_to_cpu(link_tbl_ptr->len);
link_tbl_ptr->len = 0;
@ -874,7 +880,7 @@ static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq,
unsigned int cryptlen = areq->cryptlen;
unsigned int authsize = ctx->authsize;
unsigned int ivsize;
int sg_count;
int sg_count, ret;
/* hmac key */
map_single_talitos_ptr(dev, &desc->ptr[0], ctx->authkeylen, &ctx->key,
@ -978,7 +984,12 @@ static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq,
map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv, 0,
DMA_FROM_DEVICE);
return talitos_submit(dev, desc, callback, areq);
ret = talitos_submit(dev, desc, callback, areq);
if (ret != -EINPROGRESS) {
ipsec_esp_unmap(dev, edesc, areq);
kfree(edesc);
}
return ret;
}
@ -1009,6 +1020,8 @@ static struct ipsec_esp_edesc *ipsec_esp_edesc_alloc(struct aead_request *areq,
struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
struct ipsec_esp_edesc *edesc;
int src_nents, dst_nents, alloc_len, dma_len;
gfp_t flags = areq->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
GFP_ATOMIC;
if (areq->cryptlen + ctx->authsize > TALITOS_MAX_DATA_LEN) {
dev_err(ctx->dev, "cryptlen exceeds h/w max limit\n");
@ -1022,7 +1035,7 @@ static struct ipsec_esp_edesc *ipsec_esp_edesc_alloc(struct aead_request *areq,
dst_nents = src_nents;
} else {
dst_nents = sg_count(areq->dst, areq->cryptlen + ctx->authsize);
dst_nents = (dst_nents == 1) ? 0 : src_nents;
dst_nents = (dst_nents == 1) ? 0 : dst_nents;
}
/*
@ -1040,7 +1053,7 @@ static struct ipsec_esp_edesc *ipsec_esp_edesc_alloc(struct aead_request *areq,
alloc_len += icv_stashing ? ctx->authsize : 0;
}
edesc = kmalloc(alloc_len, GFP_DMA);
edesc = kmalloc(alloc_len, GFP_DMA | flags);
if (!edesc) {
dev_err(ctx->dev, "could not allocate edescriptor\n");
return ERR_PTR(-ENOMEM);
@ -1337,6 +1350,7 @@ static int __devexit talitos_remove(struct of_device *ofdev)
if (hw_supports(dev, DESC_HDR_SEL0_RNG))
talitos_unregister_rng(dev);
kfree(priv->submit_count);
kfree(priv->tail);
kfree(priv->head);
@ -1466,9 +1480,6 @@ static int talitos_probe(struct of_device *ofdev,
goto err_out;
}
of_node_put(np);
np = NULL;
priv->head_lock = kmalloc(sizeof(spinlock_t) * priv->num_channels,
GFP_KERNEL);
priv->tail_lock = kmalloc(sizeof(spinlock_t) * priv->num_channels,
@ -1504,6 +1515,16 @@ static int talitos_probe(struct of_device *ofdev,
}
}
priv->submit_count = kmalloc(sizeof(atomic_t) * priv->num_channels,
GFP_KERNEL);
if (!priv->submit_count) {
dev_err(dev, "failed to allocate fifo submit count space\n");
err = -ENOMEM;
goto err_out;
}
for (i = 0; i < priv->num_channels; i++)
atomic_set(&priv->submit_count[i], -priv->chfifo_len);
priv->head = kzalloc(sizeof(int) * priv->num_channels, GFP_KERNEL);
priv->tail = kzalloc(sizeof(int) * priv->num_channels, GFP_KERNEL);
if (!priv->head || !priv->tail) {
@ -1559,8 +1580,6 @@ static int talitos_probe(struct of_device *ofdev,
err_out:
talitos_remove(ofdev);
if (np)
of_node_put(np);
return err;
}

View file

@ -16,8 +16,13 @@ config FIREWIRE
enable the new stack.
To compile this driver as a module, say M here: the module will be
called firewire-core. It functionally replaces ieee1394, raw1394,
and video1394.
called firewire-core.
This module functionally replaces ieee1394, raw1394, and video1394.
To access it from application programs, you generally need at least
libraw1394 version 2. IIDC/DCAM applications also need libdc1394
version 2. No libraries are required to access storage devices
through the firewire-sbp2 driver.
config FIREWIRE_OHCI
tristate "OHCI-1394 controllers"

View file

@ -539,7 +539,7 @@ fw_core_remove_card(struct fw_card *card)
wait_for_completion(&card->done);
cancel_delayed_work_sync(&card->work);
fw_flush_transactions(card);
WARN_ON(!list_empty(&card->transaction_list));
del_timer_sync(&card->flush_timer);
}
EXPORT_SYMBOL(fw_core_remove_card);

View file

@ -382,9 +382,9 @@ complete_transaction(struct fw_card *card, int rcode,
response->response.type = FW_CDEV_EVENT_RESPONSE;
response->response.rcode = rcode;
queue_event(client, &response->event,
&response->response, sizeof(response->response),
response->response.data, response->response.length);
queue_event(client, &response->event, &response->response,
sizeof(response->response) + response->response.length,
NULL, 0);
}
static int ioctl_send_request(struct client *client, void *buffer)

View file

@ -171,7 +171,6 @@ struct iso_context {
struct fw_ohci {
struct fw_card card;
u32 version;
__iomem char *registers;
dma_addr_t self_id_bus;
__le32 *self_id_cpu;
@ -180,6 +179,8 @@ struct fw_ohci {
int generation;
int request_generation; /* for timestamping incoming requests */
u32 bus_seconds;
bool use_dualbuffer;
bool old_uninorth;
bool bus_reset_packet_quirk;
@ -1885,7 +1886,7 @@ ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size)
} else {
mask = &ohci->ir_context_mask;
list = ohci->ir_context_list;
if (ohci->version >= OHCI_VERSION_1_1)
if (ohci->use_dualbuffer)
callback = handle_ir_dualbuffer_packet;
else
callback = handle_ir_packet_per_buffer;
@ -1949,7 +1950,7 @@ static int ohci_start_iso(struct fw_iso_context *base,
} else {
index = ctx - ohci->ir_context_list;
control = IR_CONTEXT_ISOCH_HEADER;
if (ohci->version >= OHCI_VERSION_1_1)
if (ohci->use_dualbuffer)
control |= IR_CONTEXT_DUAL_BUFFER_MODE;
match = (tags << 28) | (sync << 8) | ctx->base.channel;
if (cycle >= 0) {
@ -2279,7 +2280,7 @@ ohci_queue_iso(struct fw_iso_context *base,
spin_lock_irqsave(&ctx->context.ohci->lock, flags);
if (base->type == FW_ISO_CONTEXT_TRANSMIT)
retval = ohci_queue_iso_transmit(base, packet, buffer, payload);
else if (ctx->context.ohci->version >= OHCI_VERSION_1_1)
else if (ctx->context.ohci->use_dualbuffer)
retval = ohci_queue_iso_receive_dualbuffer(base, packet,
buffer, payload);
else
@ -2341,7 +2342,7 @@ static int __devinit
pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
{
struct fw_ohci *ohci;
u32 bus_options, max_receive, link_speed;
u32 bus_options, max_receive, link_speed, version;
u64 guid;
int err;
size_t size;
@ -2366,12 +2367,6 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
pci_write_config_dword(dev, OHCI1394_PCI_HCI_Control, 0);
pci_set_drvdata(dev, ohci);
#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
ohci->old_uninorth = dev->vendor == PCI_VENDOR_ID_APPLE &&
dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW;
#endif
ohci->bus_reset_packet_quirk = dev->vendor == PCI_VENDOR_ID_TI;
spin_lock_init(&ohci->lock);
tasklet_init(&ohci->bus_reset_tasklet,
@ -2390,6 +2385,23 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
goto fail_iomem;
}
version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
ohci->use_dualbuffer = version >= OHCI_VERSION_1_1;
/* x86-32 currently doesn't use highmem for dma_alloc_coherent */
#if !defined(CONFIG_X86_32)
/* dual-buffer mode is broken with descriptor addresses above 2G */
if (dev->vendor == PCI_VENDOR_ID_TI &&
dev->device == PCI_DEVICE_ID_TI_TSB43AB22)
ohci->use_dualbuffer = false;
#endif
#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
ohci->old_uninorth = dev->vendor == PCI_VENDOR_ID_APPLE &&
dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW;
#endif
ohci->bus_reset_packet_quirk = dev->vendor == PCI_VENDOR_ID_TI;
ar_context_init(&ohci->ar_request_ctx, ohci,
OHCI1394_AsReqRcvContextControlSet);
@ -2441,9 +2453,8 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
if (err < 0)
goto fail_self_id;
ohci->version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
fw_notify("Added fw-ohci device %s, OHCI version %x.%x\n",
dev->dev.bus_id, ohci->version >> 16, ohci->version & 0xff);
dev->dev.bus_id, version >> 16, version & 0xff);
return 0;
fail_self_id:

View file

@ -510,8 +510,6 @@ fw_core_handle_bus_reset(struct fw_card *card,
struct fw_node *local_node;
unsigned long flags;
fw_flush_transactions(card);
spin_lock_irqsave(&card->lock, flags);
/*

View file

@ -22,6 +22,7 @@
#include <linux/kernel.h>
#include <linux/kref.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
@ -151,7 +152,7 @@ transmit_complete_callback(struct fw_packet *packet,
static void
fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
int node_id, int source_id, int generation, int speed,
int destination_id, int source_id, int generation, int speed,
unsigned long long offset, void *payload, size_t length)
{
int ext_tcode;
@ -166,7 +167,7 @@ fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
HEADER_RETRY(RETRY_X) |
HEADER_TLABEL(tlabel) |
HEADER_TCODE(tcode) |
HEADER_DESTINATION(node_id);
HEADER_DESTINATION(destination_id);
packet->header[1] =
HEADER_OFFSET_HIGH(offset >> 32) | HEADER_SOURCE(source_id);
packet->header[2] =
@ -252,7 +253,7 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t,
fw_transaction_callback_t callback, void *callback_data)
{
unsigned long flags;
int tlabel, source;
int tlabel;
/*
* Bump the flush timer up 100ms first of all so we
@ -268,7 +269,6 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t,
spin_lock_irqsave(&card->lock, flags);
source = card->node_id;
tlabel = card->current_tlabel;
if (card->tlabel_mask & (1 << tlabel)) {
spin_unlock_irqrestore(&card->lock, flags);
@ -279,77 +279,58 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t,
card->current_tlabel = (card->current_tlabel + 1) & 0x1f;
card->tlabel_mask |= (1 << tlabel);
list_add_tail(&t->link, &card->transaction_list);
spin_unlock_irqrestore(&card->lock, flags);
/* Initialize rest of transaction, fill out packet and send it. */
t->node_id = node_id;
t->tlabel = tlabel;
t->callback = callback;
t->callback_data = callback_data;
fw_fill_request(&t->packet, tcode, t->tlabel,
node_id, source, generation,
speed, offset, payload, length);
fw_fill_request(&t->packet, tcode, t->tlabel, node_id, card->node_id,
generation, speed, offset, payload, length);
t->packet.callback = transmit_complete_callback;
list_add_tail(&t->link, &card->transaction_list);
spin_unlock_irqrestore(&card->lock, flags);
card->driver->send_request(card, &t->packet);
}
EXPORT_SYMBOL(fw_send_request);
struct fw_phy_packet {
struct fw_packet packet;
struct completion done;
struct kref kref;
};
static void phy_packet_release(struct kref *kref)
{
struct fw_phy_packet *p =
container_of(kref, struct fw_phy_packet, kref);
kfree(p);
}
static DEFINE_MUTEX(phy_config_mutex);
static DECLARE_COMPLETION(phy_config_done);
static void transmit_phy_packet_callback(struct fw_packet *packet,
struct fw_card *card, int status)
{
struct fw_phy_packet *p =
container_of(packet, struct fw_phy_packet, packet);
complete(&p->done);
kref_put(&p->kref, phy_packet_release);
complete(&phy_config_done);
}
static struct fw_packet phy_config_packet = {
.header_length = 8,
.payload_length = 0,
.speed = SCODE_100,
.callback = transmit_phy_packet_callback,
};
void fw_send_phy_config(struct fw_card *card,
int node_id, int generation, int gap_count)
{
struct fw_phy_packet *p;
long timeout = DIV_ROUND_UP(HZ, 10);
u32 data = PHY_IDENTIFIER(PHY_PACKET_CONFIG) |
PHY_CONFIG_ROOT_ID(node_id) |
PHY_CONFIG_GAP_COUNT(gap_count);
p = kmalloc(sizeof(*p), GFP_KERNEL);
if (p == NULL)
return;
mutex_lock(&phy_config_mutex);
p->packet.header[0] = data;
p->packet.header[1] = ~data;
p->packet.header_length = 8;
p->packet.payload_length = 0;
p->packet.speed = SCODE_100;
p->packet.generation = generation;
p->packet.callback = transmit_phy_packet_callback;
init_completion(&p->done);
kref_set(&p->kref, 2);
phy_config_packet.header[0] = data;
phy_config_packet.header[1] = ~data;
phy_config_packet.generation = generation;
INIT_COMPLETION(phy_config_done);
card->driver->send_request(card, &p->packet);
timeout = wait_for_completion_timeout(&p->done, timeout);
kref_put(&p->kref, phy_packet_release);
card->driver->send_request(card, &phy_config_packet);
wait_for_completion_timeout(&phy_config_done, timeout);
/* will leak p if the callback is never executed */
WARN_ON(timeout == 0);
mutex_unlock(&phy_config_mutex);
}
void fw_flush_transactions(struct fw_card *card)

View file

@ -7,6 +7,7 @@ config MISDN_HFCPCI
tristate "Support for HFC PCI cards"
depends on MISDN
depends on PCI
depends on VIRT_TO_BUS
help
Enable support for cards with Cologne Chip AG's
HFC PCI chip.

View file

@ -2030,7 +2030,7 @@ release_l2(struct layer2 *l2)
skb_queue_purge(&l2->down_queue);
ReleaseWin(l2);
if (test_bit(FLG_LAPD, &l2->flag)) {
release_tei(l2);
TEIrelease(l2);
if (l2->ch.st)
l2->ch.st->dev->D.ctrl(&l2->ch.st->dev->D,
CLOSE_CHANNEL, NULL);

View file

@ -96,7 +96,7 @@ extern int tei_l2(struct layer2 *, u_int, u_long arg);
/* from tei.c */
extern int l2_tei(struct layer2 *, u_int, u_long arg);
extern void release_tei(struct layer2 *);
extern void TEIrelease(struct layer2 *);
extern int TEIInit(u_int *);
extern void TEIFree(void);

View file

@ -945,7 +945,7 @@ l2_tei(struct layer2 *l2, u_int cmd, u_long arg)
}
void
release_tei(struct layer2 *l2)
TEIrelease(struct layer2 *l2)
{
struct teimgr *tm = l2->tm;
u_long flags;

View file

@ -147,9 +147,12 @@ static struct priority_group *alloc_priority_group(void)
static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti)
{
struct pgpath *pgpath, *tmp;
struct multipath *m = ti->private;
list_for_each_entry_safe(pgpath, tmp, pgpaths, list) {
list_del(&pgpath->list);
if (m->hw_handler_name)
scsi_dh_detach(bdev_get_queue(pgpath->path.dev->bdev));
dm_put_device(ti, pgpath->path.dev);
free_pgpath(pgpath);
}
@ -548,6 +551,7 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps,
{
int r;
struct pgpath *p;
struct multipath *m = ti->private;
/* we need at least a path arg */
if (as->argc < 1) {
@ -566,6 +570,15 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps,
goto bad;
}
if (m->hw_handler_name) {
r = scsi_dh_attach(bdev_get_queue(p->path.dev->bdev),
m->hw_handler_name);
if (r < 0) {
dm_put_device(ti, p->path.dev);
goto bad;
}
}
r = ps->type->add_path(ps, &p->path, as->argc, as->argv, &ti->error);
if (r) {
dm_put_device(ti, p->path.dev);

View file

@ -273,12 +273,12 @@ mpt_fault_reset_work(struct work_struct *work)
ioc_raw_state = mpt_GetIocState(ioc, 0);
if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
printk(MYIOC_s_WARN_FMT "IOC is in FAULT state (%04xh)!!!\n",
ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK);
ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK);
printk(MYIOC_s_WARN_FMT "Issuing HardReset from %s!!\n",
ioc->name, __FUNCTION__);
ioc->name, __func__);
rc = mpt_HardResetHandler(ioc, CAN_SLEEP);
printk(MYIOC_s_WARN_FMT "%s: HardReset: %s\n", ioc->name,
__FUNCTION__, (rc == 0) ? "success" : "failed");
__func__, (rc == 0) ? "success" : "failed");
ioc_raw_state = mpt_GetIocState(ioc, 0);
if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT)
printk(MYIOC_s_WARN_FMT "IOC is in FAULT state after "
@ -356,7 +356,7 @@ mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
MptCallbacks[cb_idx] == NULL) {
printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
__FUNCTION__, ioc->name, cb_idx);
__func__, ioc->name, cb_idx);
goto out;
}
@ -420,7 +420,7 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa)
if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
MptCallbacks[cb_idx] == NULL) {
printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
__FUNCTION__, ioc->name, cb_idx);
__func__, ioc->name, cb_idx);
freeme = 0;
goto out;
}
@ -2434,7 +2434,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
if (ioc->cached_fw != NULL) {
ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: Pushing FW onto "
"adapter\n", __FUNCTION__, ioc->name));
"adapter\n", __func__, ioc->name));
if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)
ioc->cached_fw, CAN_SLEEP)) < 0) {
printk(MYIOC_s_WARN_FMT
@ -3693,7 +3693,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
drsprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset "
"address=%p\n", ioc->name, __FUNCTION__,
"address=%p\n", ioc->name, __func__,
&ioc->chip->Doorbell, &ioc->chip->Reset_1078));
CHIPREG_WRITE32(&ioc->chip->Reset_1078, 0x07);
if (sleepFlag == CAN_SLEEP)
@ -4742,12 +4742,12 @@ mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
break;
}
printk("%s: persist_opcode=%x\n",__FUNCTION__, persist_opcode);
printk("%s: persist_opcode=%x\n",__func__, persist_opcode);
/* Get a MF for this command.
*/
if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
printk("%s: no msg frames!\n",__FUNCTION__);
printk("%s: no msg frames!\n",__func__);
return -1;
}
@ -4771,13 +4771,13 @@ mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
(SasIoUnitControlReply_t *)ioc->persist_reply_frame;
if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
__FUNCTION__,
__func__,
sasIoUnitCntrReply->IOCStatus,
sasIoUnitCntrReply->IOCLogInfo);
return -1;
}
printk("%s: success\n",__FUNCTION__);
printk("%s: success\n",__func__);
return 0;
}
@ -5784,7 +5784,7 @@ SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
ioc->name,__FUNCTION__));
ioc->name,__func__));
return -1;
}

View file

@ -505,7 +505,7 @@ mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
event = le32_to_cpu(pEvReply->Event) & 0xFF;
dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s() called\n",
ioc->name, __FUNCTION__));
ioc->name, __func__));
if(async_queue == NULL)
return 1;
@ -2482,7 +2482,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
*/
if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
ioc->name,__FUNCTION__));
ioc->name,__func__));
goto out;
}

View file

@ -231,28 +231,28 @@ static int
mptfc_abort(struct scsi_cmnd *SCpnt)
{
return
mptfc_block_error_handler(SCpnt, mptscsih_abort, __FUNCTION__);
mptfc_block_error_handler(SCpnt, mptscsih_abort, __func__);
}
static int
mptfc_dev_reset(struct scsi_cmnd *SCpnt)
{
return
mptfc_block_error_handler(SCpnt, mptscsih_dev_reset, __FUNCTION__);
mptfc_block_error_handler(SCpnt, mptscsih_dev_reset, __func__);
}
static int
mptfc_bus_reset(struct scsi_cmnd *SCpnt)
{
return
mptfc_block_error_handler(SCpnt, mptscsih_bus_reset, __FUNCTION__);
mptfc_block_error_handler(SCpnt, mptscsih_bus_reset, __func__);
}
static int
mptfc_host_reset(struct scsi_cmnd *SCpnt)
{
return
mptfc_block_error_handler(SCpnt, mptscsih_host_reset, __FUNCTION__);
mptfc_block_error_handler(SCpnt, mptscsih_host_reset, __func__);
}
static void

View file

@ -610,7 +610,7 @@ mpt_lan_send_turbo(struct net_device *dev, u32 tmsg)
dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, skb %p sent.\n",
IOC_AND_NETDEV_NAMES_s_s(dev),
__FUNCTION__, sent));
__func__, sent));
priv->SendCtl[ctx].skb = NULL;
pci_unmap_single(mpt_dev->pcidev, priv->SendCtl[ctx].dma,
@ -676,7 +676,7 @@ mpt_lan_send_reply(struct net_device *dev, LANSendReply_t *pSendRep)
dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, skb %p sent.\n",
IOC_AND_NETDEV_NAMES_s_s(dev),
__FUNCTION__, sent));
__func__, sent));
priv->SendCtl[ctx].skb = NULL;
pci_unmap_single(mpt_dev->pcidev, priv->SendCtl[ctx].dma,
@ -715,7 +715,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, struct net_device *dev)
u16 cur_naa = 0x1000;
dioprintk((KERN_INFO MYNAM ": %s called, skb_addr = %p\n",
__FUNCTION__, skb));
__func__, skb));
spin_lock_irqsave(&priv->txfidx_lock, flags);
if (priv->mpt_txfidx_tail < 0) {
@ -723,7 +723,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, struct net_device *dev)
spin_unlock_irqrestore(&priv->txfidx_lock, flags);
printk (KERN_ERR "%s: no tx context available: %u\n",
__FUNCTION__, priv->mpt_txfidx_tail);
__func__, priv->mpt_txfidx_tail);
return 1;
}
@ -733,7 +733,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, struct net_device *dev)
spin_unlock_irqrestore(&priv->txfidx_lock, flags);
printk (KERN_ERR "%s: Unable to alloc request frame\n",
__FUNCTION__);
__func__);
return 1;
}
@ -1208,7 +1208,7 @@ mpt_lan_post_receive_buckets(struct mpt_lan_priv *priv)
dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, Start_buckets = %u, buckets_out = %u\n",
IOC_AND_NETDEV_NAMES_s_s(dev),
__FUNCTION__, buckets, curr));
__func__, buckets, curr));
max = (mpt_dev->req_sz - MPT_LAN_RECEIVE_POST_REQUEST_SIZE) /
(MPT_LAN_TRANSACTION32_SIZE + sizeof(SGESimple64_t));
@ -1217,9 +1217,9 @@ mpt_lan_post_receive_buckets(struct mpt_lan_priv *priv)
mf = mpt_get_msg_frame(LanCtx, mpt_dev);
if (mf == NULL) {
printk (KERN_ERR "%s: Unable to alloc request frame\n",
__FUNCTION__);
__func__);
dioprintk((KERN_ERR "%s: %u buckets remaining\n",
__FUNCTION__, buckets));
__func__, buckets));
goto out;
}
pRecvReq = (LANReceivePostRequest_t *) mf;
@ -1244,7 +1244,7 @@ mpt_lan_post_receive_buckets(struct mpt_lan_priv *priv)
spin_lock_irqsave(&priv->rxfidx_lock, flags);
if (priv->mpt_rxfidx_tail < 0) {
printk (KERN_ERR "%s: Can't alloc context\n",
__FUNCTION__);
__func__);
spin_unlock_irqrestore(&priv->rxfidx_lock,
flags);
break;
@ -1267,7 +1267,7 @@ mpt_lan_post_receive_buckets(struct mpt_lan_priv *priv)
if (skb == NULL) {
printk (KERN_WARNING
MYNAM "/%s: Can't alloc skb\n",
__FUNCTION__);
__func__);
priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = ctx;
spin_unlock_irqrestore(&priv->rxfidx_lock, flags);
break;
@ -1305,7 +1305,7 @@ mpt_lan_post_receive_buckets(struct mpt_lan_priv *priv)
if (pSimple == NULL) {
/**/ printk (KERN_WARNING MYNAM "/%s: No buckets posted\n",
/**/ __FUNCTION__);
/**/ __func__);
mpt_free_msg_frame(mpt_dev, mf);
goto out;
}
@ -1329,9 +1329,9 @@ mpt_lan_post_receive_buckets(struct mpt_lan_priv *priv)
out:
dioprintk((KERN_INFO MYNAM "/%s: End_buckets = %u, priv->buckets_out = %u\n",
__FUNCTION__, buckets, atomic_read(&priv->buckets_out)));
__func__, buckets, atomic_read(&priv->buckets_out)));
dioprintk((KERN_INFO MYNAM "/%s: Posted %u buckets and received %u back\n",
__FUNCTION__, priv->total_posted, priv->total_received));
__func__, priv->total_posted, priv->total_received));
clear_bit(0, &priv->post_buckets_active);
}

View file

@ -300,7 +300,7 @@ mptsas_port_delete(MPT_ADAPTER *ioc, struct mptsas_portinfo_details * port_detai
phy_info = port_info->phy_info;
dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: [%p]: num_phys=%02d "
"bitmask=0x%016llX\n", ioc->name, __FUNCTION__, port_details,
"bitmask=0x%016llX\n", ioc->name, __func__, port_details,
port_details->num_phys, (unsigned long long)
port_details->phy_bitmask));
@ -411,7 +411,7 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
*/
dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
"%s: [%p]: deleting phy = %d\n",
ioc->name, __FUNCTION__, port_details, i));
ioc->name, __func__, 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));
@ -497,7 +497,7 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
continue;
dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
"%s: [%p]: phy_id=%02d num_phys=%02d "
"bitmask=0x%016llX\n", ioc->name, __FUNCTION__,
"bitmask=0x%016llX\n", ioc->name, __func__,
port_details, i, port_details->num_phys,
(unsigned long long)port_details->phy_bitmask));
dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tport = %p rphy=%p\n",
@ -553,7 +553,7 @@ mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) {
dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames @%d!!\n",
ioc->name,__FUNCTION__, __LINE__));
ioc->name,__func__, __LINE__));
return 0;
}
@ -606,7 +606,7 @@ mptsas_target_reset_queue(MPT_ADAPTER *ioc,
GFP_ATOMIC);
if (!target_reset_list) {
dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
ioc->name,__FUNCTION__, __LINE__));
ioc->name,__func__, __LINE__));
return;
}
@ -673,7 +673,7 @@ mptsas_dev_reset_complete(MPT_ADAPTER *ioc)
ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
if (!ev) {
dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
ioc->name,__FUNCTION__, __LINE__));
ioc->name,__func__, __LINE__));
return;
}
@ -1183,7 +1183,7 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
printk(MYIOC_s_INFO_FMT "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
ioc->name, __FUNCTION__, reply->IOCStatus, reply->IOCLogInfo);
ioc->name, __func__, reply->IOCStatus, reply->IOCLogInfo);
error = -ENXIO;
goto out_unlock;
}
@ -1270,14 +1270,14 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
if (!rsp) {
printk(MYIOC_s_ERR_FMT "%s: the smp response space is missing\n",
ioc->name, __FUNCTION__);
ioc->name, __func__);
return -EINVAL;
}
/* do we need to support multiple segments? */
if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u %u, rsp %u %u\n",
ioc->name, __FUNCTION__, req->bio->bi_vcnt, req->data_len,
ioc->name, __func__, req->bio->bi_vcnt, req->data_len,
rsp->bio->bi_vcnt, rsp->data_len);
return -EINVAL;
}
@ -1343,7 +1343,7 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
if (!timeleft) {
printk(MYIOC_s_ERR_FMT "%s: smp timeout!\n", ioc->name, __FUNCTION__);
printk(MYIOC_s_ERR_FMT "%s: smp timeout!\n", ioc->name, __func__);
/* On timeout reset the board */
mpt_HardResetHandler(ioc, CAN_SLEEP);
ret = -ETIMEDOUT;
@ -1361,7 +1361,7 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
rsp->data_len -= smprep->ResponseDataLength;
} else {
printk(MYIOC_s_ERR_FMT "%s: smp passthru reply failed to be returned\n",
ioc->name, __FUNCTION__);
ioc->name, __func__);
ret = -ENXIO;
}
unmap:
@ -2006,7 +2006,7 @@ static int mptsas_probe_one_phy(struct device *dev,
if (error) {
dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
"%s: exit at line=%d\n", ioc->name,
__FUNCTION__, __LINE__));
__func__, __LINE__));
goto out;
}
mptsas_set_port(ioc, phy_info, port);
@ -2076,7 +2076,7 @@ static int mptsas_probe_one_phy(struct device *dev,
if (!rphy) {
dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
"%s: exit at line=%d\n", ioc->name,
__FUNCTION__, __LINE__));
__func__, __LINE__));
goto out;
}
@ -2085,7 +2085,7 @@ static int mptsas_probe_one_phy(struct device *dev,
if (error) {
dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
"%s: exit at line=%d\n", ioc->name,
__FUNCTION__, __LINE__));
__func__, __LINE__));
sas_rphy_free(rphy);
goto out;
}
@ -2613,7 +2613,7 @@ mptsas_hotplug_work(struct work_struct *work)
(ev->channel << 8) + ev->id)) {
dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
"%s: exit at line=%d\n", ioc->name,
__FUNCTION__, __LINE__));
__func__, __LINE__));
break;
}
phy_info = mptsas_find_phyinfo_by_sas_address(
@ -2633,20 +2633,20 @@ mptsas_hotplug_work(struct work_struct *work)
if (!phy_info){
dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
"%s: exit at line=%d\n", ioc->name,
__FUNCTION__, __LINE__));
__func__, __LINE__));
break;
}
if (!phy_info->port_details) {
dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
"%s: exit at line=%d\n", ioc->name,
__FUNCTION__, __LINE__));
__func__, __LINE__));
break;
}
rphy = mptsas_get_rphy(phy_info);
if (!rphy) {
dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
"%s: exit at line=%d\n", ioc->name,
__FUNCTION__, __LINE__));
__func__, __LINE__));
break;
}
@ -2654,7 +2654,7 @@ mptsas_hotplug_work(struct work_struct *work)
if (!port) {
dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
"%s: exit at line=%d\n", ioc->name,
__FUNCTION__, __LINE__));
__func__, __LINE__));
break;
}
@ -2665,7 +2665,7 @@ mptsas_hotplug_work(struct work_struct *work)
if (!vtarget) {
dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
"%s: exit at line=%d\n", ioc->name,
__FUNCTION__, __LINE__));
__func__, __LINE__));
break;
}
@ -2720,7 +2720,7 @@ mptsas_hotplug_work(struct work_struct *work)
(ev->channel << 8) + ev->id)) {
dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
"%s: exit at line=%d\n", ioc->name,
__FUNCTION__, __LINE__));
__func__, __LINE__));
break;
}
@ -2732,7 +2732,7 @@ mptsas_hotplug_work(struct work_struct *work)
if (!phy_info || !phy_info->port_details) {
dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
"%s: exit at line=%d\n", ioc->name,
__FUNCTION__, __LINE__));
__func__, __LINE__));
break;
}
@ -2744,7 +2744,7 @@ mptsas_hotplug_work(struct work_struct *work)
if (!vtarget) {
dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
"%s: exit at line=%d\n", ioc->name,
__FUNCTION__, __LINE__));
__func__, __LINE__));
break;
}
/*
@ -2767,7 +2767,7 @@ mptsas_hotplug_work(struct work_struct *work)
if (mptsas_get_rphy(phy_info)) {
dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
"%s: exit at line=%d\n", ioc->name,
__FUNCTION__, __LINE__));
__func__, __LINE__));
if (ev->channel) printk("%d\n", __LINE__);
break;
}
@ -2776,7 +2776,7 @@ mptsas_hotplug_work(struct work_struct *work)
if (!port) {
dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
"%s: exit at line=%d\n", ioc->name,
__FUNCTION__, __LINE__));
__func__, __LINE__));
break;
}
memcpy(&phy_info->attached, &sas_device,
@ -2801,7 +2801,7 @@ mptsas_hotplug_work(struct work_struct *work)
if (!rphy) {
dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
"%s: exit at line=%d\n", ioc->name,
__FUNCTION__, __LINE__));
__func__, __LINE__));
break; /* non-fatal: an rphy can be added later */
}
@ -2809,7 +2809,7 @@ mptsas_hotplug_work(struct work_struct *work)
if (sas_rphy_add(rphy)) {
dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
"%s: exit at line=%d\n", ioc->name,
__FUNCTION__, __LINE__));
__func__, __LINE__));
sas_rphy_free(rphy);
break;
}

View file

@ -461,7 +461,7 @@ mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget,
if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: no msg frames!!\n",
ioc->name,__FUNCTION__));
ioc->name,__func__));
return;
}
@ -2187,7 +2187,7 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
(ioc->debug_level & MPT_DEBUG_TM ))
printk("%s: ha=%d [%d:%d:0] task_type=0x%02X "
"iocstatus=0x%04X\n\tloginfo=0x%08X response_code=0x%02X "
"term_cmnds=%d\n", __FUNCTION__, ioc->id, pScsiTmReply->Bus,
"term_cmnds=%d\n", __func__, ioc->id, pScsiTmReply->Bus,
pScsiTmReply->TargetID, pScsiTmReq->TaskType,
le16_to_cpu(pScsiTmReply->IOCStatus),
le32_to_cpu(pScsiTmReply->IOCLogInfo),pScsiTmReply->ResponseCode,

View file

@ -360,7 +360,7 @@ config THINKPAD_ACPI_VIDEO
If you are not sure, say Y here.
config THINKPAD_ACPI_HOTKEY_POLL
bool "Suport NVRAM polling for hot keys"
bool "Support NVRAM polling for hot keys"
depends on THINKPAD_ACPI
default y
---help---

View file

@ -13,7 +13,6 @@
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/atmel-ssc.h>

View file

@ -11,6 +11,8 @@
#include <linux/clk.h>
#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
@ -27,7 +29,6 @@
#include <asm/unaligned.h>
#include <asm/arch/board.h>
#include <asm/arch/gpio.h>
#include "atmel-mci-regs.h"
@ -573,7 +574,7 @@ static int atmci_get_ro(struct mmc_host *mmc)
int read_only = 0;
struct atmel_mci *host = mmc_priv(mmc);
if (host->wp_pin >= 0) {
if (gpio_is_valid(host->wp_pin)) {
read_only = gpio_get_value(host->wp_pin);
dev_dbg(&mmc->class_dev, "card is %s\n",
read_only ? "read-only" : "read-write");
@ -635,7 +636,7 @@ static void atmci_detect_change(unsigned long data)
* been freed.
*/
smp_rmb();
if (host->detect_pin < 0)
if (!gpio_is_valid(host->detect_pin))
return;
enable_irq(gpio_to_irq(host->detect_pin));
@ -1050,7 +1051,7 @@ static int __init atmci_probe(struct platform_device *pdev)
/* Assume card is present if we don't have a detect pin */
host->present = 1;
if (host->detect_pin >= 0) {
if (gpio_is_valid(host->detect_pin)) {
if (gpio_request(host->detect_pin, "mmc_detect")) {
dev_dbg(&mmc->class_dev, "no detect pin available\n");
host->detect_pin = -1;
@ -1058,7 +1059,7 @@ static int __init atmci_probe(struct platform_device *pdev)
host->present = !gpio_get_value(host->detect_pin);
}
}
if (host->wp_pin >= 0) {
if (gpio_is_valid(host->wp_pin)) {
if (gpio_request(host->wp_pin, "mmc_wp")) {
dev_dbg(&mmc->class_dev, "no WP pin available\n");
host->wp_pin = -1;
@ -1069,7 +1070,7 @@ static int __init atmci_probe(struct platform_device *pdev)
mmc_add_host(mmc);
if (host->detect_pin >= 0) {
if (gpio_is_valid(host->detect_pin)) {
setup_timer(&host->detect_timer, atmci_detect_change,
(unsigned long)host);
@ -1112,7 +1113,7 @@ static int __exit atmci_remove(struct platform_device *pdev)
if (host) {
/* Debugfs stuff is cleaned up by mmc core */
if (host->detect_pin >= 0) {
if (gpio_is_valid(host->detect_pin)) {
int pin = host->detect_pin;
/* Make sure the timer doesn't enable the interrupt */
@ -1132,7 +1133,7 @@ static int __exit atmci_remove(struct platform_device *pdev)
mci_readl(host, SR);
clk_disable(host->mck);
if (host->wp_pin >= 0)
if (gpio_is_valid(host->wp_pin))
gpio_free(host->wp_pin);
free_irq(platform_get_irq(pdev, 0), host->mmc);

View file

@ -6,4 +6,4 @@
# it under the terms of the GNU General Public License (version 2 only)
# as published by the Free Software Foundation.
obj-$(CONFIG_VIRTIO) += kvm_virtio.o
obj-$(CONFIG_S390_GUEST) += kvm_virtio.o

View file

@ -4,7 +4,7 @@
Written By: Adam Radford <linuxraid@amcc.com>
Modifications By: Tom Couch <linuxraid@amcc.com>
Copyright (C) 2004-2007 Applied Micro Circuits Corporation.
Copyright (C) 2004-2008 Applied Micro Circuits Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -71,6 +71,10 @@
Add support for 9650SE controllers.
2.26.02.009 - Fix dma mask setting to fallback to 32-bit if 64-bit fails.
2.26.02.010 - Add support for 9690SA controllers.
2.26.02.011 - Increase max AENs drained to 256.
Add MSI support and "use_msi" module parameter.
Fix bug in twa_get_param() on 4GB+.
Use pci_resource_len() for ioremap().
*/
#include <linux/module.h>
@ -95,7 +99,7 @@
#include "3w-9xxx.h"
/* Globals */
#define TW_DRIVER_VERSION "2.26.02.010"
#define TW_DRIVER_VERSION "2.26.02.011"
static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
static unsigned int twa_device_extension_count;
static int twa_major = -1;
@ -107,6 +111,10 @@ MODULE_DESCRIPTION ("3ware 9000 Storage Controller Linux Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(TW_DRIVER_VERSION);
static int use_msi = 0;
module_param(use_msi, int, S_IRUGO);
MODULE_PARM_DESC(use_msi, "Use Message Signaled Interrupts. Default: 0");
/* Function prototypes */
static void twa_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_Header *header);
static int twa_aen_read_queue(TW_Device_Extension *tw_dev, int request_id);
@ -1038,7 +1046,6 @@ static void *twa_get_param(TW_Device_Extension *tw_dev, int request_id, int tabl
TW_Command_Full *full_command_packet;
TW_Command *command_packet;
TW_Param_Apache *param;
unsigned long param_value;
void *retval = NULL;
/* Setup the command packet */
@ -1057,9 +1064,8 @@ static void *twa_get_param(TW_Device_Extension *tw_dev, int request_id, int tabl
param->table_id = cpu_to_le16(table_id | 0x8000);
param->parameter_id = cpu_to_le16(parameter_id);
param->parameter_size_bytes = cpu_to_le16(parameter_size_bytes);
param_value = tw_dev->generic_buffer_phys[request_id];
command_packet->byte8_offset.param.sgl[0].address = TW_CPU_TO_SGL(param_value);
command_packet->byte8_offset.param.sgl[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
command_packet->byte8_offset.param.sgl[0].length = cpu_to_le32(TW_SECTOR_SIZE);
/* Post the command packet to the board */
@ -2000,7 +2006,7 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id
{
struct Scsi_Host *host = NULL;
TW_Device_Extension *tw_dev;
u32 mem_addr;
unsigned long mem_addr, mem_len;
int retval = -ENODEV;
retval = pci_enable_device(pdev);
@ -2045,13 +2051,16 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id
goto out_free_device_extension;
}
if (pdev->device == PCI_DEVICE_ID_3WARE_9000)
if (pdev->device == PCI_DEVICE_ID_3WARE_9000) {
mem_addr = pci_resource_start(pdev, 1);
else
mem_len = pci_resource_len(pdev, 1);
} else {
mem_addr = pci_resource_start(pdev, 2);
mem_len = pci_resource_len(pdev, 2);
}
/* Save base address */
tw_dev->base_addr = ioremap(mem_addr, PAGE_SIZE);
tw_dev->base_addr = ioremap(mem_addr, mem_len);
if (!tw_dev->base_addr) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x35, "Failed to ioremap");
goto out_release_mem_region;
@ -2086,7 +2095,7 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id
pci_set_drvdata(pdev, host);
printk(KERN_WARNING "3w-9xxx: scsi%d: Found a 3ware 9000 Storage Controller at 0x%x, IRQ: %d.\n",
printk(KERN_WARNING "3w-9xxx: scsi%d: Found a 3ware 9000 Storage Controller at 0x%lx, IRQ: %d.\n",
host->host_no, mem_addr, pdev->irq);
printk(KERN_WARNING "3w-9xxx: scsi%d: Firmware %s, BIOS %s, Ports: %d.\n",
host->host_no,
@ -2097,6 +2106,11 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id
le32_to_cpu(*(int *)twa_get_param(tw_dev, 2, TW_INFORMATION_TABLE,
TW_PARAM_PORTCOUNT, TW_PARAM_PORTCOUNT_LENGTH)));
/* Try to enable MSI */
if (use_msi && (pdev->device != PCI_DEVICE_ID_3WARE_9000) &&
!pci_enable_msi(pdev))
set_bit(TW_USING_MSI, &tw_dev->flags);
/* Now setup the interrupt handler */
retval = request_irq(pdev->irq, twa_interrupt, IRQF_SHARED, "3w-9xxx", tw_dev);
if (retval) {
@ -2120,6 +2134,8 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id
return 0;
out_remove_host:
if (test_bit(TW_USING_MSI, &tw_dev->flags))
pci_disable_msi(pdev);
scsi_remove_host(host);
out_iounmap:
iounmap(tw_dev->base_addr);
@ -2151,6 +2167,10 @@ static void twa_remove(struct pci_dev *pdev)
/* Shutdown the card */
__twa_shutdown(tw_dev);
/* Disable MSI if enabled */
if (test_bit(TW_USING_MSI, &tw_dev->flags))
pci_disable_msi(pdev);
/* Free IO remapping */
iounmap(tw_dev->base_addr);

View file

@ -4,7 +4,7 @@
Written By: Adam Radford <linuxraid@amcc.com>
Modifications By: Tom Couch <linuxraid@amcc.com>
Copyright (C) 2004-2007 Applied Micro Circuits Corporation.
Copyright (C) 2004-2008 Applied Micro Circuits Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -319,8 +319,8 @@ static twa_message_type twa_error_table[] = {
/* Compatibility defines */
#define TW_9000_ARCH_ID 0x5
#define TW_CURRENT_DRIVER_SRL 30
#define TW_CURRENT_DRIVER_BUILD 80
#define TW_CURRENT_DRIVER_SRL 35
#define TW_CURRENT_DRIVER_BUILD 0
#define TW_CURRENT_DRIVER_BRANCH 0
/* Phase defines */
@ -352,8 +352,9 @@ static twa_message_type twa_error_table[] = {
#define TW_MAX_RESET_TRIES 2
#define TW_MAX_CMDS_PER_LUN 254
#define TW_MAX_RESPONSE_DRAIN 256
#define TW_MAX_AEN_DRAIN 40
#define TW_MAX_AEN_DRAIN 255
#define TW_IN_RESET 2
#define TW_USING_MSI 3
#define TW_IN_ATTENTION_LOOP 4
#define TW_MAX_SECTORS 256
#define TW_AEN_WAIT_TIME 1000

View file

@ -63,6 +63,7 @@ comment "SCSI support type (disk, tape, CD-ROM)"
config BLK_DEV_SD
tristate "SCSI disk support"
depends on SCSI
select CRC_T10DIF
---help---
If you want to use SCSI hard disks, Fibre Channel disks,
Serial ATA (SATA) or Parallel ATA (PATA) hard disks,

View file

@ -151,6 +151,8 @@ scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o
scsi_tgt-y += scsi_tgt_lib.o scsi_tgt_if.o
sd_mod-objs := sd.o
sd_mod-$(CONFIG_BLK_DEV_INTEGRITY) += sd_dif.o
sr_mod-objs := sr.o sr_ioctl.o sr_vendor.o
ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \
:= -DCONFIG_NCR53C8XX_PREFETCH -DSCSI_NCR_BIG_ENDIAN \

View file

@ -2278,7 +2278,7 @@ do { \
#define ASC_DBG(lvl, format, arg...) { \
if (asc_dbglvl >= (lvl)) \
printk(KERN_DEBUG "%s: %s: " format, DRV_NAME, \
__FUNCTION__ , ## arg); \
__func__ , ## arg); \
}
#define ASC_DBG_PRT_SCSI_HOST(lvl, s) \

View file

@ -288,20 +288,20 @@ static LIST_HEAD(aha152x_host_list);
#define DO_LOCK(flags) \
do { \
if(spin_is_locked(&QLOCK)) { \
DPRINTK(debug_intr, DEBUG_LEAD "(%s:%d) already locked at %s:%d\n", CMDINFO(CURRENT_SC), __FUNCTION__, __LINE__, QLOCKER, QLOCKERL); \
DPRINTK(debug_intr, DEBUG_LEAD "(%s:%d) already locked at %s:%d\n", CMDINFO(CURRENT_SC), __func__, __LINE__, QLOCKER, QLOCKERL); \
} \
DPRINTK(debug_locking, DEBUG_LEAD "(%s:%d) locking\n", CMDINFO(CURRENT_SC), __FUNCTION__, __LINE__); \
DPRINTK(debug_locking, DEBUG_LEAD "(%s:%d) locking\n", CMDINFO(CURRENT_SC), __func__, __LINE__); \
spin_lock_irqsave(&QLOCK,flags); \
DPRINTK(debug_locking, DEBUG_LEAD "(%s:%d) locked\n", CMDINFO(CURRENT_SC), __FUNCTION__, __LINE__); \
QLOCKER=__FUNCTION__; \
DPRINTK(debug_locking, DEBUG_LEAD "(%s:%d) locked\n", CMDINFO(CURRENT_SC), __func__, __LINE__); \
QLOCKER=__func__; \
QLOCKERL=__LINE__; \
} while(0)
#define DO_UNLOCK(flags) \
do { \
DPRINTK(debug_locking, DEBUG_LEAD "(%s:%d) unlocking (locked at %s:%d)\n", CMDINFO(CURRENT_SC), __FUNCTION__, __LINE__, QLOCKER, QLOCKERL); \
DPRINTK(debug_locking, DEBUG_LEAD "(%s:%d) unlocking (locked at %s:%d)\n", CMDINFO(CURRENT_SC), __func__, __LINE__, QLOCKER, QLOCKERL); \
spin_unlock_irqrestore(&QLOCK,flags); \
DPRINTK(debug_locking, DEBUG_LEAD "(%s:%d) unlocked\n", CMDINFO(CURRENT_SC), __FUNCTION__, __LINE__); \
DPRINTK(debug_locking, DEBUG_LEAD "(%s:%d) unlocked\n", CMDINFO(CURRENT_SC), __func__, __LINE__); \
QLOCKER="(not locked)"; \
QLOCKERL=0; \
} while(0)

View file

@ -39,9 +39,9 @@
#ifdef ASD_ENTER_EXIT
#define ENTER printk(KERN_NOTICE "%s: ENTER %s\n", ASD_DRIVER_NAME, \
__FUNCTION__)
__func__)
#define EXIT printk(KERN_NOTICE "%s: --EXIT %s\n", ASD_DRIVER_NAME, \
__FUNCTION__)
__func__)
#else
#define ENTER
#define EXIT

View file

@ -1359,7 +1359,7 @@ int asd_enable_phys(struct asd_ha_struct *asd_ha, const u8 phy_mask)
struct asd_ascb *ascb_list;
if (!phy_mask) {
asd_printk("%s called with phy_mask of 0!?\n", __FUNCTION__);
asd_printk("%s called with phy_mask of 0!?\n", __func__);
return 0;
}

View file

@ -211,7 +211,7 @@ static void asd_form_port(struct asd_ha_struct *asd_ha, struct asd_phy *phy)
phy->asd_port = port;
}
ASD_DPRINTK("%s: updating phy_mask 0x%x for phy%d\n",
__FUNCTION__, phy->asd_port->phy_mask, sas_phy->id);
__func__, phy->asd_port->phy_mask, sas_phy->id);
asd_update_port_links(asd_ha, phy);
spin_unlock_irqrestore(&asd_ha->asd_ports_lock, flags);
}
@ -294,7 +294,7 @@ static void asd_link_reset_err_tasklet(struct asd_ascb *ascb,
struct asd_ascb *cp = asd_ascb_alloc_list(ascb->ha, &num,
GFP_ATOMIC);
if (!cp) {
asd_printk("%s: out of memory\n", __FUNCTION__);
asd_printk("%s: out of memory\n", __func__);
goto out;
}
ASD_DPRINTK("phy%d: retries:0 performing link reset seq\n",
@ -446,7 +446,7 @@ static void escb_tasklet_complete(struct asd_ascb *ascb,
struct domain_device *failed_dev = NULL;
ASD_DPRINTK("%s: REQ_TASK_ABORT, reason=0x%X\n",
__FUNCTION__, dl->status_block[3]);
__func__, dl->status_block[3]);
/*
* Find the task that caused the abort and abort it first.
@ -474,7 +474,7 @@ static void escb_tasklet_complete(struct asd_ascb *ascb,
if (!failed_dev) {
ASD_DPRINTK("%s: Can't find task (tc=%d) to abort!\n",
__FUNCTION__, tc_abort);
__func__, tc_abort);
goto out;
}
@ -502,7 +502,7 @@ static void escb_tasklet_complete(struct asd_ascb *ascb,
conn_handle = *((u16*)(&dl->status_block[1]));
conn_handle = le16_to_cpu(conn_handle);
ASD_DPRINTK("%s: REQ_DEVICE_RESET, reason=0x%X\n", __FUNCTION__,
ASD_DPRINTK("%s: REQ_DEVICE_RESET, reason=0x%X\n", __func__,
dl->status_block[3]);
/* Find the last pending task for the device... */
@ -522,7 +522,7 @@ static void escb_tasklet_complete(struct asd_ascb *ascb,
if (!last_dev_task) {
ASD_DPRINTK("%s: Device reset for idle device %d?\n",
__FUNCTION__, conn_handle);
__func__, conn_handle);
goto out;
}
@ -549,10 +549,10 @@ static void escb_tasklet_complete(struct asd_ascb *ascb,
goto out;
}
case SIGNAL_NCQ_ERROR:
ASD_DPRINTK("%s: SIGNAL_NCQ_ERROR\n", __FUNCTION__);
ASD_DPRINTK("%s: SIGNAL_NCQ_ERROR\n", __func__);
goto out;
case CLEAR_NCQ_ERROR:
ASD_DPRINTK("%s: CLEAR_NCQ_ERROR\n", __FUNCTION__);
ASD_DPRINTK("%s: CLEAR_NCQ_ERROR\n", __func__);
goto out;
}
@ -560,26 +560,26 @@ static void escb_tasklet_complete(struct asd_ascb *ascb,
switch (sb_opcode) {
case BYTES_DMAED:
ASD_DPRINTK("%s: phy%d: BYTES_DMAED\n", __FUNCTION__, phy_id);
ASD_DPRINTK("%s: phy%d: BYTES_DMAED\n", __func__, phy_id);
asd_bytes_dmaed_tasklet(ascb, dl, edb, phy_id);
break;
case PRIMITIVE_RECVD:
ASD_DPRINTK("%s: phy%d: PRIMITIVE_RECVD\n", __FUNCTION__,
ASD_DPRINTK("%s: phy%d: PRIMITIVE_RECVD\n", __func__,
phy_id);
asd_primitive_rcvd_tasklet(ascb, dl, phy_id);
break;
case PHY_EVENT:
ASD_DPRINTK("%s: phy%d: PHY_EVENT\n", __FUNCTION__, phy_id);
ASD_DPRINTK("%s: phy%d: PHY_EVENT\n", __func__, phy_id);
asd_phy_event_tasklet(ascb, dl);
break;
case LINK_RESET_ERROR:
ASD_DPRINTK("%s: phy%d: LINK_RESET_ERROR\n", __FUNCTION__,
ASD_DPRINTK("%s: phy%d: LINK_RESET_ERROR\n", __func__,
phy_id);
asd_link_reset_err_tasklet(ascb, dl, phy_id);
break;
case TIMER_EVENT:
ASD_DPRINTK("%s: phy%d: TIMER_EVENT, lost dw sync\n",
__FUNCTION__, phy_id);
__func__, phy_id);
asd_turn_led(asd_ha, phy_id, 0);
/* the device is gone */
sas_phy_disconnected(sas_phy);
@ -587,7 +587,7 @@ static void escb_tasklet_complete(struct asd_ascb *ascb,
sas_ha->notify_port_event(sas_phy, PORTE_TIMER_EVENT);
break;
default:
ASD_DPRINTK("%s: phy%d: unknown event:0x%x\n", __FUNCTION__,
ASD_DPRINTK("%s: phy%d: unknown event:0x%x\n", __func__,
phy_id, sb_opcode);
ASD_DPRINTK("edb is 0x%x! dl->opcode is 0x%x\n",
edb, dl->opcode);
@ -654,7 +654,7 @@ static void control_phy_tasklet_complete(struct asd_ascb *ascb,
if (status != 0) {
ASD_DPRINTK("%s: phy%d status block opcode:0x%x\n",
__FUNCTION__, phy_id, status);
__func__, phy_id, status);
goto out;
}
@ -663,7 +663,7 @@ static void control_phy_tasklet_complete(struct asd_ascb *ascb,
asd_ha->hw_prof.enabled_phys &= ~(1 << phy_id);
asd_turn_led(asd_ha, phy_id, 0);
asd_control_led(asd_ha, phy_id, 0);
ASD_DPRINTK("%s: disable phy%d\n", __FUNCTION__, phy_id);
ASD_DPRINTK("%s: disable phy%d\n", __func__, phy_id);
break;
case ENABLE_PHY:
@ -673,40 +673,40 @@ static void control_phy_tasklet_complete(struct asd_ascb *ascb,
get_lrate_mode(phy, oob_mode);
asd_turn_led(asd_ha, phy_id, 1);
ASD_DPRINTK("%s: phy%d, lrate:0x%x, proto:0x%x\n",
__FUNCTION__, phy_id,phy->sas_phy.linkrate,
__func__, phy_id,phy->sas_phy.linkrate,
phy->sas_phy.iproto);
} else if (oob_status & CURRENT_SPINUP_HOLD) {
asd_ha->hw_prof.enabled_phys |= (1 << phy_id);
asd_turn_led(asd_ha, phy_id, 1);
ASD_DPRINTK("%s: phy%d, spinup hold\n", __FUNCTION__,
ASD_DPRINTK("%s: phy%d, spinup hold\n", __func__,
phy_id);
} else if (oob_status & CURRENT_ERR_MASK) {
asd_turn_led(asd_ha, phy_id, 0);
ASD_DPRINTK("%s: phy%d: error: oob status:0x%02x\n",
__FUNCTION__, phy_id, oob_status);
__func__, phy_id, oob_status);
} else if (oob_status & (CURRENT_HOT_PLUG_CNCT
| CURRENT_DEVICE_PRESENT)) {
asd_ha->hw_prof.enabled_phys |= (1 << phy_id);
asd_turn_led(asd_ha, phy_id, 1);
ASD_DPRINTK("%s: phy%d: hot plug or device present\n",
__FUNCTION__, phy_id);
__func__, phy_id);
} else {
asd_ha->hw_prof.enabled_phys |= (1 << phy_id);
asd_turn_led(asd_ha, phy_id, 0);
ASD_DPRINTK("%s: phy%d: no device present: "
"oob_status:0x%x\n",
__FUNCTION__, phy_id, oob_status);
__func__, phy_id, oob_status);
}
break;
case RELEASE_SPINUP_HOLD:
case PHY_NO_OP:
case EXECUTE_HARD_RESET:
ASD_DPRINTK("%s: phy%d: sub_func:0x%x\n", __FUNCTION__,
ASD_DPRINTK("%s: phy%d: sub_func:0x%x\n", __func__,
phy_id, control_phy->sub_func);
/* XXX finish */
break;
default:
ASD_DPRINTK("%s: phy%d: sub_func:0x%x?\n", __FUNCTION__,
ASD_DPRINTK("%s: phy%d: sub_func:0x%x?\n", __func__,
phy_id, control_phy->sub_func);
break;
}

View file

@ -320,7 +320,7 @@ Again:
case TC_RESUME:
case TC_PARTIAL_SG_LIST:
default:
ASD_DPRINTK("%s: dl opcode: 0x%x?\n", __FUNCTION__, opcode);
ASD_DPRINTK("%s: dl opcode: 0x%x?\n", __func__, opcode);
break;
}

View file

@ -75,12 +75,12 @@ static void asd_clear_nexus_tasklet_complete(struct asd_ascb *ascb,
struct done_list_struct *dl)
{
struct tasklet_completion_status *tcs = ascb->uldd_task;
ASD_DPRINTK("%s: here\n", __FUNCTION__);
ASD_DPRINTK("%s: here\n", __func__);
if (!del_timer(&ascb->timer)) {
ASD_DPRINTK("%s: couldn't delete timer\n", __FUNCTION__);
ASD_DPRINTK("%s: couldn't delete timer\n", __func__);
return;
}
ASD_DPRINTK("%s: opcode: 0x%x\n", __FUNCTION__, dl->opcode);
ASD_DPRINTK("%s: opcode: 0x%x\n", __func__, dl->opcode);
tcs->dl_opcode = dl->opcode;
complete(ascb->completion);
asd_ascb_free(ascb);
@ -91,7 +91,7 @@ static void asd_clear_nexus_timedout(unsigned long data)
struct asd_ascb *ascb = (void *)data;
struct tasklet_completion_status *tcs = ascb->uldd_task;
ASD_DPRINTK("%s: here\n", __FUNCTION__);
ASD_DPRINTK("%s: here\n", __func__);
tcs->dl_opcode = TMF_RESP_FUNC_FAILED;
complete(ascb->completion);
}
@ -103,7 +103,7 @@ static void asd_clear_nexus_timedout(unsigned long data)
DECLARE_COMPLETION_ONSTACK(completion); \
DECLARE_TCS(tcs); \
\
ASD_DPRINTK("%s: PRE\n", __FUNCTION__); \
ASD_DPRINTK("%s: PRE\n", __func__); \
res = 1; \
ascb = asd_ascb_alloc_list(asd_ha, &res, GFP_KERNEL); \
if (!ascb) \
@ -115,12 +115,12 @@ static void asd_clear_nexus_timedout(unsigned long data)
scb->header.opcode = CLEAR_NEXUS
#define CLEAR_NEXUS_POST \
ASD_DPRINTK("%s: POST\n", __FUNCTION__); \
ASD_DPRINTK("%s: POST\n", __func__); \
res = asd_enqueue_internal(ascb, asd_clear_nexus_tasklet_complete, \
asd_clear_nexus_timedout); \
if (res) \
goto out_err; \
ASD_DPRINTK("%s: clear nexus posted, waiting...\n", __FUNCTION__); \
ASD_DPRINTK("%s: clear nexus posted, waiting...\n", __func__); \
wait_for_completion(&completion); \
res = tcs.dl_opcode; \
if (res == TC_NO_ERROR) \
@ -417,7 +417,7 @@ int asd_abort_task(struct sas_task *task)
if (task->task_state_flags & SAS_TASK_STATE_DONE) {
spin_unlock_irqrestore(&task->task_state_lock, flags);
res = TMF_RESP_FUNC_COMPLETE;
ASD_DPRINTK("%s: task 0x%p done\n", __FUNCTION__, task);
ASD_DPRINTK("%s: task 0x%p done\n", __func__, task);
goto out_done;
}
spin_unlock_irqrestore(&task->task_state_lock, flags);
@ -481,7 +481,7 @@ int asd_abort_task(struct sas_task *task)
if (task->task_state_flags & SAS_TASK_STATE_DONE) {
spin_unlock_irqrestore(&task->task_state_lock, flags);
res = TMF_RESP_FUNC_COMPLETE;
ASD_DPRINTK("%s: task 0x%p done\n", __FUNCTION__, task);
ASD_DPRINTK("%s: task 0x%p done\n", __func__, task);
goto out_done;
}
spin_unlock_irqrestore(&task->task_state_lock, flags);

View file

@ -240,7 +240,7 @@ static void __fas216_checkmagic(FAS216_Info *info, const char *func)
panic("scsi memory space corrupted in %s", func);
}
}
#define fas216_checkmagic(info) __fas216_checkmagic((info), __FUNCTION__)
#define fas216_checkmagic(info) __fas216_checkmagic((info), __func__)
#else
#define fas216_checkmagic(info)
#endif
@ -2658,7 +2658,7 @@ int fas216_eh_host_reset(struct scsi_cmnd *SCpnt)
fas216_checkmagic(info);
printk("scsi%d.%c: %s: resetting host\n",
info->host->host_no, '0' + SCpnt->device->id, __FUNCTION__);
info->host->host_no, '0' + SCpnt->device->id, __func__);
/*
* Reset the SCSI chip.

View file

@ -930,6 +930,7 @@ static int ch_probe(struct device *dev)
if (init)
ch_init_elem(ch);
dev_set_drvdata(dev, ch);
sdev_printk(KERN_INFO, sd, "Attached scsi changer %s\n", ch->name);
return 0;

View file

@ -30,3 +30,11 @@ config SCSI_DH_EMC
depends on SCSI_DH
help
If you have a EMC CLARiiON select y. Otherwise, say N.
config SCSI_DH_ALUA
tristate "SPC-3 ALUA Device Handler (EXPERIMENTAL)"
depends on SCSI_DH && EXPERIMENTAL
help
SCSI Device handler for generic SPC-3 Asymmetric Logical Unit
Access (ALUA).

View file

@ -5,3 +5,4 @@ obj-$(CONFIG_SCSI_DH) += scsi_dh.o
obj-$(CONFIG_SCSI_DH_RDAC) += scsi_dh_rdac.o
obj-$(CONFIG_SCSI_DH_HP_SW) += scsi_dh_hp_sw.o
obj-$(CONFIG_SCSI_DH_EMC) += scsi_dh_emc.o
obj-$(CONFIG_SCSI_DH_ALUA) += scsi_dh_alua.o

View file

@ -24,8 +24,16 @@
#include <scsi/scsi_dh.h>
#include "../scsi_priv.h"
struct scsi_dh_devinfo_list {
struct list_head node;
char vendor[9];
char model[17];
struct scsi_device_handler *handler;
};
static DEFINE_SPINLOCK(list_lock);
static LIST_HEAD(scsi_dh_list);
static LIST_HEAD(scsi_dh_dev_list);
static struct scsi_device_handler *get_device_handler(const char *name)
{
@ -33,7 +41,7 @@ static struct scsi_device_handler *get_device_handler(const char *name)
spin_lock(&list_lock);
list_for_each_entry(tmp, &scsi_dh_list, list) {
if (!strcmp(tmp->name, name)) {
if (!strncmp(tmp->name, name, strlen(tmp->name))) {
found = tmp;
break;
}
@ -42,11 +50,307 @@ static struct scsi_device_handler *get_device_handler(const char *name)
return found;
}
static struct scsi_device_handler *
scsi_dh_cache_lookup(struct scsi_device *sdev)
{
struct scsi_dh_devinfo_list *tmp;
struct scsi_device_handler *found_dh = NULL;
spin_lock(&list_lock);
list_for_each_entry(tmp, &scsi_dh_dev_list, node) {
if (!strncmp(sdev->vendor, tmp->vendor, strlen(tmp->vendor)) &&
!strncmp(sdev->model, tmp->model, strlen(tmp->model))) {
found_dh = tmp->handler;
break;
}
}
spin_unlock(&list_lock);
return found_dh;
}
static int scsi_dh_handler_lookup(struct scsi_device_handler *scsi_dh,
struct scsi_device *sdev)
{
int i, found = 0;
for(i = 0; scsi_dh->devlist[i].vendor; i++) {
if (!strncmp(sdev->vendor, scsi_dh->devlist[i].vendor,
strlen(scsi_dh->devlist[i].vendor)) &&
!strncmp(sdev->model, scsi_dh->devlist[i].model,
strlen(scsi_dh->devlist[i].model))) {
found = 1;
break;
}
}
return found;
}
/*
* device_handler_match - Attach a device handler to a device
* @scsi_dh - The device handler to match against or NULL
* @sdev - SCSI device to be tested against @scsi_dh
*
* Tests @sdev against the device handler @scsi_dh or against
* all registered device_handler if @scsi_dh == NULL.
* Returns the found device handler or NULL if not found.
*/
static struct scsi_device_handler *
device_handler_match(struct scsi_device_handler *scsi_dh,
struct scsi_device *sdev)
{
struct scsi_device_handler *found_dh = NULL;
struct scsi_dh_devinfo_list *tmp;
found_dh = scsi_dh_cache_lookup(sdev);
if (found_dh)
return found_dh;
if (scsi_dh) {
if (scsi_dh_handler_lookup(scsi_dh, sdev))
found_dh = scsi_dh;
} else {
struct scsi_device_handler *tmp_dh;
spin_lock(&list_lock);
list_for_each_entry(tmp_dh, &scsi_dh_list, list) {
if (scsi_dh_handler_lookup(tmp_dh, sdev))
found_dh = tmp_dh;
}
spin_unlock(&list_lock);
}
if (found_dh) { /* If device is found, add it to the cache */
tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
if (tmp) {
strncpy(tmp->vendor, sdev->vendor, 8);
strncpy(tmp->model, sdev->model, 16);
tmp->vendor[8] = '\0';
tmp->model[16] = '\0';
tmp->handler = found_dh;
spin_lock(&list_lock);
list_add(&tmp->node, &scsi_dh_dev_list);
spin_unlock(&list_lock);
} else {
found_dh = NULL;
}
}
return found_dh;
}
/*
* scsi_dh_handler_attach - Attach a device handler to a device
* @sdev - SCSI device the device handler should attach to
* @scsi_dh - The device handler to attach
*/
static int scsi_dh_handler_attach(struct scsi_device *sdev,
struct scsi_device_handler *scsi_dh)
{
int err = 0;
if (sdev->scsi_dh_data) {
if (sdev->scsi_dh_data->scsi_dh != scsi_dh)
err = -EBUSY;
} else if (scsi_dh->attach)
err = scsi_dh->attach(sdev);
return err;
}
/*
* scsi_dh_handler_detach - Detach a device handler from a device
* @sdev - SCSI device the device handler should be detached from
* @scsi_dh - Device handler to be detached
*
* Detach from a device handler. If a device handler is specified,
* only detach if the currently attached handler matches @scsi_dh.
*/
static void scsi_dh_handler_detach(struct scsi_device *sdev,
struct scsi_device_handler *scsi_dh)
{
if (!sdev->scsi_dh_data)
return;
if (scsi_dh && scsi_dh != sdev->scsi_dh_data->scsi_dh)
return;
if (!scsi_dh)
scsi_dh = sdev->scsi_dh_data->scsi_dh;
if (scsi_dh && scsi_dh->detach)
scsi_dh->detach(sdev);
}
/*
* Functions for sysfs attribute 'dh_state'
*/
static ssize_t
store_dh_state(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct scsi_device *sdev = to_scsi_device(dev);
struct scsi_device_handler *scsi_dh;
int err = -EINVAL;
if (!sdev->scsi_dh_data) {
/*
* Attach to a device handler
*/
if (!(scsi_dh = get_device_handler(buf)))
return err;
err = scsi_dh_handler_attach(sdev, scsi_dh);
} else {
scsi_dh = sdev->scsi_dh_data->scsi_dh;
if (!strncmp(buf, "detach", 6)) {
/*
* Detach from a device handler
*/
scsi_dh_handler_detach(sdev, scsi_dh);
err = 0;
} else if (!strncmp(buf, "activate", 8)) {
/*
* Activate a device handler
*/
if (scsi_dh->activate)
err = scsi_dh->activate(sdev);
else
err = 0;
}
}
return err<0?err:count;
}
static ssize_t
show_dh_state(struct device *dev, struct device_attribute *attr, char *buf)
{
struct scsi_device *sdev = to_scsi_device(dev);
if (!sdev->scsi_dh_data)
return snprintf(buf, 20, "detached\n");
return snprintf(buf, 20, "%s\n", sdev->scsi_dh_data->scsi_dh->name);
}
static struct device_attribute scsi_dh_state_attr =
__ATTR(dh_state, S_IRUGO | S_IWUSR, show_dh_state,
store_dh_state);
/*
* scsi_dh_sysfs_attr_add - Callback for scsi_init_dh
*/
static int scsi_dh_sysfs_attr_add(struct device *dev, void *data)
{
struct scsi_device *sdev;
int err;
if (!scsi_is_sdev_device(dev))
return 0;
sdev = to_scsi_device(dev);
err = device_create_file(&sdev->sdev_gendev,
&scsi_dh_state_attr);
return 0;
}
/*
* scsi_dh_sysfs_attr_remove - Callback for scsi_exit_dh
*/
static int scsi_dh_sysfs_attr_remove(struct device *dev, void *data)
{
struct scsi_device *sdev;
if (!scsi_is_sdev_device(dev))
return 0;
sdev = to_scsi_device(dev);
device_remove_file(&sdev->sdev_gendev,
&scsi_dh_state_attr);
return 0;
}
/*
* scsi_dh_notifier - notifier chain callback
*/
static int scsi_dh_notifier(struct notifier_block *nb,
unsigned long action, void *data)
{
struct device *dev = data;
struct scsi_device *sdev;
int err = 0;
struct scsi_device_handler *devinfo = NULL;
if (!scsi_is_sdev_device(dev))
return 0;
sdev = to_scsi_device(dev);
if (action == BUS_NOTIFY_ADD_DEVICE) {
devinfo = device_handler_match(NULL, sdev);
if (!devinfo)
goto out;
err = scsi_dh_handler_attach(sdev, devinfo);
if (!err)
err = device_create_file(dev, &scsi_dh_state_attr);
} else if (action == BUS_NOTIFY_DEL_DEVICE) {
device_remove_file(dev, &scsi_dh_state_attr);
scsi_dh_handler_detach(sdev, NULL);
}
out:
return err;
}
/*
* scsi_dh_notifier_add - Callback for scsi_register_device_handler
*/
static int scsi_dh_notifier_add(struct device *dev, void *data)
{
struct scsi_device_handler *scsi_dh = data;
struct scsi_device *sdev;
if (!scsi_is_sdev_device(dev))
return 0;
if (!get_device(dev))
return 0;
sdev = to_scsi_device(dev);
if (device_handler_match(scsi_dh, sdev))
scsi_dh_handler_attach(sdev, scsi_dh);
put_device(dev);
return 0;
}
/*
* scsi_dh_notifier_remove - Callback for scsi_unregister_device_handler
*/
static int scsi_dh_notifier_remove(struct device *dev, void *data)
{
struct scsi_device_handler *scsi_dh = data;
struct scsi_device *sdev;
if (!scsi_is_sdev_device(dev))
return 0;
if (!get_device(dev))
return 0;
sdev = to_scsi_device(dev);
scsi_dh_handler_detach(sdev, scsi_dh);
put_device(dev);
scsi_dh->nb.notifier_call(&scsi_dh->nb, BUS_NOTIFY_ADD_DEVICE, dev);
return 0;
}
@ -59,33 +363,19 @@ static int scsi_dh_notifier_add(struct device *dev, void *data)
*/
int scsi_register_device_handler(struct scsi_device_handler *scsi_dh)
{
int ret = -EBUSY;
struct scsi_device_handler *tmp;
if (get_device_handler(scsi_dh->name))
return -EBUSY;
tmp = get_device_handler(scsi_dh->name);
if (tmp)
goto done;
ret = bus_register_notifier(&scsi_bus_type, &scsi_dh->nb);
bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, scsi_dh_notifier_add);
spin_lock(&list_lock);
list_add(&scsi_dh->list, &scsi_dh_list);
spin_unlock(&list_lock);
bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, scsi_dh_notifier_add);
printk(KERN_INFO "%s: device handler registered\n", scsi_dh->name);
done:
return ret;
return SCSI_DH_OK;
}
EXPORT_SYMBOL_GPL(scsi_register_device_handler);
static int scsi_dh_notifier_remove(struct device *dev, void *data)
{
struct scsi_device_handler *scsi_dh = data;
scsi_dh->nb.notifier_call(&scsi_dh->nb, BUS_NOTIFY_DEL_DEVICE, dev);
return 0;
}
/*
* scsi_unregister_device_handler - register a device handler personality
* module.
@ -95,23 +385,26 @@ static int scsi_dh_notifier_remove(struct device *dev, void *data)
*/
int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh)
{
int ret = -ENODEV;
struct scsi_device_handler *tmp;
struct scsi_dh_devinfo_list *tmp, *pos;
tmp = get_device_handler(scsi_dh->name);
if (!tmp)
goto done;
ret = bus_unregister_notifier(&scsi_bus_type, &scsi_dh->nb);
if (!get_device_handler(scsi_dh->name))
return -ENODEV;
bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh,
scsi_dh_notifier_remove);
scsi_dh_notifier_remove);
spin_lock(&list_lock);
list_del(&scsi_dh->list);
list_for_each_entry_safe(pos, tmp, &scsi_dh_dev_list, node) {
if (pos->handler == scsi_dh) {
list_del(&pos->node);
kfree(pos);
}
}
spin_unlock(&list_lock);
printk(KERN_INFO "%s: device handler unregistered\n", scsi_dh->name);
done:
return ret;
return SCSI_DH_OK;
}
EXPORT_SYMBOL_GPL(scsi_unregister_device_handler);
@ -157,6 +450,97 @@ int scsi_dh_handler_exist(const char *name)
}
EXPORT_SYMBOL_GPL(scsi_dh_handler_exist);
/*
* scsi_dh_handler_attach - Attach device handler
* @sdev - sdev the handler should be attached to
* @name - name of the handler to attach
*/
int scsi_dh_attach(struct request_queue *q, const char *name)
{
unsigned long flags;
struct scsi_device *sdev;
struct scsi_device_handler *scsi_dh;
int err = 0;
scsi_dh = get_device_handler(name);
if (!scsi_dh)
return -EINVAL;
spin_lock_irqsave(q->queue_lock, flags);
sdev = q->queuedata;
if (!sdev || !get_device(&sdev->sdev_gendev))
err = -ENODEV;
spin_unlock_irqrestore(q->queue_lock, flags);
if (!err) {
err = scsi_dh_handler_attach(sdev, scsi_dh);
put_device(&sdev->sdev_gendev);
}
return err;
}
EXPORT_SYMBOL_GPL(scsi_dh_attach);
/*
* scsi_dh_handler_detach - Detach device handler
* @sdev - sdev the handler should be detached from
*
* This function will detach the device handler only
* if the sdev is not part of the internal list, ie
* if it has been attached manually.
*/
void scsi_dh_detach(struct request_queue *q)
{
unsigned long flags;
struct scsi_device *sdev;
struct scsi_device_handler *scsi_dh = NULL;
spin_lock_irqsave(q->queue_lock, flags);
sdev = q->queuedata;
if (!sdev || !get_device(&sdev->sdev_gendev))
sdev = NULL;
spin_unlock_irqrestore(q->queue_lock, flags);
if (!sdev)
return;
if (sdev->scsi_dh_data) {
/* if sdev is not on internal list, detach */
scsi_dh = sdev->scsi_dh_data->scsi_dh;
if (!device_handler_match(scsi_dh, sdev))
scsi_dh_handler_detach(sdev, scsi_dh);
}
put_device(&sdev->sdev_gendev);
}
EXPORT_SYMBOL_GPL(scsi_dh_detach);
static struct notifier_block scsi_dh_nb = {
.notifier_call = scsi_dh_notifier
};
static int __init scsi_dh_init(void)
{
int r;
r = bus_register_notifier(&scsi_bus_type, &scsi_dh_nb);
if (!r)
bus_for_each_dev(&scsi_bus_type, NULL, NULL,
scsi_dh_sysfs_attr_add);
return r;
}
static void __exit scsi_dh_exit(void)
{
bus_for_each_dev(&scsi_bus_type, NULL, NULL,
scsi_dh_sysfs_attr_remove);
bus_unregister_notifier(&scsi_bus_type, &scsi_dh_nb);
}
module_init(scsi_dh_init);
module_exit(scsi_dh_exit);
MODULE_DESCRIPTION("SCSI device handler");
MODULE_AUTHOR("Chandra Seetharaman <sekharan@us.ibm.com>");
MODULE_LICENSE("GPL");

View file

@ -0,0 +1,802 @@
/*
* Generic SCSI-3 ALUA SCSI Device Handler
*
* Copyright (C) 2007, 2008 Hannes Reinecke, SUSE Linux Products GmbH.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include <scsi/scsi.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_dh.h>
#define ALUA_DH_NAME "alua"
#define ALUA_DH_VER "1.2"
#define TPGS_STATE_OPTIMIZED 0x0
#define TPGS_STATE_NONOPTIMIZED 0x1
#define TPGS_STATE_STANDBY 0x2
#define TPGS_STATE_UNAVAILABLE 0x3
#define TPGS_STATE_OFFLINE 0xe
#define TPGS_STATE_TRANSITIONING 0xf
#define TPGS_SUPPORT_NONE 0x00
#define TPGS_SUPPORT_OPTIMIZED 0x01
#define TPGS_SUPPORT_NONOPTIMIZED 0x02
#define TPGS_SUPPORT_STANDBY 0x04
#define TPGS_SUPPORT_UNAVAILABLE 0x08
#define TPGS_SUPPORT_OFFLINE 0x40
#define TPGS_SUPPORT_TRANSITION 0x80
#define TPGS_MODE_UNINITIALIZED -1
#define TPGS_MODE_NONE 0x0
#define TPGS_MODE_IMPLICIT 0x1
#define TPGS_MODE_EXPLICIT 0x2
#define ALUA_INQUIRY_SIZE 36
#define ALUA_FAILOVER_TIMEOUT (60 * HZ)
#define ALUA_FAILOVER_RETRIES 5
struct alua_dh_data {
int group_id;
int rel_port;
int tpgs;
int state;
unsigned char inq[ALUA_INQUIRY_SIZE];
unsigned char *buff;
int bufflen;
unsigned char sense[SCSI_SENSE_BUFFERSIZE];
int senselen;
};
#define ALUA_POLICY_SWITCH_CURRENT 0
#define ALUA_POLICY_SWITCH_ALL 1
static inline struct alua_dh_data *get_alua_data(struct scsi_device *sdev)
{
struct scsi_dh_data *scsi_dh_data = sdev->scsi_dh_data;
BUG_ON(scsi_dh_data == NULL);
return ((struct alua_dh_data *) scsi_dh_data->buf);
}
static int realloc_buffer(struct alua_dh_data *h, unsigned len)
{
if (h->buff && h->buff != h->inq)
kfree(h->buff);
h->buff = kmalloc(len, GFP_NOIO);
if (!h->buff) {
h->buff = h->inq;
h->bufflen = ALUA_INQUIRY_SIZE;
return 1;
}
h->bufflen = len;
return 0;
}
static struct request *get_alua_req(struct scsi_device *sdev,
void *buffer, unsigned buflen, int rw)
{
struct request *rq;
struct request_queue *q = sdev->request_queue;
rq = blk_get_request(q, rw, GFP_NOIO);
if (!rq) {
sdev_printk(KERN_INFO, sdev,
"%s: blk_get_request failed\n", __func__);
return NULL;
}
if (buflen && blk_rq_map_kern(q, rq, buffer, buflen, GFP_NOIO)) {
blk_put_request(rq);
sdev_printk(KERN_INFO, sdev,
"%s: blk_rq_map_kern failed\n", __func__);
return NULL;
}
rq->cmd_type = REQ_TYPE_BLOCK_PC;
rq->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE;
rq->retries = ALUA_FAILOVER_RETRIES;
rq->timeout = ALUA_FAILOVER_TIMEOUT;
return rq;
}
/*
* submit_std_inquiry - Issue a standard INQUIRY command
* @sdev: sdev the command should be send to
*/
static int submit_std_inquiry(struct scsi_device *sdev, struct alua_dh_data *h)
{
struct request *rq;
int err = SCSI_DH_RES_TEMP_UNAVAIL;
rq = get_alua_req(sdev, h->inq, ALUA_INQUIRY_SIZE, READ);
if (!rq)
goto done;
/* Prepare the command. */
rq->cmd[0] = INQUIRY;
rq->cmd[1] = 0;
rq->cmd[2] = 0;
rq->cmd[4] = ALUA_INQUIRY_SIZE;
rq->cmd_len = COMMAND_SIZE(INQUIRY);
rq->sense = h->sense;
memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
rq->sense_len = h->senselen = 0;
err = blk_execute_rq(rq->q, NULL, rq, 1);
if (err == -EIO) {
sdev_printk(KERN_INFO, sdev,
"%s: std inquiry failed with %x\n",
ALUA_DH_NAME, rq->errors);
h->senselen = rq->sense_len;
err = SCSI_DH_IO;
}
blk_put_request(rq);
done:
return err;
}
/*
* submit_vpd_inquiry - Issue an INQUIRY VPD page 0x83 command
* @sdev: sdev the command should be sent to
*/
static int submit_vpd_inquiry(struct scsi_device *sdev, struct alua_dh_data *h)
{
struct request *rq;
int err = SCSI_DH_RES_TEMP_UNAVAIL;
rq = get_alua_req(sdev, h->buff, h->bufflen, READ);
if (!rq)
goto done;
/* Prepare the command. */
rq->cmd[0] = INQUIRY;
rq->cmd[1] = 1;
rq->cmd[2] = 0x83;
rq->cmd[4] = h->bufflen;
rq->cmd_len = COMMAND_SIZE(INQUIRY);
rq->sense = h->sense;
memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
rq->sense_len = h->senselen = 0;
err = blk_execute_rq(rq->q, NULL, rq, 1);
if (err == -EIO) {
sdev_printk(KERN_INFO, sdev,
"%s: evpd inquiry failed with %x\n",
ALUA_DH_NAME, rq->errors);
h->senselen = rq->sense_len;
err = SCSI_DH_IO;
}
blk_put_request(rq);
done:
return err;
}
/*
* submit_rtpg - Issue a REPORT TARGET GROUP STATES command
* @sdev: sdev the command should be sent to
*/
static unsigned submit_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
{
struct request *rq;
int err = SCSI_DH_RES_TEMP_UNAVAIL;
rq = get_alua_req(sdev, h->buff, h->bufflen, READ);
if (!rq)
goto done;
/* Prepare the command. */
rq->cmd[0] = MAINTENANCE_IN;
rq->cmd[1] = MI_REPORT_TARGET_PGS;
rq->cmd[6] = (h->bufflen >> 24) & 0xff;
rq->cmd[7] = (h->bufflen >> 16) & 0xff;
rq->cmd[8] = (h->bufflen >> 8) & 0xff;
rq->cmd[9] = h->bufflen & 0xff;
rq->cmd_len = COMMAND_SIZE(MAINTENANCE_IN);
rq->sense = h->sense;
memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
rq->sense_len = h->senselen = 0;
err = blk_execute_rq(rq->q, NULL, rq, 1);
if (err == -EIO) {
sdev_printk(KERN_INFO, sdev,
"%s: rtpg failed with %x\n",
ALUA_DH_NAME, rq->errors);
h->senselen = rq->sense_len;
err = SCSI_DH_IO;
}
blk_put_request(rq);
done:
return err;
}
/*
* submit_stpg - Issue a SET TARGET GROUP STATES command
* @sdev: sdev the command should be sent to
*
* Currently we're only setting the current target port group state
* to 'active/optimized' and let the array firmware figure out
* the states of the remaining groups.
*/
static unsigned submit_stpg(struct scsi_device *sdev, struct alua_dh_data *h)
{
struct request *rq;
int err = SCSI_DH_RES_TEMP_UNAVAIL;
int stpg_len = 8;
/* Prepare the data buffer */
memset(h->buff, 0, stpg_len);
h->buff[4] = TPGS_STATE_OPTIMIZED & 0x0f;
h->buff[6] = (h->group_id >> 8) & 0x0f;
h->buff[7] = h->group_id & 0x0f;
rq = get_alua_req(sdev, h->buff, stpg_len, WRITE);
if (!rq)
goto done;
/* Prepare the command. */
rq->cmd[0] = MAINTENANCE_OUT;
rq->cmd[1] = MO_SET_TARGET_PGS;
rq->cmd[6] = (stpg_len >> 24) & 0xff;
rq->cmd[7] = (stpg_len >> 16) & 0xff;
rq->cmd[8] = (stpg_len >> 8) & 0xff;
rq->cmd[9] = stpg_len & 0xff;
rq->cmd_len = COMMAND_SIZE(MAINTENANCE_OUT);
rq->sense = h->sense;
memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
rq->sense_len = h->senselen = 0;
err = blk_execute_rq(rq->q, NULL, rq, 1);
if (err == -EIO) {
sdev_printk(KERN_INFO, sdev,
"%s: stpg failed with %x\n",
ALUA_DH_NAME, rq->errors);
h->senselen = rq->sense_len;
err = SCSI_DH_IO;
}
blk_put_request(rq);
done:
return err;
}
/*
* alua_std_inquiry - Evaluate standard INQUIRY command
* @sdev: device to be checked
*
* Just extract the TPGS setting to find out if ALUA
* is supported.
*/
static int alua_std_inquiry(struct scsi_device *sdev, struct alua_dh_data *h)
{
int err;
err = submit_std_inquiry(sdev, h);
if (err != SCSI_DH_OK)
return err;
/* Check TPGS setting */
h->tpgs = (h->inq[5] >> 4) & 0x3;
switch (h->tpgs) {
case TPGS_MODE_EXPLICIT|TPGS_MODE_IMPLICIT:
sdev_printk(KERN_INFO, sdev,
"%s: supports implicit and explicit TPGS\n",
ALUA_DH_NAME);
break;
case TPGS_MODE_EXPLICIT:
sdev_printk(KERN_INFO, sdev, "%s: supports explicit TPGS\n",
ALUA_DH_NAME);
break;
case TPGS_MODE_IMPLICIT:
sdev_printk(KERN_INFO, sdev, "%s: supports implicit TPGS\n",
ALUA_DH_NAME);
break;
default:
h->tpgs = TPGS_MODE_NONE;
sdev_printk(KERN_INFO, sdev, "%s: not supported\n",
ALUA_DH_NAME);
err = SCSI_DH_DEV_UNSUPP;
break;
}
return err;
}
/*
* alua_vpd_inquiry - Evaluate INQUIRY vpd page 0x83
* @sdev: device to be checked
*
* Extract the relative target port and the target port group
* descriptor from the list of identificators.
*/
static int alua_vpd_inquiry(struct scsi_device *sdev, struct alua_dh_data *h)
{
int len;
unsigned err;
unsigned char *d;
retry:
err = submit_vpd_inquiry(sdev, h);
if (err != SCSI_DH_OK)
return err;
/* Check if vpd page exceeds initial buffer */
len = (h->buff[2] << 8) + h->buff[3] + 4;
if (len > h->bufflen) {
/* Resubmit with the correct length */
if (realloc_buffer(h, len)) {
sdev_printk(KERN_WARNING, sdev,
"%s: kmalloc buffer failed\n",
ALUA_DH_NAME);
/* Temporary failure, bypass */
return SCSI_DH_DEV_TEMP_BUSY;
}
goto retry;
}
/*
* Now look for the correct descriptor.
*/
d = h->buff + 4;
while (d < h->buff + len) {
switch (d[1] & 0xf) {
case 0x4:
/* Relative target port */
h->rel_port = (d[6] << 8) + d[7];
break;
case 0x5:
/* Target port group */
h->group_id = (d[6] << 8) + d[7];
break;
default:
break;
}
d += d[3] + 4;
}
if (h->group_id == -1) {
/*
* Internal error; TPGS supported but required
* VPD identification descriptors not present.
* Disable ALUA support
*/
sdev_printk(KERN_INFO, sdev,
"%s: No target port descriptors found\n",
ALUA_DH_NAME);
h->state = TPGS_STATE_OPTIMIZED;
h->tpgs = TPGS_MODE_NONE;
err = SCSI_DH_DEV_UNSUPP;
} else {
sdev_printk(KERN_INFO, sdev,
"%s: port group %02x rel port %02x\n",
ALUA_DH_NAME, h->group_id, h->rel_port);
}
return err;
}
static char print_alua_state(int state)
{
switch (state) {
case TPGS_STATE_OPTIMIZED:
return 'A';
case TPGS_STATE_NONOPTIMIZED:
return 'N';
case TPGS_STATE_STANDBY:
return 'S';
case TPGS_STATE_UNAVAILABLE:
return 'U';
case TPGS_STATE_OFFLINE:
return 'O';
case TPGS_STATE_TRANSITIONING:
return 'T';
default:
return 'X';
}
}
static int alua_check_sense(struct scsi_device *sdev,
struct scsi_sense_hdr *sense_hdr)
{
switch (sense_hdr->sense_key) {
case NOT_READY:
if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x0a)
/*
* LUN Not Accessible - ALUA state transition
*/
return NEEDS_RETRY;
if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x0b)
/*
* LUN Not Accessible -- Target port in standby state
*/
return SUCCESS;
if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x0c)
/*
* LUN Not Accessible -- Target port in unavailable state
*/
return SUCCESS;
if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x12)
/*
* LUN Not Ready -- Offline
*/
return SUCCESS;
break;
case UNIT_ATTENTION:
if (sense_hdr->asc == 0x29 && sense_hdr->ascq == 0x00)
/*
* Power On, Reset, or Bus Device Reset, just retry.
*/
return NEEDS_RETRY;
if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x06) {
/*
* ALUA state changed
*/
return NEEDS_RETRY;
}
if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x07) {
/*
* Implicit ALUA state transition failed
*/
return NEEDS_RETRY;
}
break;
}
return SCSI_RETURN_NOT_HANDLED;
}
/*
* alua_stpg - Evaluate SET TARGET GROUP STATES
* @sdev: the device to be evaluated
* @state: the new target group state
*
* Send a SET TARGET GROUP STATES command to the device.
* We only have to test here if we should resubmit the command;
* any other error is assumed as a failure.
*/
static int alua_stpg(struct scsi_device *sdev, int state,
struct alua_dh_data *h)
{
struct scsi_sense_hdr sense_hdr;
unsigned err;
int retry = ALUA_FAILOVER_RETRIES;
retry:
err = submit_stpg(sdev, h);
if (err == SCSI_DH_IO && h->senselen > 0) {
err = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
&sense_hdr);
if (!err)
return SCSI_DH_IO;
err = alua_check_sense(sdev, &sense_hdr);
if (retry > 0 && err == NEEDS_RETRY) {
retry--;
goto retry;
}
sdev_printk(KERN_INFO, sdev,
"%s: stpg sense code: %02x/%02x/%02x\n",
ALUA_DH_NAME, sense_hdr.sense_key,
sense_hdr.asc, sense_hdr.ascq);
err = SCSI_DH_IO;
}
if (err == SCSI_DH_OK) {
h->state = state;
sdev_printk(KERN_INFO, sdev,
"%s: port group %02x switched to state %c\n",
ALUA_DH_NAME, h->group_id,
print_alua_state(h->state) );
}
return err;
}
/*
* alua_rtpg - Evaluate REPORT TARGET GROUP STATES
* @sdev: the device to be evaluated.
*
* Evaluate the Target Port Group State.
* Returns SCSI_DH_DEV_OFFLINED if the path is
* found to be unuseable.
*/
static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
{
struct scsi_sense_hdr sense_hdr;
int len, k, off, valid_states = 0;
char *ucp;
unsigned err;
retry:
err = submit_rtpg(sdev, h);
if (err == SCSI_DH_IO && h->senselen > 0) {
err = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
&sense_hdr);
if (!err)
return SCSI_DH_IO;
err = alua_check_sense(sdev, &sense_hdr);
if (err == NEEDS_RETRY)
goto retry;
sdev_printk(KERN_INFO, sdev,
"%s: rtpg sense code %02x/%02x/%02x\n",
ALUA_DH_NAME, sense_hdr.sense_key,
sense_hdr.asc, sense_hdr.ascq);
err = SCSI_DH_IO;
}
if (err != SCSI_DH_OK)
return err;
len = (h->buff[0] << 24) + (h->buff[1] << 16) +
(h->buff[2] << 8) + h->buff[3] + 4;
if (len > h->bufflen) {
/* Resubmit with the correct length */
if (realloc_buffer(h, len)) {
sdev_printk(KERN_WARNING, sdev,
"%s: kmalloc buffer failed\n",__func__);
/* Temporary failure, bypass */
return SCSI_DH_DEV_TEMP_BUSY;
}
goto retry;
}
for (k = 4, ucp = h->buff + 4; k < len; k += off, ucp += off) {
if (h->group_id == (ucp[2] << 8) + ucp[3]) {
h->state = ucp[0] & 0x0f;
valid_states = ucp[1];
}
off = 8 + (ucp[7] * 4);
}
sdev_printk(KERN_INFO, sdev,
"%s: port group %02x state %c supports %c%c%c%c%c%c\n",
ALUA_DH_NAME, h->group_id, print_alua_state(h->state),
valid_states&TPGS_SUPPORT_TRANSITION?'T':'t',
valid_states&TPGS_SUPPORT_OFFLINE?'O':'o',
valid_states&TPGS_SUPPORT_UNAVAILABLE?'U':'u',
valid_states&TPGS_SUPPORT_STANDBY?'S':'s',
valid_states&TPGS_SUPPORT_NONOPTIMIZED?'N':'n',
valid_states&TPGS_SUPPORT_OPTIMIZED?'A':'a');
if (h->tpgs & TPGS_MODE_EXPLICIT) {
switch (h->state) {
case TPGS_STATE_TRANSITIONING:
/* State transition, retry */
goto retry;
break;
case TPGS_STATE_OFFLINE:
/* Path is offline, fail */
err = SCSI_DH_DEV_OFFLINED;
break;
default:
break;
}
} else {
/* Only Implicit ALUA support */
if (h->state == TPGS_STATE_OPTIMIZED ||
h->state == TPGS_STATE_NONOPTIMIZED ||
h->state == TPGS_STATE_STANDBY)
/* Useable path if active */
err = SCSI_DH_OK;
else
/* Path unuseable for unavailable/offline */
err = SCSI_DH_DEV_OFFLINED;
}
return err;
}
/*
* alua_initialize - Initialize ALUA state
* @sdev: the device to be initialized
*
* For the prep_fn to work correctly we have
* to initialize the ALUA state for the device.
*/
static int alua_initialize(struct scsi_device *sdev, struct alua_dh_data *h)
{
int err;
err = alua_std_inquiry(sdev, h);
if (err != SCSI_DH_OK)
goto out;
err = alua_vpd_inquiry(sdev, h);
if (err != SCSI_DH_OK)
goto out;
err = alua_rtpg(sdev, h);
if (err != SCSI_DH_OK)
goto out;
out:
return err;
}
/*
* alua_activate - activate a path
* @sdev: device on the path to be activated
*
* We're currently switching the port group to be activated only and
* let the array figure out the rest.
* There may be other arrays which require us to switch all port groups
* based on a certain policy. But until we actually encounter them it
* should be okay.
*/
static int alua_activate(struct scsi_device *sdev)
{
struct alua_dh_data *h = get_alua_data(sdev);
int err = SCSI_DH_OK;
if (h->group_id != -1) {
err = alua_rtpg(sdev, h);
if (err != SCSI_DH_OK)
goto out;
}
if (h->tpgs == TPGS_MODE_EXPLICIT && h->state != TPGS_STATE_OPTIMIZED)
err = alua_stpg(sdev, TPGS_STATE_OPTIMIZED, h);
out:
return err;
}
/*
* alua_prep_fn - request callback
*
* Fail I/O to all paths not in state
* active/optimized or active/non-optimized.
*/
static int alua_prep_fn(struct scsi_device *sdev, struct request *req)
{
struct alua_dh_data *h = get_alua_data(sdev);
int ret = BLKPREP_OK;
if (h->state != TPGS_STATE_OPTIMIZED &&
h->state != TPGS_STATE_NONOPTIMIZED) {
ret = BLKPREP_KILL;
req->cmd_flags |= REQ_QUIET;
}
return ret;
}
const struct scsi_dh_devlist alua_dev_list[] = {
{"HP", "MSA VOLUME" },
{"HP", "HSV101" },
{"HP", "HSV111" },
{"HP", "HSV200" },
{"HP", "HSV210" },
{"HP", "HSV300" },
{"IBM", "2107900" },
{"IBM", "2145" },
{"Pillar", "Axiom" },
{NULL, NULL}
};
static int alua_bus_attach(struct scsi_device *sdev);
static void alua_bus_detach(struct scsi_device *sdev);
static struct scsi_device_handler alua_dh = {
.name = ALUA_DH_NAME,
.module = THIS_MODULE,
.devlist = alua_dev_list,
.attach = alua_bus_attach,
.detach = alua_bus_detach,
.prep_fn = alua_prep_fn,
.check_sense = alua_check_sense,
.activate = alua_activate,
};
/*
* alua_bus_attach - Attach device handler
* @sdev: device to be attached to
*/
static int alua_bus_attach(struct scsi_device *sdev)
{
struct scsi_dh_data *scsi_dh_data;
struct alua_dh_data *h;
unsigned long flags;
int err = SCSI_DH_OK;
scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
+ sizeof(*h) , GFP_KERNEL);
if (!scsi_dh_data) {
sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n",
ALUA_DH_NAME);
return -ENOMEM;
}
scsi_dh_data->scsi_dh = &alua_dh;
h = (struct alua_dh_data *) scsi_dh_data->buf;
h->tpgs = TPGS_MODE_UNINITIALIZED;
h->state = TPGS_STATE_OPTIMIZED;
h->group_id = -1;
h->rel_port = -1;
h->buff = h->inq;
h->bufflen = ALUA_INQUIRY_SIZE;
err = alua_initialize(sdev, h);
if (err != SCSI_DH_OK)
goto failed;
if (!try_module_get(THIS_MODULE))
goto failed;
spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
sdev->scsi_dh_data = scsi_dh_data;
spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
return 0;
failed:
kfree(scsi_dh_data);
sdev_printk(KERN_ERR, sdev, "%s: not attached\n", ALUA_DH_NAME);
return -EINVAL;
}
/*
* alua_bus_detach - Detach device handler
* @sdev: device to be detached from
*/
static void alua_bus_detach(struct scsi_device *sdev)
{
struct scsi_dh_data *scsi_dh_data;
struct alua_dh_data *h;
unsigned long flags;
spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
scsi_dh_data = sdev->scsi_dh_data;
sdev->scsi_dh_data = NULL;
spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
h = (struct alua_dh_data *) scsi_dh_data->buf;
if (h->buff && h->inq != h->buff)
kfree(h->buff);
kfree(scsi_dh_data);
module_put(THIS_MODULE);
sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", ALUA_DH_NAME);
}
static int __init alua_init(void)
{
int r;
r = scsi_register_device_handler(&alua_dh);
if (r != 0)
printk(KERN_ERR "%s: Failed to register scsi device handler",
ALUA_DH_NAME);
return r;
}
static void __exit alua_exit(void)
{
scsi_unregister_device_handler(&alua_dh);
}
module_init(alua_init);
module_exit(alua_exit);
MODULE_DESCRIPTION("DM Multipath ALUA support");
MODULE_AUTHOR("Hannes Reinecke <hare@suse.de>");
MODULE_LICENSE("GPL");
MODULE_VERSION(ALUA_DH_VER);

View file

@ -25,28 +25,31 @@
#include <scsi/scsi_dh.h>
#include <scsi/scsi_device.h>
#define CLARIION_NAME "emc_clariion"
#define CLARIION_NAME "emc"
#define CLARIION_TRESPASS_PAGE 0x22
#define CLARIION_BUFFER_SIZE 0x80
#define CLARIION_BUFFER_SIZE 0xFC
#define CLARIION_TIMEOUT (60 * HZ)
#define CLARIION_RETRIES 3
#define CLARIION_UNBOUND_LU -1
#define CLARIION_SP_A 0
#define CLARIION_SP_B 1
/* Flags */
#define CLARIION_SHORT_TRESPASS 1
#define CLARIION_HONOR_RESERVATIONS 2
/* LUN states */
#define CLARIION_LUN_UNINITIALIZED -1
#define CLARIION_LUN_UNBOUND 0
#define CLARIION_LUN_BOUND 1
#define CLARIION_LUN_OWNED 2
static unsigned char long_trespass[] = {
0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
CLARIION_TRESPASS_PAGE, /* Page code */
0x09, /* Page length - 2 */
0x81, /* Trespass code + Honor reservation bit */
0xff, 0xff, /* Trespass target */
0, 0, 0, 0, 0, 0 /* Reserved bytes / unknown */
};
static unsigned char long_trespass_hr[] = {
0, 0, 0, 0,
CLARIION_TRESPASS_PAGE, /* Page code */
0x09, /* Page length - 2 */
0x01, /* Trespass code + Honor reservation bit */
0x01, /* Trespass code */
0xff, 0xff, /* Trespass target */
0, 0, 0, 0, 0, 0 /* Reserved bytes / unknown */
};
@ -55,39 +58,56 @@ static unsigned char short_trespass[] = {
0, 0, 0, 0,
CLARIION_TRESPASS_PAGE, /* Page code */
0x02, /* Page length - 2 */
0x81, /* Trespass code + Honor reservation bit */
0x01, /* Trespass code */
0xff, /* Trespass target */
};
static unsigned char short_trespass_hr[] = {
0, 0, 0, 0,
CLARIION_TRESPASS_PAGE, /* Page code */
0x02, /* Page length - 2 */
0x01, /* Trespass code + Honor reservation bit */
0xff, /* Trespass target */
static const char * lun_state[] =
{
"not bound",
"bound",
"owned",
};
struct clariion_dh_data {
/*
* Flags:
* CLARIION_SHORT_TRESPASS
* Use short trespass command (FC-series) or the long version
* (default for AX/CX CLARiiON arrays).
*/
unsigned short_trespass;
/*
*
* CLARIION_HONOR_RESERVATIONS
* Whether or not (default) to honor SCSI reservations when
* initiating a switch-over.
*/
unsigned hr;
/* I/O buffer for both MODE_SELECT and INQUIRY commands. */
unsigned flags;
/*
* I/O buffer for both MODE_SELECT and INQUIRY commands.
*/
char buffer[CLARIION_BUFFER_SIZE];
/*
* SCSI sense buffer for commands -- assumes serial issuance
* and completion sequence of all commands for same multipath.
*/
unsigned char sense[SCSI_SENSE_BUFFERSIZE];
/* which SP (A=0,B=1,UNBOUND=-1) is dflt SP for path's mapped dev */
unsigned int senselen;
/*
* LUN state
*/
int lun_state;
/*
* SP Port number
*/
int port;
/*
* which SP (A=0,B=1,UNBOUND=-1) is the default SP for this
* path's mapped LUN
*/
int default_sp;
/* which SP (A=0,B=1,UNBOUND=-1) is active for path's mapped dev */
/*
* which SP (A=0,B=1,UNBOUND=-1) is the active SP for this
* path's mapped LUN
*/
int current_sp;
};
@ -102,19 +122,16 @@ static inline struct clariion_dh_data
/*
* Parse MODE_SELECT cmd reply.
*/
static int trespass_endio(struct scsi_device *sdev, int result)
static int trespass_endio(struct scsi_device *sdev, char *sense)
{
int err = SCSI_DH_OK;
int err = SCSI_DH_IO;
struct scsi_sense_hdr sshdr;
struct clariion_dh_data *csdev = get_clariion_data(sdev);
char *sense = csdev->sense;
if (status_byte(result) == CHECK_CONDITION &&
scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, &sshdr)) {
sdev_printk(KERN_ERR, sdev, "Found valid sense data 0x%2x, "
if (!scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, &sshdr)) {
sdev_printk(KERN_ERR, sdev, "%s: Found valid sense data 0x%2x, "
"0x%2x, 0x%2x while sending CLARiiON trespass "
"command.\n", sshdr.sense_key, sshdr.asc,
sshdr.ascq);
"command.\n", CLARIION_NAME, sshdr.sense_key,
sshdr.asc, sshdr.ascq);
if ((sshdr.sense_key == 0x05) && (sshdr.asc == 0x04) &&
(sshdr.ascq == 0x00)) {
@ -122,9 +139,9 @@ static int trespass_endio(struct scsi_device *sdev, int result)
* Array based copy in progress -- do not send
* mode_select or copy will be aborted mid-stream.
*/
sdev_printk(KERN_INFO, sdev, "Array Based Copy in "
sdev_printk(KERN_INFO, sdev, "%s: Array Based Copy in "
"progress while sending CLARiiON trespass "
"command.\n");
"command.\n", CLARIION_NAME);
err = SCSI_DH_DEV_TEMP_BUSY;
} else if ((sshdr.sense_key == 0x02) && (sshdr.asc == 0x04) &&
(sshdr.ascq == 0x03)) {
@ -132,160 +149,153 @@ static int trespass_endio(struct scsi_device *sdev, int result)
* LUN Not Ready - Manual Intervention Required
* indicates in-progress ucode upgrade (NDU).
*/
sdev_printk(KERN_INFO, sdev, "Detected in-progress "
sdev_printk(KERN_INFO, sdev, "%s: Detected in-progress "
"ucode upgrade NDU operation while sending "
"CLARiiON trespass command.\n");
"CLARiiON trespass command.\n", CLARIION_NAME);
err = SCSI_DH_DEV_TEMP_BUSY;
} else
err = SCSI_DH_DEV_FAILED;
} else if (result) {
sdev_printk(KERN_ERR, sdev, "Error 0x%x while sending "
"CLARiiON trespass command.\n", result);
err = SCSI_DH_IO;
} else {
sdev_printk(KERN_INFO, sdev,
"%s: failed to send MODE SELECT, no sense available\n",
CLARIION_NAME);
}
return err;
}
static int parse_sp_info_reply(struct scsi_device *sdev, int result,
int *default_sp, int *current_sp, int *new_current_sp)
static int parse_sp_info_reply(struct scsi_device *sdev,
struct clariion_dh_data *csdev)
{
int err = SCSI_DH_OK;
struct clariion_dh_data *csdev = get_clariion_data(sdev);
if (result == 0) {
/* check for in-progress ucode upgrade (NDU) */
if (csdev->buffer[48] != 0) {
sdev_printk(KERN_NOTICE, sdev, "Detected in-progress "
"ucode upgrade NDU operation while finding "
"current active SP.");
err = SCSI_DH_DEV_TEMP_BUSY;
} else {
*default_sp = csdev->buffer[5];
if (csdev->buffer[4] == 2)
/* SP for path is current */
*current_sp = csdev->buffer[8];
else {
if (csdev->buffer[4] == 1)
/* SP for this path is NOT current */
if (csdev->buffer[8] == 0)
*current_sp = 1;
else
*current_sp = 0;
else
/* unbound LU or LUNZ */
*current_sp = CLARIION_UNBOUND_LU;
}
*new_current_sp = csdev->buffer[8];
}
} else {
struct scsi_sense_hdr sshdr;
err = SCSI_DH_IO;
if (scsi_normalize_sense(csdev->sense, SCSI_SENSE_BUFFERSIZE,
&sshdr))
sdev_printk(KERN_ERR, sdev, "Found valid sense data "
"0x%2x, 0x%2x, 0x%2x while finding current "
"active SP.", sshdr.sense_key, sshdr.asc,
sshdr.ascq);
else
sdev_printk(KERN_ERR, sdev, "Error 0x%x finding "
"current active SP.", result);
/* check for in-progress ucode upgrade (NDU) */
if (csdev->buffer[48] != 0) {
sdev_printk(KERN_NOTICE, sdev, "%s: Detected in-progress "
"ucode upgrade NDU operation while finding "
"current active SP.", CLARIION_NAME);
err = SCSI_DH_DEV_TEMP_BUSY;
goto out;
}
if (csdev->buffer[4] < 0 || csdev->buffer[4] > 2) {
/* Invalid buffer format */
sdev_printk(KERN_NOTICE, sdev,
"%s: invalid VPD page 0xC0 format\n",
CLARIION_NAME);
err = SCSI_DH_NOSYS;
goto out;
}
switch (csdev->buffer[28] & 0x0f) {
case 6:
sdev_printk(KERN_NOTICE, sdev,
"%s: ALUA failover mode detected\n",
CLARIION_NAME);
break;
case 4:
/* Linux failover */
break;
default:
sdev_printk(KERN_WARNING, sdev,
"%s: Invalid failover mode %d\n",
CLARIION_NAME, csdev->buffer[28] & 0x0f);
err = SCSI_DH_NOSYS;
goto out;
}
csdev->default_sp = csdev->buffer[5];
csdev->lun_state = csdev->buffer[4];
csdev->current_sp = csdev->buffer[8];
csdev->port = csdev->buffer[7];
out:
return err;
}
static int sp_info_endio(struct scsi_device *sdev, int result,
int mode_select_sent, int *done)
#define emc_default_str "FC (Legacy)"
static char * parse_sp_model(struct scsi_device *sdev, unsigned char *buffer)
{
struct clariion_dh_data *csdev = get_clariion_data(sdev);
int err_flags, default_sp, current_sp, new_current_sp;
unsigned char len = buffer[4] + 5;
char *sp_model = NULL;
unsigned char sp_len, serial_len;
err_flags = parse_sp_info_reply(sdev, result, &default_sp,
&current_sp, &new_current_sp);
if (err_flags != SCSI_DH_OK)
goto done;
if (mode_select_sent) {
csdev->default_sp = default_sp;
csdev->current_sp = current_sp;
} else {
/*
* Issue the actual module_selec request IFF either
* (1) we do not know the identity of the current SP OR
* (2) what we think we know is actually correct.
*/
if ((current_sp != CLARIION_UNBOUND_LU) &&
(new_current_sp != current_sp)) {
csdev->default_sp = default_sp;
csdev->current_sp = current_sp;
sdev_printk(KERN_INFO, sdev, "Ignoring path group "
"switch-over command for CLARiiON SP%s since "
" mapped device is already initialized.",
current_sp ? "B" : "A");
if (done)
*done = 1; /* as good as doing it */
if (len < 160) {
sdev_printk(KERN_WARNING, sdev,
"%s: Invalid information section length %d\n",
CLARIION_NAME, len);
/* Check for old FC arrays */
if (!strncmp(buffer + 8, "DGC", 3)) {
/* Old FC array, not supporting extended information */
sp_model = emc_default_str;
}
goto out;
}
done:
return err_flags;
/*
* Parse extended information for SP model number
*/
serial_len = buffer[160];
if (serial_len == 0 || serial_len + 161 > len) {
sdev_printk(KERN_WARNING, sdev,
"%s: Invalid array serial number length %d\n",
CLARIION_NAME, serial_len);
goto out;
}
sp_len = buffer[99];
if (sp_len == 0 || serial_len + sp_len + 161 > len) {
sdev_printk(KERN_WARNING, sdev,
"%s: Invalid model number length %d\n",
CLARIION_NAME, sp_len);
goto out;
}
sp_model = &buffer[serial_len + 161];
/* Strip whitespace at the end */
while (sp_len > 1 && sp_model[sp_len - 1] == ' ')
sp_len--;
sp_model[sp_len] = '\0';
out:
return sp_model;
}
/*
* Get block request for REQ_BLOCK_PC command issued to path. Currently
* limited to MODE_SELECT (trespass) and INQUIRY (VPD page 0xC0) commands.
*
* Uses data and sense buffers in hardware handler context structure and
* assumes serial servicing of commands, both issuance and completion.
*/
static struct request *get_req(struct scsi_device *sdev, int cmd)
* Get block request for REQ_BLOCK_PC command issued to path. Currently
* limited to MODE_SELECT (trespass) and INQUIRY (VPD page 0xC0) commands.
*
* Uses data and sense buffers in hardware handler context structure and
* assumes serial servicing of commands, both issuance and completion.
*/
static struct request *get_req(struct scsi_device *sdev, int cmd,
unsigned char *buffer)
{
struct clariion_dh_data *csdev = get_clariion_data(sdev);
struct request *rq;
unsigned char *page22;
int len = 0;
rq = blk_get_request(sdev->request_queue,
(cmd == MODE_SELECT) ? WRITE : READ, GFP_ATOMIC);
(cmd == MODE_SELECT) ? WRITE : READ, GFP_NOIO);
if (!rq) {
sdev_printk(KERN_INFO, sdev, "get_req: blk_get_request failed");
return NULL;
}
memset(&rq->cmd, 0, BLK_MAX_CDB);
memset(rq->cmd, 0, BLK_MAX_CDB);
rq->cmd_len = COMMAND_SIZE(cmd);
rq->cmd[0] = cmd;
rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);
switch (cmd) {
case MODE_SELECT:
if (csdev->short_trespass) {
page22 = csdev->hr ? short_trespass_hr : short_trespass;
len = sizeof(short_trespass);
} else {
page22 = csdev->hr ? long_trespass_hr : long_trespass;
len = sizeof(long_trespass);
}
/*
* Can't DMA from kernel BSS -- must copy selected trespass
* command mode page contents to context buffer which is
* allocated by kmalloc.
*/
BUG_ON((len > CLARIION_BUFFER_SIZE));
memcpy(csdev->buffer, page22, len);
len = sizeof(short_trespass);
rq->cmd_flags |= REQ_RW;
rq->cmd[1] = 0x10;
break;
case MODE_SELECT_10:
len = sizeof(long_trespass);
rq->cmd_flags |= REQ_RW;
rq->cmd[1] = 0x10;
break;
case INQUIRY:
rq->cmd[1] = 0x1;
rq->cmd[2] = 0xC0;
len = CLARIION_BUFFER_SIZE;
memset(csdev->buffer, 0, CLARIION_BUFFER_SIZE);
memset(buffer, 0, len);
break;
default:
BUG_ON(1);
@ -298,47 +308,94 @@ static struct request *get_req(struct scsi_device *sdev, int cmd)
rq->timeout = CLARIION_TIMEOUT;
rq->retries = CLARIION_RETRIES;
rq->sense = csdev->sense;
memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
rq->sense_len = 0;
if (blk_rq_map_kern(sdev->request_queue, rq, csdev->buffer,
len, GFP_ATOMIC)) {
__blk_put_request(rq->q, rq);
if (blk_rq_map_kern(rq->q, rq, buffer, len, GFP_NOIO)) {
blk_put_request(rq);
return NULL;
}
return rq;
}
static int send_cmd(struct scsi_device *sdev, int cmd)
static int send_inquiry_cmd(struct scsi_device *sdev, int page,
struct clariion_dh_data *csdev)
{
struct request *rq = get_req(sdev, cmd);
struct request *rq = get_req(sdev, INQUIRY, csdev->buffer);
int err;
if (!rq)
return SCSI_DH_RES_TEMP_UNAVAIL;
return blk_execute_rq(sdev->request_queue, NULL, rq, 1);
rq->sense = csdev->sense;
memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
rq->sense_len = csdev->senselen = 0;
rq->cmd[0] = INQUIRY;
if (page != 0) {
rq->cmd[1] = 1;
rq->cmd[2] = page;
}
err = blk_execute_rq(sdev->request_queue, NULL, rq, 1);
if (err == -EIO) {
sdev_printk(KERN_INFO, sdev,
"%s: failed to send %s INQUIRY: %x\n",
CLARIION_NAME, page?"EVPD":"standard",
rq->errors);
csdev->senselen = rq->sense_len;
err = SCSI_DH_IO;
}
blk_put_request(rq);
return err;
}
static int clariion_activate(struct scsi_device *sdev)
static int send_trespass_cmd(struct scsi_device *sdev,
struct clariion_dh_data *csdev)
{
int result, done = 0;
struct request *rq;
unsigned char *page22;
int err, len, cmd;
result = send_cmd(sdev, INQUIRY);
result = sp_info_endio(sdev, result, 0, &done);
if (result || done)
goto done;
if (csdev->flags & CLARIION_SHORT_TRESPASS) {
page22 = short_trespass;
if (!(csdev->flags & CLARIION_HONOR_RESERVATIONS))
/* Set Honor Reservations bit */
page22[6] |= 0x80;
len = sizeof(short_trespass);
cmd = MODE_SELECT;
} else {
page22 = long_trespass;
if (!(csdev->flags & CLARIION_HONOR_RESERVATIONS))
/* Set Honor Reservations bit */
page22[10] |= 0x80;
len = sizeof(long_trespass);
cmd = MODE_SELECT_10;
}
BUG_ON((len > CLARIION_BUFFER_SIZE));
memcpy(csdev->buffer, page22, len);
result = send_cmd(sdev, MODE_SELECT);
result = trespass_endio(sdev, result);
if (result)
goto done;
rq = get_req(sdev, cmd, csdev->buffer);
if (!rq)
return SCSI_DH_RES_TEMP_UNAVAIL;
result = send_cmd(sdev, INQUIRY);
result = sp_info_endio(sdev, result, 1, NULL);
done:
return result;
rq->sense = csdev->sense;
memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
rq->sense_len = csdev->senselen = 0;
err = blk_execute_rq(sdev->request_queue, NULL, rq, 1);
if (err == -EIO) {
if (rq->sense_len) {
err = trespass_endio(sdev, csdev->sense);
} else {
sdev_printk(KERN_INFO, sdev,
"%s: failed to send MODE SELECT: %x\n",
CLARIION_NAME, rq->errors);
}
}
blk_put_request(rq);
return err;
}
static int clariion_check_sense(struct scsi_device *sdev,
@ -386,99 +443,215 @@ static int clariion_check_sense(struct scsi_device *sdev,
break;
}
/* success just means we do not care what scsi-ml does */
return SUCCESS;
return SCSI_RETURN_NOT_HANDLED;
}
static const struct {
char *vendor;
char *model;
} clariion_dev_list[] = {
static int clariion_prep_fn(struct scsi_device *sdev, struct request *req)
{
struct clariion_dh_data *h = get_clariion_data(sdev);
int ret = BLKPREP_OK;
if (h->lun_state != CLARIION_LUN_OWNED) {
ret = BLKPREP_KILL;
req->cmd_flags |= REQ_QUIET;
}
return ret;
}
static int clariion_std_inquiry(struct scsi_device *sdev,
struct clariion_dh_data *csdev)
{
int err;
char *sp_model;
err = send_inquiry_cmd(sdev, 0, csdev);
if (err != SCSI_DH_OK && csdev->senselen) {
struct scsi_sense_hdr sshdr;
if (scsi_normalize_sense(csdev->sense, SCSI_SENSE_BUFFERSIZE,
&sshdr)) {
sdev_printk(KERN_ERR, sdev, "%s: INQUIRY sense code "
"%02x/%02x/%02x\n", CLARIION_NAME,
sshdr.sense_key, sshdr.asc, sshdr.ascq);
}
err = SCSI_DH_IO;
goto out;
}
sp_model = parse_sp_model(sdev, csdev->buffer);
if (!sp_model) {
err = SCSI_DH_DEV_UNSUPP;
goto out;
}
/*
* FC Series arrays do not support long trespass
*/
if (!strlen(sp_model) || !strncmp(sp_model, "FC",2))
csdev->flags |= CLARIION_SHORT_TRESPASS;
sdev_printk(KERN_INFO, sdev,
"%s: detected Clariion %s, flags %x\n",
CLARIION_NAME, sp_model, csdev->flags);
out:
return err;
}
static int clariion_send_inquiry(struct scsi_device *sdev,
struct clariion_dh_data *csdev)
{
int err, retry = CLARIION_RETRIES;
retry:
err = send_inquiry_cmd(sdev, 0xC0, csdev);
if (err != SCSI_DH_OK && csdev->senselen) {
struct scsi_sense_hdr sshdr;
err = scsi_normalize_sense(csdev->sense, SCSI_SENSE_BUFFERSIZE,
&sshdr);
if (!err)
return SCSI_DH_IO;
err = clariion_check_sense(sdev, &sshdr);
if (retry > 0 && err == NEEDS_RETRY) {
retry--;
goto retry;
}
sdev_printk(KERN_ERR, sdev, "%s: INQUIRY sense code "
"%02x/%02x/%02x\n", CLARIION_NAME,
sshdr.sense_key, sshdr.asc, sshdr.ascq);
err = SCSI_DH_IO;
} else {
err = parse_sp_info_reply(sdev, csdev);
}
return err;
}
static int clariion_activate(struct scsi_device *sdev)
{
struct clariion_dh_data *csdev = get_clariion_data(sdev);
int result;
result = clariion_send_inquiry(sdev, csdev);
if (result != SCSI_DH_OK)
goto done;
if (csdev->lun_state == CLARIION_LUN_OWNED)
goto done;
result = send_trespass_cmd(sdev, csdev);
if (result != SCSI_DH_OK)
goto done;
sdev_printk(KERN_INFO, sdev,"%s: %s trespass command sent\n",
CLARIION_NAME,
csdev->flags&CLARIION_SHORT_TRESPASS?"short":"long" );
/* Update status */
result = clariion_send_inquiry(sdev, csdev);
if (result != SCSI_DH_OK)
goto done;
done:
sdev_printk(KERN_INFO, sdev,
"%s: at SP %c Port %d (%s, default SP %c)\n",
CLARIION_NAME, csdev->current_sp + 'A',
csdev->port, lun_state[csdev->lun_state],
csdev->default_sp + 'A');
return result;
}
const struct scsi_dh_devlist clariion_dev_list[] = {
{"DGC", "RAID"},
{"DGC", "DISK"},
{"DGC", "VRAID"},
{NULL, NULL},
};
static int clariion_bus_notify(struct notifier_block *, unsigned long, void *);
static int clariion_bus_attach(struct scsi_device *sdev);
static void clariion_bus_detach(struct scsi_device *sdev);
static struct scsi_device_handler clariion_dh = {
.name = CLARIION_NAME,
.module = THIS_MODULE,
.nb.notifier_call = clariion_bus_notify,
.devlist = clariion_dev_list,
.attach = clariion_bus_attach,
.detach = clariion_bus_detach,
.check_sense = clariion_check_sense,
.activate = clariion_activate,
.prep_fn = clariion_prep_fn,
};
/*
* TODO: need some interface so we can set trespass values
*/
static int clariion_bus_notify(struct notifier_block *nb,
unsigned long action, void *data)
static int clariion_bus_attach(struct scsi_device *sdev)
{
struct device *dev = data;
struct scsi_device *sdev;
struct scsi_dh_data *scsi_dh_data;
struct clariion_dh_data *h;
int i, found = 0;
unsigned long flags;
int err;
if (!scsi_is_sdev_device(dev))
return 0;
sdev = to_scsi_device(dev);
if (action == BUS_NOTIFY_ADD_DEVICE) {
for (i = 0; clariion_dev_list[i].vendor; i++) {
if (!strncmp(sdev->vendor, clariion_dev_list[i].vendor,
strlen(clariion_dev_list[i].vendor)) &&
!strncmp(sdev->model, clariion_dev_list[i].model,
strlen(clariion_dev_list[i].model))) {
found = 1;
break;
}
}
if (!found)
goto out;
scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
+ sizeof(*h) , GFP_KERNEL);
if (!scsi_dh_data) {
sdev_printk(KERN_ERR, sdev, "Attach failed %s.\n",
CLARIION_NAME);
goto out;
}
scsi_dh_data->scsi_dh = &clariion_dh;
h = (struct clariion_dh_data *) scsi_dh_data->buf;
h->default_sp = CLARIION_UNBOUND_LU;
h->current_sp = CLARIION_UNBOUND_LU;
spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
sdev->scsi_dh_data = scsi_dh_data;
spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
sdev_printk(KERN_NOTICE, sdev, "Attached %s.\n", CLARIION_NAME);
try_module_get(THIS_MODULE);
} else if (action == BUS_NOTIFY_DEL_DEVICE) {
if (sdev->scsi_dh_data == NULL ||
sdev->scsi_dh_data->scsi_dh != &clariion_dh)
goto out;
spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
scsi_dh_data = sdev->scsi_dh_data;
sdev->scsi_dh_data = NULL;
spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
sdev_printk(KERN_NOTICE, sdev, "Dettached %s.\n",
scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
+ sizeof(*h) , GFP_KERNEL);
if (!scsi_dh_data) {
sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n",
CLARIION_NAME);
kfree(scsi_dh_data);
module_put(THIS_MODULE);
return -ENOMEM;
}
out:
scsi_dh_data->scsi_dh = &clariion_dh;
h = (struct clariion_dh_data *) scsi_dh_data->buf;
h->lun_state = CLARIION_LUN_UNINITIALIZED;
h->default_sp = CLARIION_UNBOUND_LU;
h->current_sp = CLARIION_UNBOUND_LU;
err = clariion_std_inquiry(sdev, h);
if (err != SCSI_DH_OK)
goto failed;
err = clariion_send_inquiry(sdev, h);
if (err != SCSI_DH_OK)
goto failed;
if (!try_module_get(THIS_MODULE))
goto failed;
spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
sdev->scsi_dh_data = scsi_dh_data;
spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
sdev_printk(KERN_INFO, sdev,
"%s: connected to SP %c Port %d (%s, default SP %c)\n",
CLARIION_NAME, h->current_sp + 'A',
h->port, lun_state[h->lun_state],
h->default_sp + 'A');
return 0;
failed:
kfree(scsi_dh_data);
sdev_printk(KERN_ERR, sdev, "%s: not attached\n",
CLARIION_NAME);
return -EINVAL;
}
static void clariion_bus_detach(struct scsi_device *sdev)
{
struct scsi_dh_data *scsi_dh_data;
unsigned long flags;
spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
scsi_dh_data = sdev->scsi_dh_data;
sdev->scsi_dh_data = NULL;
spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n",
CLARIION_NAME);
kfree(scsi_dh_data);
module_put(THIS_MODULE);
}
static int __init clariion_init(void)
@ -487,7 +660,8 @@ static int __init clariion_init(void)
r = scsi_register_device_handler(&clariion_dh);
if (r != 0)
printk(KERN_ERR "Failed to register scsi device handler.");
printk(KERN_ERR "%s: Failed to register scsi device handler.",
CLARIION_NAME);
return r;
}

View file

@ -4,6 +4,7 @@
*
* Copyright (C) 2006 Red Hat, Inc. All rights reserved.
* Copyright (C) 2006 Mike Christie
* Copyright (C) 2008 Hannes Reinecke <hare@suse.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -25,13 +26,18 @@
#include <scsi/scsi_eh.h>
#include <scsi/scsi_dh.h>
#define HP_SW_NAME "hp_sw"
#define HP_SW_NAME "hp_sw"
#define HP_SW_TIMEOUT (60 * HZ)
#define HP_SW_RETRIES 3
#define HP_SW_TIMEOUT (60 * HZ)
#define HP_SW_RETRIES 3
#define HP_SW_PATH_UNINITIALIZED -1
#define HP_SW_PATH_ACTIVE 0
#define HP_SW_PATH_PASSIVE 1
struct hp_sw_dh_data {
unsigned char sense[SCSI_SENSE_BUFFERSIZE];
int path_state;
int retries;
};
@ -42,51 +48,161 @@ static inline struct hp_sw_dh_data *get_hp_sw_data(struct scsi_device *sdev)
return ((struct hp_sw_dh_data *) scsi_dh_data->buf);
}
static int hp_sw_done(struct scsi_device *sdev)
/*
* tur_done - Handle TEST UNIT READY return status
* @sdev: sdev the command has been sent to
* @errors: blk error code
*
* Returns SCSI_DH_DEV_OFFLINED if the sdev is on the passive path
*/
static int tur_done(struct scsi_device *sdev, unsigned char *sense)
{
struct scsi_sense_hdr sshdr;
int ret;
ret = scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, &sshdr);
if (!ret) {
sdev_printk(KERN_WARNING, sdev,
"%s: sending tur failed, no sense available\n",
HP_SW_NAME);
ret = SCSI_DH_IO;
goto done;
}
switch (sshdr.sense_key) {
case UNIT_ATTENTION:
ret = SCSI_DH_IMM_RETRY;
break;
case NOT_READY:
if ((sshdr.asc == 0x04) && (sshdr.ascq == 2)) {
/*
* LUN not ready - Initialization command required
*
* This is the passive path
*/
ret = SCSI_DH_DEV_OFFLINED;
break;
}
/* Fallthrough */
default:
sdev_printk(KERN_WARNING, sdev,
"%s: sending tur failed, sense %x/%x/%x\n",
HP_SW_NAME, sshdr.sense_key, sshdr.asc,
sshdr.ascq);
break;
}
done:
return ret;
}
/*
* hp_sw_tur - Send TEST UNIT READY
* @sdev: sdev command should be sent to
*
* Use the TEST UNIT READY command to determine
* the path state.
*/
static int hp_sw_tur(struct scsi_device *sdev, struct hp_sw_dh_data *h)
{
struct request *req;
int ret;
req = blk_get_request(sdev->request_queue, WRITE, GFP_NOIO);
if (!req)
return SCSI_DH_RES_TEMP_UNAVAIL;
req->cmd_type = REQ_TYPE_BLOCK_PC;
req->cmd_flags |= REQ_FAILFAST;
req->cmd_len = COMMAND_SIZE(TEST_UNIT_READY);
memset(req->cmd, 0, MAX_COMMAND_SIZE);
req->cmd[0] = TEST_UNIT_READY;
req->timeout = HP_SW_TIMEOUT;
req->sense = h->sense;
memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE);
req->sense_len = 0;
retry:
ret = blk_execute_rq(req->q, NULL, req, 1);
if (ret == -EIO) {
if (req->sense_len > 0) {
ret = tur_done(sdev, h->sense);
} else {
sdev_printk(KERN_WARNING, sdev,
"%s: sending tur failed with %x\n",
HP_SW_NAME, req->errors);
ret = SCSI_DH_IO;
}
} else {
h->path_state = HP_SW_PATH_ACTIVE;
ret = SCSI_DH_OK;
}
if (ret == SCSI_DH_IMM_RETRY)
goto retry;
if (ret == SCSI_DH_DEV_OFFLINED) {
h->path_state = HP_SW_PATH_PASSIVE;
ret = SCSI_DH_OK;
}
blk_put_request(req);
return ret;
}
/*
* start_done - Handle START STOP UNIT return status
* @sdev: sdev the command has been sent to
* @errors: blk error code
*/
static int start_done(struct scsi_device *sdev, unsigned char *sense)
{
struct hp_sw_dh_data *h = get_hp_sw_data(sdev);
struct scsi_sense_hdr sshdr;
int rc;
sdev_printk(KERN_INFO, sdev, "hp_sw_done\n");
rc = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE, &sshdr);
if (!rc)
goto done;
rc = scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, &sshdr);
if (!rc) {
sdev_printk(KERN_WARNING, sdev,
"%s: sending start_stop_unit failed, "
"no sense available\n",
HP_SW_NAME);
return SCSI_DH_IO;
}
switch (sshdr.sense_key) {
case NOT_READY:
if ((sshdr.asc == 0x04) && (sshdr.ascq == 3)) {
/*
* LUN not ready - manual intervention required
*
* Switch-over in progress, retry.
*/
rc = SCSI_DH_RETRY;
h->retries++;
break;
}
/* fall through */
default:
h->retries++;
rc = SCSI_DH_IMM_RETRY;
}
done:
if (rc == SCSI_DH_OK || rc == SCSI_DH_IO)
h->retries = 0;
else if (h->retries > HP_SW_RETRIES) {
h->retries = 0;
sdev_printk(KERN_WARNING, sdev,
"%s: sending start_stop_unit failed, sense %x/%x/%x\n",
HP_SW_NAME, sshdr.sense_key, sshdr.asc,
sshdr.ascq);
rc = SCSI_DH_IO;
}
return rc;
}
static int hp_sw_activate(struct scsi_device *sdev)
/*
* hp_sw_start_stop - Send START STOP UNIT command
* @sdev: sdev command should be sent to
*
* Sending START STOP UNIT activates the SP.
*/
static int hp_sw_start_stop(struct scsi_device *sdev, struct hp_sw_dh_data *h)
{
struct hp_sw_dh_data *h = get_hp_sw_data(sdev);
struct request *req;
int ret = SCSI_DH_RES_TEMP_UNAVAIL;
int ret, retry;
req = blk_get_request(sdev->request_queue, WRITE, GFP_ATOMIC);
req = blk_get_request(sdev->request_queue, WRITE, GFP_NOIO);
if (!req)
goto done;
sdev_printk(KERN_INFO, sdev, "sending START_STOP.");
return SCSI_DH_RES_TEMP_UNAVAIL;
req->cmd_type = REQ_TYPE_BLOCK_PC;
req->cmd_flags |= REQ_FAILFAST;
@ -98,95 +214,153 @@ static int hp_sw_activate(struct scsi_device *sdev)
req->sense = h->sense;
memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE);
req->sense_len = 0;
retry = h->retries;
retry:
ret = blk_execute_rq(req->q, NULL, req, 1);
if (!ret) /* SUCCESS */
ret = hp_sw_done(sdev);
else
if (ret == -EIO) {
if (req->sense_len > 0) {
ret = start_done(sdev, h->sense);
} else {
sdev_printk(KERN_WARNING, sdev,
"%s: sending start_stop_unit failed with %x\n",
HP_SW_NAME, req->errors);
ret = SCSI_DH_IO;
}
} else
ret = SCSI_DH_OK;
if (ret == SCSI_DH_RETRY) {
if (--retry)
goto retry;
ret = SCSI_DH_IO;
done:
}
blk_put_request(req);
return ret;
}
static const struct {
char *vendor;
char *model;
} hp_sw_dh_data_list[] = {
{"COMPAQ", "MSA"},
{"HP", "HSV"},
static int hp_sw_prep_fn(struct scsi_device *sdev, struct request *req)
{
struct hp_sw_dh_data *h = get_hp_sw_data(sdev);
int ret = BLKPREP_OK;
if (h->path_state != HP_SW_PATH_ACTIVE) {
ret = BLKPREP_KILL;
req->cmd_flags |= REQ_QUIET;
}
return ret;
}
/*
* hp_sw_activate - Activate a path
* @sdev: sdev on the path to be activated
*
* The HP Active/Passive firmware is pretty simple;
* the passive path reports NOT READY with sense codes
* 0x04/0x02; a START STOP UNIT command will then
* activate the passive path (and deactivate the
* previously active one).
*/
static int hp_sw_activate(struct scsi_device *sdev)
{
int ret = SCSI_DH_OK;
struct hp_sw_dh_data *h = get_hp_sw_data(sdev);
ret = hp_sw_tur(sdev, h);
if (ret == SCSI_DH_OK && h->path_state == HP_SW_PATH_PASSIVE) {
ret = hp_sw_start_stop(sdev, h);
if (ret == SCSI_DH_OK)
sdev_printk(KERN_INFO, sdev,
"%s: activated path\n",
HP_SW_NAME);
}
return ret;
}
const struct scsi_dh_devlist hp_sw_dh_data_list[] = {
{"COMPAQ", "MSA1000 VOLUME"},
{"COMPAQ", "HSV110"},
{"HP", "HSV100"},
{"DEC", "HSG80"},
{NULL, NULL},
};
static int hp_sw_bus_notify(struct notifier_block *, unsigned long, void *);
static int hp_sw_bus_attach(struct scsi_device *sdev);
static void hp_sw_bus_detach(struct scsi_device *sdev);
static struct scsi_device_handler hp_sw_dh = {
.name = HP_SW_NAME,
.module = THIS_MODULE,
.nb.notifier_call = hp_sw_bus_notify,
.devlist = hp_sw_dh_data_list,
.attach = hp_sw_bus_attach,
.detach = hp_sw_bus_detach,
.activate = hp_sw_activate,
.prep_fn = hp_sw_prep_fn,
};
static int hp_sw_bus_notify(struct notifier_block *nb,
unsigned long action, void *data)
static int hp_sw_bus_attach(struct scsi_device *sdev)
{
struct device *dev = data;
struct scsi_device *sdev;
struct scsi_dh_data *scsi_dh_data;
int i, found = 0;
struct hp_sw_dh_data *h;
unsigned long flags;
int ret;
if (!scsi_is_sdev_device(dev))
scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
+ sizeof(struct hp_sw_dh_data) , GFP_KERNEL);
if (!scsi_dh_data) {
sdev_printk(KERN_ERR, sdev, "%s: Attach Failed\n",
HP_SW_NAME);
return 0;
sdev = to_scsi_device(dev);
if (action == BUS_NOTIFY_ADD_DEVICE) {
for (i = 0; hp_sw_dh_data_list[i].vendor; i++) {
if (!strncmp(sdev->vendor, hp_sw_dh_data_list[i].vendor,
strlen(hp_sw_dh_data_list[i].vendor)) &&
!strncmp(sdev->model, hp_sw_dh_data_list[i].model,
strlen(hp_sw_dh_data_list[i].model))) {
found = 1;
break;
}
}
if (!found)
goto out;
scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
+ sizeof(struct hp_sw_dh_data) , GFP_KERNEL);
if (!scsi_dh_data) {
sdev_printk(KERN_ERR, sdev, "Attach Failed %s.\n",
HP_SW_NAME);
goto out;
}
scsi_dh_data->scsi_dh = &hp_sw_dh;
spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
sdev->scsi_dh_data = scsi_dh_data;
spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
try_module_get(THIS_MODULE);
sdev_printk(KERN_NOTICE, sdev, "Attached %s.\n", HP_SW_NAME);
} else if (action == BUS_NOTIFY_DEL_DEVICE) {
if (sdev->scsi_dh_data == NULL ||
sdev->scsi_dh_data->scsi_dh != &hp_sw_dh)
goto out;
spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
scsi_dh_data = sdev->scsi_dh_data;
sdev->scsi_dh_data = NULL;
spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
module_put(THIS_MODULE);
sdev_printk(KERN_NOTICE, sdev, "Dettached %s.\n", HP_SW_NAME);
kfree(scsi_dh_data);
}
out:
scsi_dh_data->scsi_dh = &hp_sw_dh;
h = (struct hp_sw_dh_data *) scsi_dh_data->buf;
h->path_state = HP_SW_PATH_UNINITIALIZED;
h->retries = HP_SW_RETRIES;
ret = hp_sw_tur(sdev, h);
if (ret != SCSI_DH_OK || h->path_state == HP_SW_PATH_UNINITIALIZED)
goto failed;
if (!try_module_get(THIS_MODULE))
goto failed;
spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
sdev->scsi_dh_data = scsi_dh_data;
spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
sdev_printk(KERN_INFO, sdev, "%s: attached to %s path\n",
HP_SW_NAME, h->path_state == HP_SW_PATH_ACTIVE?
"active":"passive");
return 0;
failed:
kfree(scsi_dh_data);
sdev_printk(KERN_ERR, sdev, "%s: not attached\n",
HP_SW_NAME);
return -EINVAL;
}
static void hp_sw_bus_detach( struct scsi_device *sdev )
{
struct scsi_dh_data *scsi_dh_data;
unsigned long flags;
spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
scsi_dh_data = sdev->scsi_dh_data;
sdev->scsi_dh_data = NULL;
spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
module_put(THIS_MODULE);
sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", HP_SW_NAME);
kfree(scsi_dh_data);
}
static int __init hp_sw_init(void)
@ -202,6 +376,6 @@ static void __exit hp_sw_exit(void)
module_init(hp_sw_init);
module_exit(hp_sw_exit);
MODULE_DESCRIPTION("HP MSA 1000");
MODULE_DESCRIPTION("HP Active/Passive driver");
MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu");
MODULE_LICENSE("GPL");

View file

@ -173,6 +173,11 @@ struct rdac_dh_data {
#define RDAC_STATE_ACTIVE 0
#define RDAC_STATE_PASSIVE 1
unsigned char state;
#define RDAC_LUN_UNOWNED 0
#define RDAC_LUN_OWNED 1
#define RDAC_LUN_AVT 2
char lun_state;
unsigned char sense[SCSI_SENSE_BUFFERSIZE];
union {
struct c2_inquiry c2;
@ -182,6 +187,13 @@ struct rdac_dh_data {
} inq;
};
static const char *lun_state[] =
{
"unowned",
"owned",
"owned (AVT mode)",
};
static LIST_HEAD(ctlr_list);
static DEFINE_SPINLOCK(list_lock);
@ -197,9 +209,8 @@ static struct request *get_rdac_req(struct scsi_device *sdev,
{
struct request *rq;
struct request_queue *q = sdev->request_queue;
struct rdac_dh_data *h = get_rdac_data(sdev);
rq = blk_get_request(q, rw, GFP_KERNEL);
rq = blk_get_request(q, rw, GFP_NOIO);
if (!rq) {
sdev_printk(KERN_INFO, sdev,
@ -207,17 +218,14 @@ static struct request *get_rdac_req(struct scsi_device *sdev,
return NULL;
}
if (buflen && blk_rq_map_kern(q, rq, buffer, buflen, GFP_KERNEL)) {
if (buflen && blk_rq_map_kern(q, rq, buffer, buflen, GFP_NOIO)) {
blk_put_request(rq);
sdev_printk(KERN_INFO, sdev,
"get_rdac_req: blk_rq_map_kern failed.\n");
return NULL;
}
memset(&rq->cmd, 0, BLK_MAX_CDB);
rq->sense = h->sense;
memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
rq->sense_len = 0;
memset(rq->cmd, 0, BLK_MAX_CDB);
rq->cmd_type = REQ_TYPE_BLOCK_PC;
rq->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE;
@ -227,12 +235,12 @@ static struct request *get_rdac_req(struct scsi_device *sdev,
return rq;
}
static struct request *rdac_failover_get(struct scsi_device *sdev)
static struct request *rdac_failover_get(struct scsi_device *sdev,
struct rdac_dh_data *h)
{
struct request *rq;
struct rdac_mode_common *common;
unsigned data_size;
struct rdac_dh_data *h = get_rdac_data(sdev);
if (h->ctlr->use_ms10) {
struct rdac_pg_expanded *rdac_pg;
@ -277,6 +285,10 @@ static struct request *rdac_failover_get(struct scsi_device *sdev)
}
rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);
rq->sense = h->sense;
memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
rq->sense_len = 0;
return rq;
}
@ -321,11 +333,10 @@ done:
}
static int submit_inquiry(struct scsi_device *sdev, int page_code,
unsigned int len)
unsigned int len, struct rdac_dh_data *h)
{
struct request *rq;
struct request_queue *q = sdev->request_queue;
struct rdac_dh_data *h = get_rdac_data(sdev);
int err = SCSI_DH_RES_TEMP_UNAVAIL;
rq = get_rdac_req(sdev, &h->inq, len, READ);
@ -338,59 +349,68 @@ static int submit_inquiry(struct scsi_device *sdev, int page_code,
rq->cmd[2] = page_code;
rq->cmd[4] = len;
rq->cmd_len = COMMAND_SIZE(INQUIRY);
rq->sense = h->sense;
memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
rq->sense_len = 0;
err = blk_execute_rq(q, NULL, rq, 1);
if (err == -EIO)
err = SCSI_DH_IO;
blk_put_request(rq);
done:
return err;
}
static int get_lun(struct scsi_device *sdev)
static int get_lun(struct scsi_device *sdev, struct rdac_dh_data *h)
{
int err;
struct c8_inquiry *inqp;
struct rdac_dh_data *h = get_rdac_data(sdev);
err = submit_inquiry(sdev, 0xC8, sizeof(struct c8_inquiry));
err = submit_inquiry(sdev, 0xC8, sizeof(struct c8_inquiry), h);
if (err == SCSI_DH_OK) {
inqp = &h->inq.c8;
h->lun = inqp->lun[7]; /* currently it uses only one byte */
if (inqp->page_code != 0xc8)
return SCSI_DH_NOSYS;
if (inqp->page_id[0] != 'e' || inqp->page_id[1] != 'd' ||
inqp->page_id[2] != 'i' || inqp->page_id[3] != 'd')
return SCSI_DH_NOSYS;
h->lun = scsilun_to_int((struct scsi_lun *)inqp->lun);
}
return err;
}
#define RDAC_OWNED 0
#define RDAC_UNOWNED 1
#define RDAC_FAILED 2
static int check_ownership(struct scsi_device *sdev)
static int check_ownership(struct scsi_device *sdev, struct rdac_dh_data *h)
{
int err;
struct c9_inquiry *inqp;
struct rdac_dh_data *h = get_rdac_data(sdev);
err = submit_inquiry(sdev, 0xC9, sizeof(struct c9_inquiry));
err = submit_inquiry(sdev, 0xC9, sizeof(struct c9_inquiry), h);
if (err == SCSI_DH_OK) {
err = RDAC_UNOWNED;
inqp = &h->inq.c9;
/*
* If in AVT mode or if the path already owns the LUN,
* return RDAC_OWNED;
*/
if (((inqp->avte_cvp >> 7) == 0x1) ||
((inqp->avte_cvp & 0x1) != 0))
err = RDAC_OWNED;
} else
err = RDAC_FAILED;
if ((inqp->avte_cvp >> 7) == 0x1) {
/* LUN in AVT mode */
sdev_printk(KERN_NOTICE, sdev,
"%s: AVT mode detected\n",
RDAC_NAME);
h->lun_state = RDAC_LUN_AVT;
} else if ((inqp->avte_cvp & 0x1) != 0) {
/* LUN was owned by the controller */
h->lun_state = RDAC_LUN_OWNED;
}
}
return err;
}
static int initialize_controller(struct scsi_device *sdev)
static int initialize_controller(struct scsi_device *sdev,
struct rdac_dh_data *h)
{
int err;
struct c4_inquiry *inqp;
struct rdac_dh_data *h = get_rdac_data(sdev);
err = submit_inquiry(sdev, 0xC4, sizeof(struct c4_inquiry));
err = submit_inquiry(sdev, 0xC4, sizeof(struct c4_inquiry), h);
if (err == SCSI_DH_OK) {
inqp = &h->inq.c4;
h->ctlr = get_controller(inqp->subsys_id, inqp->slot_id);
@ -400,13 +420,12 @@ static int initialize_controller(struct scsi_device *sdev)
return err;
}
static int set_mode_select(struct scsi_device *sdev)
static int set_mode_select(struct scsi_device *sdev, struct rdac_dh_data *h)
{
int err;
struct c2_inquiry *inqp;
struct rdac_dh_data *h = get_rdac_data(sdev);
err = submit_inquiry(sdev, 0xC2, sizeof(struct c2_inquiry));
err = submit_inquiry(sdev, 0xC2, sizeof(struct c2_inquiry), h);
if (err == SCSI_DH_OK) {
inqp = &h->inq.c2;
/*
@ -421,13 +440,13 @@ static int set_mode_select(struct scsi_device *sdev)
return err;
}
static int mode_select_handle_sense(struct scsi_device *sdev)
static int mode_select_handle_sense(struct scsi_device *sdev,
unsigned char *sensebuf)
{
struct scsi_sense_hdr sense_hdr;
struct rdac_dh_data *h = get_rdac_data(sdev);
int sense, err = SCSI_DH_IO, ret;
ret = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE, &sense_hdr);
ret = scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE, &sense_hdr);
if (!ret)
goto done;
@ -451,14 +470,13 @@ done:
return err;
}
static int send_mode_select(struct scsi_device *sdev)
static int send_mode_select(struct scsi_device *sdev, struct rdac_dh_data *h)
{
struct request *rq;
struct request_queue *q = sdev->request_queue;
struct rdac_dh_data *h = get_rdac_data(sdev);
int err = SCSI_DH_RES_TEMP_UNAVAIL;
rq = rdac_failover_get(sdev);
rq = rdac_failover_get(sdev, h);
if (!rq)
goto done;
@ -466,9 +484,11 @@ static int send_mode_select(struct scsi_device *sdev)
err = blk_execute_rq(q, NULL, rq, 1);
if (err != SCSI_DH_OK)
err = mode_select_handle_sense(sdev);
err = mode_select_handle_sense(sdev, h->sense);
if (err == SCSI_DH_OK)
h->state = RDAC_STATE_ACTIVE;
blk_put_request(rq);
done:
return err;
}
@ -478,38 +498,23 @@ static int rdac_activate(struct scsi_device *sdev)
struct rdac_dh_data *h = get_rdac_data(sdev);
int err = SCSI_DH_OK;
if (h->lun == UNINITIALIZED_LUN) {
err = get_lun(sdev);
if (err != SCSI_DH_OK)
goto done;
}
err = check_ownership(sdev);
switch (err) {
case RDAC_UNOWNED:
break;
case RDAC_OWNED:
err = SCSI_DH_OK;
err = check_ownership(sdev, h);
if (err != SCSI_DH_OK)
goto done;
case RDAC_FAILED:
default:
err = SCSI_DH_IO;
goto done;
}
if (!h->ctlr) {
err = initialize_controller(sdev);
err = initialize_controller(sdev, h);
if (err != SCSI_DH_OK)
goto done;
}
if (h->ctlr->use_ms10 == -1) {
err = set_mode_select(sdev);
err = set_mode_select(sdev, h);
if (err != SCSI_DH_OK)
goto done;
}
err = send_mode_select(sdev);
if (h->lun_state == RDAC_LUN_UNOWNED)
err = send_mode_select(sdev, h);
done:
return err;
}
@ -569,10 +574,7 @@ static int rdac_check_sense(struct scsi_device *sdev,
return SCSI_RETURN_NOT_HANDLED;
}
static const struct {
char *vendor;
char *model;
} rdac_dev_list[] = {
const struct scsi_dh_devlist rdac_dev_list[] = {
{"IBM", "1722"},
{"IBM", "1724"},
{"IBM", "1726"},
@ -590,89 +592,89 @@ static const struct {
{NULL, NULL},
};
static int rdac_bus_notify(struct notifier_block *, unsigned long, void *);
static int rdac_bus_attach(struct scsi_device *sdev);
static void rdac_bus_detach(struct scsi_device *sdev);
static struct scsi_device_handler rdac_dh = {
.name = RDAC_NAME,
.module = THIS_MODULE,
.nb.notifier_call = rdac_bus_notify,
.devlist = rdac_dev_list,
.prep_fn = rdac_prep_fn,
.check_sense = rdac_check_sense,
.attach = rdac_bus_attach,
.detach = rdac_bus_detach,
.activate = rdac_activate,
};
/*
* TODO: need some interface so we can set trespass values
*/
static int rdac_bus_notify(struct notifier_block *nb,
unsigned long action, void *data)
static int rdac_bus_attach(struct scsi_device *sdev)
{
struct device *dev = data;
struct scsi_device *sdev;
struct scsi_dh_data *scsi_dh_data;
struct rdac_dh_data *h;
int i, found = 0;
unsigned long flags;
int err;
if (!scsi_is_sdev_device(dev))
scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
+ sizeof(*h) , GFP_KERNEL);
if (!scsi_dh_data) {
sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n",
RDAC_NAME);
return 0;
sdev = to_scsi_device(dev);
if (action == BUS_NOTIFY_ADD_DEVICE) {
for (i = 0; rdac_dev_list[i].vendor; i++) {
if (!strncmp(sdev->vendor, rdac_dev_list[i].vendor,
strlen(rdac_dev_list[i].vendor)) &&
!strncmp(sdev->model, rdac_dev_list[i].model,
strlen(rdac_dev_list[i].model))) {
found = 1;
break;
}
}
if (!found)
goto out;
scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
+ sizeof(*h) , GFP_KERNEL);
if (!scsi_dh_data) {
sdev_printk(KERN_ERR, sdev, "Attach failed %s.\n",
RDAC_NAME);
goto out;
}
scsi_dh_data->scsi_dh = &rdac_dh;
h = (struct rdac_dh_data *) scsi_dh_data->buf;
h->lun = UNINITIALIZED_LUN;
h->state = RDAC_STATE_ACTIVE;
spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
sdev->scsi_dh_data = scsi_dh_data;
spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
try_module_get(THIS_MODULE);
sdev_printk(KERN_NOTICE, sdev, "Attached %s.\n", RDAC_NAME);
} else if (action == BUS_NOTIFY_DEL_DEVICE) {
if (sdev->scsi_dh_data == NULL ||
sdev->scsi_dh_data->scsi_dh != &rdac_dh)
goto out;
spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
scsi_dh_data = sdev->scsi_dh_data;
sdev->scsi_dh_data = NULL;
spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
h = (struct rdac_dh_data *) scsi_dh_data->buf;
if (h->ctlr)
kref_put(&h->ctlr->kref, release_controller);
kfree(scsi_dh_data);
module_put(THIS_MODULE);
sdev_printk(KERN_NOTICE, sdev, "Dettached %s.\n", RDAC_NAME);
}
out:
scsi_dh_data->scsi_dh = &rdac_dh;
h = (struct rdac_dh_data *) scsi_dh_data->buf;
h->lun = UNINITIALIZED_LUN;
h->state = RDAC_STATE_ACTIVE;
err = get_lun(sdev, h);
if (err != SCSI_DH_OK)
goto failed;
err = check_ownership(sdev, h);
if (err != SCSI_DH_OK)
goto failed;
if (!try_module_get(THIS_MODULE))
goto failed;
spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
sdev->scsi_dh_data = scsi_dh_data;
spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
sdev_printk(KERN_NOTICE, sdev,
"%s: LUN %d (%s)\n",
RDAC_NAME, h->lun, lun_state[(int)h->lun_state]);
return 0;
failed:
kfree(scsi_dh_data);
sdev_printk(KERN_ERR, sdev, "%s: not attached\n",
RDAC_NAME);
return -EINVAL;
}
static void rdac_bus_detach( struct scsi_device *sdev )
{
struct scsi_dh_data *scsi_dh_data;
struct rdac_dh_data *h;
unsigned long flags;
spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
scsi_dh_data = sdev->scsi_dh_data;
sdev->scsi_dh_data = NULL;
spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
h = (struct rdac_dh_data *) scsi_dh_data->buf;
if (h->ctlr)
kref_put(&h->ctlr->kref, release_controller);
kfree(scsi_dh_data);
module_put(THIS_MODULE);
sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", RDAC_NAME);
}
static int __init rdac_init(void)
{
int r;

View file

@ -521,9 +521,10 @@ static void ibmvfc_set_host_action(struct ibmvfc_host *vhost,
static void ibmvfc_reinit_host(struct ibmvfc_host *vhost)
{
if (vhost->action == IBMVFC_HOST_ACTION_NONE) {
scsi_block_requests(vhost->host);
ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING);
ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY);
if (!ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING)) {
scsi_block_requests(vhost->host);
ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY);
}
} else
vhost->reinit = 1;
@ -854,39 +855,41 @@ static void ibmvfc_retry_host_init(struct ibmvfc_host *vhost)
}
/**
* __ibmvfc_find_target - Find the specified scsi_target (no locking)
* __ibmvfc_get_target - Find the specified scsi_target (no locking)
* @starget: scsi target struct
*
* Return value:
* ibmvfc_target struct / NULL if not found
**/
static struct ibmvfc_target *__ibmvfc_find_target(struct scsi_target *starget)
static struct ibmvfc_target *__ibmvfc_get_target(struct scsi_target *starget)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct ibmvfc_host *vhost = shost_priv(shost);
struct ibmvfc_target *tgt;
list_for_each_entry(tgt, &vhost->targets, queue)
if (tgt->target_id == starget->id)
if (tgt->target_id == starget->id) {
kref_get(&tgt->kref);
return tgt;
}
return NULL;
}
/**
* ibmvfc_find_target - Find the specified scsi_target
* ibmvfc_get_target - Find the specified scsi_target
* @starget: scsi target struct
*
* Return value:
* ibmvfc_target struct / NULL if not found
**/
static struct ibmvfc_target *ibmvfc_find_target(struct scsi_target *starget)
static struct ibmvfc_target *ibmvfc_get_target(struct scsi_target *starget)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct ibmvfc_target *tgt;
unsigned long flags;
spin_lock_irqsave(shost->host_lock, flags);
tgt = __ibmvfc_find_target(starget);
tgt = __ibmvfc_get_target(starget);
spin_unlock_irqrestore(shost->host_lock, flags);
return tgt;
}
@ -963,6 +966,9 @@ static void ibmvfc_get_host_port_state(struct Scsi_Host *shost)
case IBMVFC_HALTED:
fc_host_port_state(shost) = FC_PORTSTATE_BLOCKED;
break;
case IBMVFC_NO_CRQ:
fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
break;
default:
ibmvfc_log(vhost, 3, "Unknown port state: %d\n", vhost->state);
fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
@ -987,6 +993,17 @@ static void ibmvfc_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout)
rport->dev_loss_tmo = 1;
}
/**
* ibmvfc_release_tgt - Free memory allocated for a target
* @kref: kref struct
*
**/
static void ibmvfc_release_tgt(struct kref *kref)
{
struct ibmvfc_target *tgt = container_of(kref, struct ibmvfc_target, kref);
kfree(tgt);
}
/**
* ibmvfc_get_starget_node_name - Get SCSI target's node name
* @starget: scsi target struct
@ -996,8 +1013,10 @@ static void ibmvfc_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout)
**/
static void ibmvfc_get_starget_node_name(struct scsi_target *starget)
{
struct ibmvfc_target *tgt = ibmvfc_find_target(starget);
struct ibmvfc_target *tgt = ibmvfc_get_target(starget);
fc_starget_port_name(starget) = tgt ? tgt->ids.node_name : 0;
if (tgt)
kref_put(&tgt->kref, ibmvfc_release_tgt);
}
/**
@ -1009,8 +1028,10 @@ static void ibmvfc_get_starget_node_name(struct scsi_target *starget)
**/
static void ibmvfc_get_starget_port_name(struct scsi_target *starget)
{
struct ibmvfc_target *tgt = ibmvfc_find_target(starget);
struct ibmvfc_target *tgt = ibmvfc_get_target(starget);
fc_starget_port_name(starget) = tgt ? tgt->ids.port_name : 0;
if (tgt)
kref_put(&tgt->kref, ibmvfc_release_tgt);
}
/**
@ -1022,8 +1043,10 @@ static void ibmvfc_get_starget_port_name(struct scsi_target *starget)
**/
static void ibmvfc_get_starget_port_id(struct scsi_target *starget)
{
struct ibmvfc_target *tgt = ibmvfc_find_target(starget);
struct ibmvfc_target *tgt = ibmvfc_get_target(starget);
fc_starget_port_id(starget) = tgt ? tgt->scsi_id : -1;
if (tgt)
kref_put(&tgt->kref, ibmvfc_release_tgt);
}
/**
@ -1113,7 +1136,7 @@ static void ibmvfc_set_login_info(struct ibmvfc_host *vhost)
login_info->max_cmds = max_requests + IBMVFC_NUM_INTERNAL_REQ;
login_info->capabilities = IBMVFC_CAN_MIGRATE;
login_info->async.va = vhost->async_crq.msg_token;
login_info->async.len = vhost->async_crq.size;
login_info->async.len = vhost->async_crq.size * sizeof(*vhost->async_crq.msgs);
strncpy(login_info->partition_name, vhost->partition_name, IBMVFC_MAX_NAME);
strncpy(login_info->device_name,
vhost->host->shost_gendev.bus_id, IBMVFC_MAX_NAME);
@ -1404,7 +1427,7 @@ static void ibmvfc_log_error(struct ibmvfc_event *evt)
err = cmd_status[index].name;
}
if (!logerr && (vhost->log_level <= IBMVFC_DEFAULT_LOG_LEVEL))
if (!logerr && (vhost->log_level <= (IBMVFC_DEFAULT_LOG_LEVEL + 1)))
return;
if (rsp->flags & FCP_RSP_LEN_VALID)
@ -2054,7 +2077,7 @@ static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq,
{
const char *desc = ibmvfc_get_ae_desc(crq->event);
ibmvfc_log(vhost, 2, "%s event received\n", desc);
ibmvfc_log(vhost, 3, "%s event received\n", desc);
switch (crq->event) {
case IBMVFC_AE_LINK_UP:
@ -2647,17 +2670,6 @@ static void ibmvfc_retry_tgt_init(struct ibmvfc_target *tgt,
ibmvfc_init_tgt(tgt, job_step);
}
/**
* ibmvfc_release_tgt - Free memory allocated for a target
* @kref: kref struct
*
**/
static void ibmvfc_release_tgt(struct kref *kref)
{
struct ibmvfc_target *tgt = container_of(kref, struct ibmvfc_target, kref);
kfree(tgt);
}
/**
* ibmvfc_tgt_prli_done - Completion handler for Process Login
* @evt: ibmvfc event struct
@ -2901,6 +2913,139 @@ static void ibmvfc_tgt_implicit_logout(struct ibmvfc_target *tgt)
tgt_dbg(tgt, "Sent Implicit Logout\n");
}
/**
* ibmvfc_adisc_needs_plogi - Does device need PLOGI?
* @mad: ibmvfc passthru mad struct
* @tgt: ibmvfc target struct
*
* Returns:
* 1 if PLOGI needed / 0 if PLOGI not needed
**/
static int ibmvfc_adisc_needs_plogi(struct ibmvfc_passthru_mad *mad,
struct ibmvfc_target *tgt)
{
if (memcmp(&mad->fc_iu.response[2], &tgt->ids.port_name,
sizeof(tgt->ids.port_name)))
return 1;
if (memcmp(&mad->fc_iu.response[4], &tgt->ids.node_name,
sizeof(tgt->ids.node_name)))
return 1;
if (mad->fc_iu.response[6] != tgt->scsi_id)
return 1;
return 0;
}
/**
* ibmvfc_tgt_adisc_done - Completion handler for ADISC
* @evt: ibmvfc event struct
*
**/
static void ibmvfc_tgt_adisc_done(struct ibmvfc_event *evt)
{
struct ibmvfc_target *tgt = evt->tgt;
struct ibmvfc_host *vhost = evt->vhost;
struct ibmvfc_passthru_mad *mad = &evt->xfer_iu->passthru;
u32 status = mad->common.status;
u8 fc_reason, fc_explain;
vhost->discovery_threads--;
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
switch (status) {
case IBMVFC_MAD_SUCCESS:
tgt_dbg(tgt, "ADISC succeeded\n");
if (ibmvfc_adisc_needs_plogi(mad, tgt))
tgt->need_login = 1;
break;
case IBMVFC_MAD_DRIVER_FAILED:
break;
case IBMVFC_MAD_FAILED:
default:
tgt->need_login = 1;
fc_reason = (mad->fc_iu.response[1] & 0x00ff0000) >> 16;
fc_explain = (mad->fc_iu.response[1] & 0x0000ff00) >> 8;
tgt_info(tgt, "ADISC failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n",
ibmvfc_get_cmd_error(mad->iu.status, mad->iu.error),
mad->iu.status, mad->iu.error,
ibmvfc_get_fc_type(fc_reason), fc_reason,
ibmvfc_get_ls_explain(fc_explain), fc_explain, status);
break;
};
kref_put(&tgt->kref, ibmvfc_release_tgt);
ibmvfc_free_event(evt);
wake_up(&vhost->work_wait_q);
}
/**
* ibmvfc_init_passthru - Initialize an event struct for FC passthru
* @evt: ibmvfc event struct
*
**/
static void ibmvfc_init_passthru(struct ibmvfc_event *evt)
{
struct ibmvfc_passthru_mad *mad = &evt->iu.passthru;
memset(mad, 0, sizeof(*mad));
mad->common.version = 1;
mad->common.opcode = IBMVFC_PASSTHRU;
mad->common.length = sizeof(*mad) - sizeof(mad->fc_iu) - sizeof(mad->iu);
mad->cmd_ioba.va = (u64)evt->crq.ioba +
offsetof(struct ibmvfc_passthru_mad, iu);
mad->cmd_ioba.len = sizeof(mad->iu);
mad->iu.cmd_len = sizeof(mad->fc_iu.payload);
mad->iu.rsp_len = sizeof(mad->fc_iu.response);
mad->iu.cmd.va = (u64)evt->crq.ioba +
offsetof(struct ibmvfc_passthru_mad, fc_iu) +
offsetof(struct ibmvfc_passthru_fc_iu, payload);
mad->iu.cmd.len = sizeof(mad->fc_iu.payload);
mad->iu.rsp.va = (u64)evt->crq.ioba +
offsetof(struct ibmvfc_passthru_mad, fc_iu) +
offsetof(struct ibmvfc_passthru_fc_iu, response);
mad->iu.rsp.len = sizeof(mad->fc_iu.response);
}
/**
* ibmvfc_tgt_adisc - Initiate an ADISC for specified target
* @tgt: ibmvfc target struct
*
**/
static void ibmvfc_tgt_adisc(struct ibmvfc_target *tgt)
{
struct ibmvfc_passthru_mad *mad;
struct ibmvfc_host *vhost = tgt->vhost;
struct ibmvfc_event *evt;
if (vhost->discovery_threads >= disc_threads)
return;
kref_get(&tgt->kref);
evt = ibmvfc_get_event(vhost);
vhost->discovery_threads++;
ibmvfc_init_event(evt, ibmvfc_tgt_adisc_done, IBMVFC_MAD_FORMAT);
evt->tgt = tgt;
ibmvfc_init_passthru(evt);
mad = &evt->iu.passthru;
mad->iu.flags = IBMVFC_FC_ELS;
mad->iu.scsi_id = tgt->scsi_id;
mad->fc_iu.payload[0] = IBMVFC_ADISC;
memcpy(&mad->fc_iu.payload[2], &vhost->login_buf->resp.port_name,
sizeof(vhost->login_buf->resp.port_name));
memcpy(&mad->fc_iu.payload[4], &vhost->login_buf->resp.node_name,
sizeof(vhost->login_buf->resp.node_name));
mad->fc_iu.payload[6] = vhost->login_buf->resp.scsi_id & 0x00ffffff;
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT);
if (ibmvfc_send_event(evt, vhost, default_timeout)) {
vhost->discovery_threads--;
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
kref_put(&tgt->kref, ibmvfc_release_tgt);
} else
tgt_dbg(tgt, "Sent ADISC\n");
}
/**
* ibmvfc_tgt_query_target_done - Completion handler for Query Target MAD
* @evt: ibmvfc event struct
@ -2921,6 +3066,8 @@ static void ibmvfc_tgt_query_target_done(struct ibmvfc_event *evt)
tgt->new_scsi_id = rsp->scsi_id;
if (rsp->scsi_id != tgt->scsi_id)
ibmvfc_init_tgt(tgt, ibmvfc_tgt_implicit_logout);
else
ibmvfc_init_tgt(tgt, ibmvfc_tgt_adisc);
break;
case IBMVFC_MAD_DRIVER_FAILED:
break;
@ -3336,6 +3483,7 @@ static void ibmvfc_tgt_add_rport(struct ibmvfc_target *tgt)
tgt_dbg(tgt, "rport add succeeded\n");
rport->maxframe_size = tgt->service_parms.common.bb_rcv_sz & 0x0fff;
rport->supported_classes = 0;
tgt->target_id = rport->scsi_target_id;
if (tgt->service_parms.class1_parms[0] & 0x80000000)
rport->supported_classes |= FC_COS_CLASS1;
if (tgt->service_parms.class2_parms[0] & 0x80000000)
@ -3800,10 +3948,12 @@ static int ibmvfc_remove(struct vio_dev *vdev)
ENTER;
ibmvfc_remove_trace_file(&vhost->host->shost_dev.kobj, &ibmvfc_trace_attr);
ibmvfc_link_down(vhost, IBMVFC_HOST_OFFLINE);
ibmvfc_wait_while_resetting(vhost);
ibmvfc_release_crq_queue(vhost);
kthread_stop(vhost->work_thread);
fc_remove_host(vhost->host);
scsi_remove_host(vhost->host);
ibmvfc_release_crq_queue(vhost);
spin_lock_irqsave(vhost->host->host_lock, flags);
ibmvfc_purge_requests(vhost, DID_ERROR);

View file

@ -29,8 +29,8 @@
#include "viosrp.h"
#define IBMVFC_NAME "ibmvfc"
#define IBMVFC_DRIVER_VERSION "1.0.0"
#define IBMVFC_DRIVER_DATE "(July 1, 2008)"
#define IBMVFC_DRIVER_VERSION "1.0.1"
#define IBMVFC_DRIVER_DATE "(July 11, 2008)"
#define IBMVFC_DEFAULT_TIMEOUT 15
#define IBMVFC_INIT_TIMEOUT 30
@ -119,6 +119,7 @@ enum ibmvfc_mad_types {
IBMVFC_PROCESS_LOGIN = 0x0008,
IBMVFC_QUERY_TARGET = 0x0010,
IBMVFC_IMPLICIT_LOGOUT = 0x0040,
IBMVFC_PASSTHRU = 0x0200,
IBMVFC_TMF_MAD = 0x0100,
};
@ -439,6 +440,37 @@ struct ibmvfc_cmd {
struct ibmvfc_fcp_rsp rsp;
}__attribute__((packed, aligned (8)));
struct ibmvfc_passthru_fc_iu {
u32 payload[7];
#define IBMVFC_ADISC 0x52000000
u32 response[7];
};
struct ibmvfc_passthru_iu {
u64 task_tag;
u32 cmd_len;
u32 rsp_len;
u16 status;
u16 error;
u32 flags;
#define IBMVFC_FC_ELS 0x01
u32 cancel_key;
u32 reserved;
struct srp_direct_buf cmd;
struct srp_direct_buf rsp;
u64 correlation;
u64 scsi_id;
u64 tag;
u64 reserved2[2];
}__attribute__((packed, aligned (8)));
struct ibmvfc_passthru_mad {
struct ibmvfc_mad_common common;
struct srp_direct_buf cmd_ioba;
struct ibmvfc_passthru_iu iu;
struct ibmvfc_passthru_fc_iu fc_iu;
}__attribute__((packed, aligned (8)));
struct ibmvfc_trace_start_entry {
u32 xfer_len;
}__attribute__((packed));
@ -531,6 +563,7 @@ union ibmvfc_iu {
struct ibmvfc_implicit_logout implicit_logout;
struct ibmvfc_tmf tmf;
struct ibmvfc_cmd cmd;
struct ibmvfc_passthru_mad passthru;
}__attribute__((packed, aligned (8)));
enum ibmvfc_target_action {
@ -656,6 +689,9 @@ struct ibmvfc_host {
#define tgt_dbg(t, fmt, ...) \
DBG_CMD(dev_info((t)->vhost->dev, "%lX: " fmt, (t)->scsi_id, ##__VA_ARGS__))
#define tgt_info(t, fmt, ...) \
dev_info((t)->vhost->dev, "%lX: " fmt, (t)->scsi_id, ##__VA_ARGS__)
#define tgt_err(t, fmt, ...) \
dev_err((t)->vhost->dev, "%lX: " fmt, (t)->scsi_id, ##__VA_ARGS__)
@ -668,8 +704,8 @@ struct ibmvfc_host {
dev_err((vhost)->dev, ##__VA_ARGS__); \
} while (0)
#define ENTER DBG_CMD(printk(KERN_INFO IBMVFC_NAME": Entering %s\n", __FUNCTION__))
#define LEAVE DBG_CMD(printk(KERN_INFO IBMVFC_NAME": Leaving %s\n", __FUNCTION__))
#define ENTER DBG_CMD(printk(KERN_INFO IBMVFC_NAME": Entering %s\n", __func__))
#define LEAVE DBG_CMD(printk(KERN_INFO IBMVFC_NAME": Leaving %s\n", __func__))
#ifdef CONFIG_SCSI_IBMVFC_TRACE
#define ibmvfc_create_trace_file(kobj, attr) sysfs_create_bin_file(kobj, attr)

View file

@ -55,7 +55,7 @@
/* tmp - will replace with SCSI logging stuff */
#define eprintk(fmt, args...) \
do { \
printk("%s(%d) " fmt, __FUNCTION__, __LINE__, ##args); \
printk("%s(%d) " fmt, __func__, __LINE__, ##args); \
} while (0)
/* #define dprintk eprintk */
#define dprintk(fmt, args...)

View file

@ -163,7 +163,7 @@ static int imm_proc_info(struct Scsi_Host *host, char *buffer, char **start,
#if IMM_DEBUG > 0
#define imm_fail(x,y) printk("imm: imm_fail(%i) from %s at line %d\n",\
y, __FUNCTION__, __LINE__); imm_fail_func(x,y);
y, __func__, __LINE__); imm_fail_func(x,y);
static inline void
imm_fail_func(imm_struct *dev, int error_code)
#else

View file

@ -1403,10 +1403,10 @@ struct ipr_ucode_image_header {
}
#define ipr_trace ipr_dbg("%s: %s: Line: %d\n",\
__FILE__, __FUNCTION__, __LINE__)
__FILE__, __func__, __LINE__)
#define ENTER IPR_DBG_CMD(printk(KERN_INFO IPR_NAME": Entering %s\n", __FUNCTION__))
#define LEAVE IPR_DBG_CMD(printk(KERN_INFO IPR_NAME": Leaving %s\n", __FUNCTION__))
#define ENTER IPR_DBG_CMD(printk(KERN_INFO IPR_NAME": Entering %s\n", __func__))
#define LEAVE IPR_DBG_CMD(printk(KERN_INFO IPR_NAME": Leaving %s\n", __func__))
#define ipr_err_separator \
ipr_err("----------------------------------------------------------\n")

View file

@ -74,7 +74,7 @@ static enum ata_completion_errors sas_to_ata_err(struct task_status_struct *ts)
case SAS_OPEN_TO:
case SAS_OPEN_REJECT:
SAS_DPRINTK("%s: Saw error %d. What to do?\n",
__FUNCTION__, ts->stat);
__func__, ts->stat);
return AC_ERR_OTHER;
case SAS_ABORTED_TASK:
@ -115,7 +115,7 @@ static void sas_ata_task_done(struct sas_task *task)
} else if (stat->stat != SAM_STAT_GOOD) {
ac = sas_to_ata_err(stat);
if (ac) {
SAS_DPRINTK("%s: SAS error %x\n", __FUNCTION__,
SAS_DPRINTK("%s: SAS error %x\n", __func__,
stat->stat);
/* We saw a SAS error. Send a vague error. */
qc->err_mask = ac;
@ -244,20 +244,20 @@ static void sas_ata_phy_reset(struct ata_port *ap)
res = i->dft->lldd_I_T_nexus_reset(dev);
if (res != TMF_RESP_FUNC_COMPLETE)
SAS_DPRINTK("%s: Unable to reset I T nexus?\n", __FUNCTION__);
SAS_DPRINTK("%s: Unable to reset I T nexus?\n", __func__);
switch (dev->sata_dev.command_set) {
case ATA_COMMAND_SET:
SAS_DPRINTK("%s: Found ATA device.\n", __FUNCTION__);
SAS_DPRINTK("%s: Found ATA device.\n", __func__);
ap->link.device[0].class = ATA_DEV_ATA;
break;
case ATAPI_COMMAND_SET:
SAS_DPRINTK("%s: Found ATAPI device.\n", __FUNCTION__);
SAS_DPRINTK("%s: Found ATAPI device.\n", __func__);
ap->link.device[0].class = ATA_DEV_ATAPI;
break;
default:
SAS_DPRINTK("%s: Unknown SATA command set: %d.\n",
__FUNCTION__,
__func__,
dev->sata_dev.command_set);
ap->link.device[0].class = ATA_DEV_UNKNOWN;
break;
@ -299,7 +299,7 @@ static int sas_ata_scr_write(struct ata_port *ap, unsigned int sc_reg_in,
{
struct domain_device *dev = ap->private_data;
SAS_DPRINTK("STUB %s\n", __FUNCTION__);
SAS_DPRINTK("STUB %s\n", __func__);
switch (sc_reg_in) {
case SCR_STATUS:
dev->sata_dev.sstatus = val;
@ -324,7 +324,7 @@ static int sas_ata_scr_read(struct ata_port *ap, unsigned int sc_reg_in,
{
struct domain_device *dev = ap->private_data;
SAS_DPRINTK("STUB %s\n", __FUNCTION__);
SAS_DPRINTK("STUB %s\n", __func__);
switch (sc_reg_in) {
case SCR_STATUS:
*val = dev->sata_dev.sstatus;

View file

@ -121,7 +121,7 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size,
break;
} else {
SAS_DPRINTK("%s: task to dev %016llx response: 0x%x "
"status 0x%x\n", __FUNCTION__,
"status 0x%x\n", __func__,
SAS_ADDR(dev->sas_addr),
task->task_status.resp,
task->task_status.stat);
@ -1279,7 +1279,7 @@ static int sas_configure_present(struct domain_device *dev, int phy_id,
goto out;
} else if (res != SMP_RESP_FUNC_ACC) {
SAS_DPRINTK("%s: dev %016llx phy 0x%x index 0x%x "
"result 0x%x\n", __FUNCTION__,
"result 0x%x\n", __func__,
SAS_ADDR(dev->sas_addr), phy_id, i, res);
goto out;
}
@ -1901,7 +1901,7 @@ int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
if (!rsp) {
printk("%s: space for a smp response is missing\n",
__FUNCTION__);
__func__);
return -EINVAL;
}
@ -1914,20 +1914,20 @@ int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
if (type != SAS_EDGE_EXPANDER_DEVICE &&
type != SAS_FANOUT_EXPANDER_DEVICE) {
printk("%s: can we send a smp request to a device?\n",
__FUNCTION__);
__func__);
return -EINVAL;
}
dev = sas_find_dev_by_rphy(rphy);
if (!dev) {
printk("%s: fail to find a domain_device?\n", __FUNCTION__);
printk("%s: fail to find a domain_device?\n", __func__);
return -EINVAL;
}
/* do we need to support multiple segments? */
if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
printk("%s: multiple segments req %u %u, rsp %u %u\n",
__FUNCTION__, req->bio->bi_vcnt, req->data_len,
__func__, req->bio->bi_vcnt, req->data_len,
rsp->bio->bi_vcnt, rsp->data_len);
return -EINVAL;
}

View file

@ -50,7 +50,7 @@ static void sas_form_port(struct asd_sas_phy *phy)
sas_deform_port(phy);
else {
SAS_DPRINTK("%s: phy%d belongs to port%d already(%d)!\n",
__FUNCTION__, phy->id, phy->port->id,
__func__, phy->id, phy->port->id,
phy->port->num_phys);
return;
}
@ -78,7 +78,7 @@ static void sas_form_port(struct asd_sas_phy *phy)
if (i >= sas_ha->num_phys) {
printk(KERN_NOTICE "%s: couldn't find a free port, bug?\n",
__FUNCTION__);
__func__);
spin_unlock_irqrestore(&sas_ha->phy_port_lock, flags);
return;
}

View file

@ -343,7 +343,7 @@ static enum task_disposition sas_scsi_find_task(struct sas_task *task)
flags);
SAS_DPRINTK("%s: task 0x%p aborted from "
"task_queue\n",
__FUNCTION__, task);
__func__, task);
return TASK_IS_ABORTED;
}
}
@ -351,13 +351,13 @@ static enum task_disposition sas_scsi_find_task(struct sas_task *task)
}
for (i = 0; i < 5; i++) {
SAS_DPRINTK("%s: aborting task 0x%p\n", __FUNCTION__, task);
SAS_DPRINTK("%s: aborting task 0x%p\n", __func__, task);
res = si->dft->lldd_abort_task(task);
spin_lock_irqsave(&task->task_state_lock, flags);
if (task->task_state_flags & SAS_TASK_STATE_DONE) {
spin_unlock_irqrestore(&task->task_state_lock, flags);
SAS_DPRINTK("%s: task 0x%p is done\n", __FUNCTION__,
SAS_DPRINTK("%s: task 0x%p is done\n", __func__,
task);
return TASK_IS_DONE;
}
@ -365,24 +365,24 @@ static enum task_disposition sas_scsi_find_task(struct sas_task *task)
if (res == TMF_RESP_FUNC_COMPLETE) {
SAS_DPRINTK("%s: task 0x%p is aborted\n",
__FUNCTION__, task);
__func__, task);
return TASK_IS_ABORTED;
} else if (si->dft->lldd_query_task) {
SAS_DPRINTK("%s: querying task 0x%p\n",
__FUNCTION__, task);
__func__, task);
res = si->dft->lldd_query_task(task);
switch (res) {
case TMF_RESP_FUNC_SUCC:
SAS_DPRINTK("%s: task 0x%p at LU\n",
__FUNCTION__, task);
__func__, task);
return TASK_IS_AT_LU;
case TMF_RESP_FUNC_COMPLETE:
SAS_DPRINTK("%s: task 0x%p not at LU\n",
__FUNCTION__, task);
__func__, task);
return TASK_IS_NOT_AT_LU;
case TMF_RESP_FUNC_FAILED:
SAS_DPRINTK("%s: task 0x%p failed to abort\n",
__FUNCTION__, task);
__func__, task);
return TASK_ABORT_FAILED;
}
@ -545,7 +545,7 @@ Again:
if (need_reset) {
SAS_DPRINTK("%s: task 0x%p requests reset\n",
__FUNCTION__, task);
__func__, task);
goto reset;
}
@ -556,13 +556,13 @@ Again:
switch (res) {
case TASK_IS_DONE:
SAS_DPRINTK("%s: task 0x%p is done\n", __FUNCTION__,
SAS_DPRINTK("%s: task 0x%p is done\n", __func__,
task);
sas_eh_finish_cmd(cmd);
continue;
case TASK_IS_ABORTED:
SAS_DPRINTK("%s: task 0x%p is aborted\n",
__FUNCTION__, task);
__func__, task);
sas_eh_finish_cmd(cmd);
continue;
case TASK_IS_AT_LU:
@ -633,7 +633,7 @@ Again:
}
return list_empty(work_q);
clear_q:
SAS_DPRINTK("--- Exit %s -- clear_q\n", __FUNCTION__);
SAS_DPRINTK("--- Exit %s -- clear_q\n", __func__);
list_for_each_entry_safe(cmd, n, work_q, eh_entry)
sas_eh_finish_cmd(cmd);
@ -650,7 +650,7 @@ void sas_scsi_recover_host(struct Scsi_Host *shost)
list_splice_init(&shost->eh_cmd_q, &eh_work_q);
spin_unlock_irqrestore(shost->host_lock, flags);
SAS_DPRINTK("Enter %s\n", __FUNCTION__);
SAS_DPRINTK("Enter %s\n", __func__);
/*
* Deal with commands that still have SAS tasks (i.e. they didn't
* complete via the normal sas_task completion mechanism)
@ -669,7 +669,7 @@ void sas_scsi_recover_host(struct Scsi_Host *shost)
out:
scsi_eh_flush_done_q(&ha->eh_done_q);
SAS_DPRINTK("--- Exit %s\n", __FUNCTION__);
SAS_DPRINTK("--- Exit %s\n", __func__);
return;
}
@ -990,7 +990,7 @@ int __sas_task_abort(struct sas_task *task)
if (task->task_state_flags & SAS_TASK_STATE_ABORTED ||
task->task_state_flags & SAS_TASK_STATE_DONE) {
spin_unlock_irqrestore(&task->task_state_lock, flags);
SAS_DPRINTK("%s: Task %p already finished.\n", __FUNCTION__,
SAS_DPRINTK("%s: Task %p already finished.\n", __func__,
task);
return 0;
}

View file

@ -39,7 +39,7 @@ enum srp_task_attributes {
/* tmp - will replace with SCSI logging stuff */
#define eprintk(fmt, args...) \
do { \
printk("%s(%d) " fmt, __FUNCTION__, __LINE__, ##args); \
printk("%s(%d) " fmt, __func__, __LINE__, ##args); \
} while (0)
/* #define dprintk eprintk */
#define dprintk(fmt, args...)

View file

@ -2083,7 +2083,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
if (iocbq_entry == NULL) {
printk(KERN_ERR "%s: only allocated %d iocbs of "
"expected %d count. Unloading driver.\n",
__FUNCTION__, i, LPFC_IOCB_LIST_CNT);
__func__, i, LPFC_IOCB_LIST_CNT);
error = -ENOMEM;
goto out_free_iocbq;
}
@ -2093,7 +2093,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
kfree (iocbq_entry);
printk(KERN_ERR "%s: failed to allocate IOTAG. "
"Unloading driver.\n",
__FUNCTION__);
__func__);
error = -ENOMEM;
goto out_free_iocbq;
}

View file

@ -341,7 +341,7 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) {
printk(KERN_ERR "%s: Too many sg segments from "
"dma_map_sg. Config %d, seg_cnt %d",
__FUNCTION__, phba->cfg_sg_seg_cnt,
__func__, phba->cfg_sg_seg_cnt,
lpfc_cmd->seg_cnt);
scsi_dma_unmap(scsi_cmnd);
return 1;

View file

@ -219,7 +219,7 @@ lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd)
case CMD_IOCB_LOGENTRY_CN:
case CMD_IOCB_LOGENTRY_ASYNC_CN:
printk("%s - Unhandled SLI-3 Command x%x\n",
__FUNCTION__, iocb_cmnd);
__func__, iocb_cmnd);
type = LPFC_UNKNOWN_IOCB;
break;
default:
@ -1715,7 +1715,7 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba,
rspiocbp = __lpfc_sli_get_iocbq(phba);
if (rspiocbp == NULL) {
printk(KERN_ERR "%s: out of buffers! Failing "
"completion.\n", __FUNCTION__);
"completion.\n", __func__);
break;
}
@ -3793,7 +3793,7 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, struct lpfc_vport *vport,
break;
default:
printk(KERN_ERR "%s: Unknown context cmd type, value %d\n",
__FUNCTION__, ctx_cmd);
__func__, ctx_cmd);
break;
}

View file

@ -265,7 +265,7 @@ typedef struct {
#define ASSERT(expression) \
if (!(expression)) { \
ASSERT_ACTION("assertion failed:(%s), file: %s, line: %d:%s\n", \
#expression, __FILE__, __LINE__, __FUNCTION__); \
#expression, __FILE__, __LINE__, __func__); \
}
#else
#define ASSERT(expression)

View file

@ -458,7 +458,7 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
if (adapter == NULL) {
con_log(CL_ANN, (KERN_WARNING
"megaraid: out of memory, %s %d.\n", __FUNCTION__, __LINE__));
"megaraid: out of memory, %s %d.\n", __func__, __LINE__));
goto out_probe_one;
}
@ -1002,7 +1002,7 @@ megaraid_alloc_cmd_packets(adapter_t *adapter)
if (!raid_dev->una_mbox64) {
con_log(CL_ANN, (KERN_WARNING
"megaraid: out of memory, %s %d\n", __FUNCTION__,
"megaraid: out of memory, %s %d\n", __func__,
__LINE__));
return -1;
}
@ -1030,7 +1030,7 @@ megaraid_alloc_cmd_packets(adapter_t *adapter)
if (!adapter->ibuf) {
con_log(CL_ANN, (KERN_WARNING
"megaraid: out of memory, %s %d\n", __FUNCTION__,
"megaraid: out of memory, %s %d\n", __func__,
__LINE__));
goto out_free_common_mbox;
@ -1052,7 +1052,7 @@ megaraid_alloc_cmd_packets(adapter_t *adapter)
if (adapter->kscb_list == NULL) {
con_log(CL_ANN, (KERN_WARNING
"megaraid: out of memory, %s %d\n", __FUNCTION__,
"megaraid: out of memory, %s %d\n", __func__,
__LINE__));
goto out_free_ibuf;
}
@ -1060,7 +1060,7 @@ megaraid_alloc_cmd_packets(adapter_t *adapter)
// memory allocation for our command packets
if (megaraid_mbox_setup_dma_pools(adapter) != 0) {
con_log(CL_ANN, (KERN_WARNING
"megaraid: out of memory, %s %d\n", __FUNCTION__,
"megaraid: out of memory, %s %d\n", __func__,
__LINE__));
goto out_free_scb_list;
}
@ -2981,7 +2981,7 @@ megaraid_mbox_product_info(adapter_t *adapter)
if (pinfo == NULL) {
con_log(CL_ANN, (KERN_WARNING
"megaraid: out of memory, %s %d\n", __FUNCTION__,
"megaraid: out of memory, %s %d\n", __func__,
__LINE__));
return -1;
@ -3508,7 +3508,7 @@ megaraid_cmm_register(adapter_t *adapter)
if (adapter->uscb_list == NULL) {
con_log(CL_ANN, (KERN_WARNING
"megaraid: out of memory, %s %d\n", __FUNCTION__,
"megaraid: out of memory, %s %d\n", __func__,
__LINE__));
return -1;
}
@ -3879,7 +3879,7 @@ megaraid_sysfs_alloc_resources(adapter_t *adapter)
!raid_dev->sysfs_buffer) {
con_log(CL_ANN, (KERN_WARNING
"megaraid: out of memory, %s %d\n", __FUNCTION__,
"megaraid: out of memory, %s %d\n", __func__,
__LINE__));
rval = -ENOMEM;

View file

@ -929,7 +929,7 @@ mraid_mm_register_adp(mraid_mmadp_t *lld_adp)
!adapter->pthru_dma_pool) {
con_log(CL_ANN, (KERN_WARNING
"megaraid cmm: out of memory, %s %d\n", __FUNCTION__,
"megaraid cmm: out of memory, %s %d\n", __func__,
__LINE__));
rval = (-ENOMEM);
@ -957,7 +957,7 @@ mraid_mm_register_adp(mraid_mmadp_t *lld_adp)
con_log(CL_ANN, (KERN_WARNING
"megaraid cmm: out of memory, %s %d\n",
__FUNCTION__, __LINE__));
__func__, __LINE__));
rval = (-ENOMEM);

View file

@ -299,9 +299,9 @@ static struct scsi_host_template nsp32_template = {
#else
# define NSP32_DEBUG_MASK 0xffffff
# define nsp32_msg(type, args...) \
nsp32_message (__FUNCTION__, __LINE__, (type), args)
nsp32_message (__func__, __LINE__, (type), args)
# define nsp32_dbg(mask, args...) \
nsp32_dmessage(__FUNCTION__, __LINE__, (mask), args)
nsp32_dmessage(__func__, __LINE__, (mask), args)
#endif
#define NSP32_DEBUG_QUEUECOMMAND BIT(0)

View file

@ -88,7 +88,7 @@ static void print_commandk (unsigned char *command)
int i,s;
// printk(KERN_DEBUG);
print_opcodek(command[0]);
/*printk(KERN_DEBUG "%s ", __FUNCTION__);*/
/*printk(KERN_DEBUG "%s ", __func__);*/
if ((command[0] >> 5) == 6 ||
(command[0] >> 5) == 7 ) {
s = 12; /* vender specific */

View file

@ -107,9 +107,9 @@ static nsp_hw_data nsp_data_base; /* attach <-> detect glue */
#else
# define NSP_DEBUG_MASK 0xffffff
# define nsp_msg(type, args...) \
nsp_cs_message (__FUNCTION__, __LINE__, (type), args)
nsp_cs_message (__func__, __LINE__, (type), args)
# define nsp_dbg(mask, args...) \
nsp_cs_dmessage(__FUNCTION__, __LINE__, (mask), args)
nsp_cs_dmessage(__func__, __LINE__, (mask), args)
#endif
#define NSP_DEBUG_QUEUECOMMAND BIT(0)

View file

@ -90,7 +90,7 @@ static void print_commandk (unsigned char *command)
int i, s;
printk(KERN_DEBUG);
print_opcodek(command[0]);
/*printk(KERN_DEBUG "%s ", __FUNCTION__);*/
/*printk(KERN_DEBUG "%s ", __func__);*/
if ((command[0] >> 5) == 6 ||
(command[0] >> 5) == 7 ) {
s = 12; /* vender specific */

View file

@ -171,7 +171,7 @@ static int device_check(ppa_struct *dev);
#if PPA_DEBUG > 0
#define ppa_fail(x,y) printk("ppa: ppa_fail(%i) from %s at line %d\n",\
y, __FUNCTION__, __LINE__); ppa_fail_func(x,y);
y, __func__, __LINE__); ppa_fail_func(x,y);
static inline void ppa_fail_func(ppa_struct *dev, int error_code)
#else
static inline void ppa_fail(ppa_struct *dev, int error_code)

View file

@ -1695,7 +1695,7 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
risc_code_size = *ql1280_board_tbl[ha->devnum].fwlen;
dprintk(1, "%s: DMA RISC code (%i) words\n",
__FUNCTION__, risc_code_size);
__func__, risc_code_size);
num = 0;
while (risc_code_size > 0) {
@ -1721,7 +1721,7 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
mb[7] = pci_dma_hi32(ha->request_dma) & 0xffff;
mb[6] = pci_dma_hi32(ha->request_dma) >> 16;
dprintk(2, "%s: op=%d 0x%p = 0x%4x,0x%4x,0x%4x,0x%4x\n",
__FUNCTION__, mb[0],
__func__, mb[0],
(void *)(long)ha->request_dma,
mb[6], mb[7], mb[2], mb[3]);
err = qla1280_mailbox_command(ha, BIT_4 | BIT_3 | BIT_2 |
@ -1753,10 +1753,10 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
if (tbuf[i] != sp[i] && warn++ < 10) {
printk(KERN_ERR "%s: FW compare error @ "
"byte(0x%x) loop#=%x\n",
__FUNCTION__, i, num);
__func__, i, num);
printk(KERN_ERR "%s: FWbyte=%x "
"FWfromChip=%x\n",
__FUNCTION__, sp[i], tbuf[i]);
__func__, sp[i], tbuf[i]);
/*break; */
}
}
@ -1781,7 +1781,7 @@ qla1280_start_firmware(struct scsi_qla_host *ha)
int err;
dprintk(1, "%s: Verifying checksum of loaded RISC code.\n",
__FUNCTION__);
__func__);
/* Verify checksum of loaded RISC code. */
mb[0] = MBC_VERIFY_CHECKSUM;
@ -1794,7 +1794,7 @@ qla1280_start_firmware(struct scsi_qla_host *ha)
}
/* Start firmware execution. */
dprintk(1, "%s: start firmware running.\n", __FUNCTION__);
dprintk(1, "%s: start firmware running.\n", __func__);
mb[0] = MBC_EXECUTE_FIRMWARE;
mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
err = qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);

View file

@ -20,18 +20,12 @@ qla2x00_sysfs_read_fw_dump(struct kobject *kobj,
{
struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
struct device, kobj)));
char *rbuf = (char *)ha->fw_dump;
if (ha->fw_dump_reading == 0)
return 0;
if (off > ha->fw_dump_len)
return 0;
if (off + count > ha->fw_dump_len)
count = ha->fw_dump_len - off;
memcpy(buf, &rbuf[off], count);
return (count);
return memory_read_from_buffer(buf, count, &off, ha->fw_dump,
ha->fw_dump_len);
}
static ssize_t
@ -94,20 +88,13 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj,
{
struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
struct device, kobj)));
int size = ha->nvram_size;
char *nvram_cache = ha->nvram;
if (!capable(CAP_SYS_ADMIN) || off > size || count == 0)
if (!capable(CAP_SYS_ADMIN))
return 0;
if (off + count > size) {
size -= off;
count = size;
}
/* Read NVRAM data from cache. */
memcpy(buf, &nvram_cache[off], count);
return count;
return memory_read_from_buffer(buf, count, &off, ha->nvram,
ha->nvram_size);
}
static ssize_t
@ -175,14 +162,9 @@ qla2x00_sysfs_read_optrom(struct kobject *kobj,
if (ha->optrom_state != QLA_SREADING)
return 0;
if (off > ha->optrom_region_size)
return 0;
if (off + count > ha->optrom_region_size)
count = ha->optrom_region_size - off;
memcpy(buf, &ha->optrom_buffer[off], count);
return count;
return memory_read_from_buffer(buf, count, &off, ha->optrom_buffer,
ha->optrom_region_size);
}
static ssize_t
@ -374,20 +356,12 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj,
{
struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
struct device, kobj)));
int size = ha->vpd_size;
char *vpd_cache = ha->vpd;
if (!capable(CAP_SYS_ADMIN) || off > size || count == 0)
if (!capable(CAP_SYS_ADMIN))
return 0;
if (off + count > size) {
size -= off;
count = size;
}
/* Read NVRAM data from cache. */
memcpy(buf, &vpd_cache[off], count);
return count;
return memory_read_from_buffer(buf, count, &off, ha->vpd, ha->vpd_size);
}
static ssize_t
@ -557,8 +531,10 @@ qla2x00_serial_num_show(struct device *dev, struct device_attribute *attr,
scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
uint32_t sn;
if (IS_FWI2_CAPABLE(ha))
return snprintf(buf, PAGE_SIZE, "\n");
if (IS_FWI2_CAPABLE(ha)) {
qla2xxx_get_vpd_field(ha, "SN", buf, PAGE_SIZE);
return snprintf(buf, PAGE_SIZE, "%s\n", buf);
}
sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1;
return snprintf(buf, PAGE_SIZE, "%c%05d\n", 'A' + sn / 100000,
@ -809,6 +785,16 @@ qla2x00_optrom_fw_version_show(struct device *dev,
ha->fw_revision[3]);
}
static ssize_t
qla2x00_total_isp_aborts_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
return snprintf(buf, PAGE_SIZE, "%d\n",
ha->qla_stats.total_isp_aborts);
}
static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL);
static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL);
@ -831,6 +817,8 @@ static DEVICE_ATTR(optrom_fcode_version, S_IRUGO,
qla2x00_optrom_fcode_version_show, NULL);
static DEVICE_ATTR(optrom_fw_version, S_IRUGO, qla2x00_optrom_fw_version_show,
NULL);
static DEVICE_ATTR(total_isp_aborts, S_IRUGO, qla2x00_total_isp_aborts_show,
NULL);
struct device_attribute *qla2x00_host_attrs[] = {
&dev_attr_driver_version,
@ -849,6 +837,7 @@ struct device_attribute *qla2x00_host_attrs[] = {
&dev_attr_optrom_efi_version,
&dev_attr_optrom_fcode_version,
&dev_attr_optrom_fw_version,
&dev_attr_total_isp_aborts,
NULL,
};
@ -972,26 +961,39 @@ qla2x00_get_starget_port_id(struct scsi_target *starget)
}
static void
qla2x00_get_rport_loss_tmo(struct fc_rport *rport)
qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
{
struct Scsi_Host *host = rport_to_shost(rport);
scsi_qla_host_t *ha = shost_priv(host);
rport->dev_loss_tmo = ha->port_down_retry_count + 5;
if (timeout)
rport->dev_loss_tmo = timeout;
else
rport->dev_loss_tmo = 1;
}
static void
qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
qla2x00_dev_loss_tmo_callbk(struct fc_rport *rport)
{
struct Scsi_Host *host = rport_to_shost(rport);
scsi_qla_host_t *ha = shost_priv(host);
fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
if (timeout)
ha->port_down_retry_count = timeout;
else
ha->port_down_retry_count = 1;
qla2x00_abort_fcport_cmds(fcport);
rport->dev_loss_tmo = ha->port_down_retry_count + 5;
/*
* Transport has effectively 'deleted' the rport, clear
* all local references.
*/
spin_lock_irq(host->host_lock);
fcport->rport = NULL;
*((fc_port_t **)rport->dd_data) = NULL;
spin_unlock_irq(host->host_lock);
}
static void
qla2x00_terminate_rport_io(struct fc_rport *rport)
{
fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
qla2x00_abort_fcport_cmds(fcport);
scsi_target_unblock(&rport->dev);
}
static int
@ -1045,6 +1047,7 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
pfc_host_stat->invalid_tx_word_count = stats->inval_xmit_word_cnt;
pfc_host_stat->invalid_crc_count = stats->inval_crc_cnt;
if (IS_FWI2_CAPABLE(ha)) {
pfc_host_stat->lip_count = stats->lip_cnt;
pfc_host_stat->tx_frames = stats->tx_frames;
pfc_host_stat->rx_frames = stats->rx_frames;
pfc_host_stat->dumped_frames = stats->dumped_frames;
@ -1173,17 +1176,16 @@ vport_create_failed_2:
static int
qla24xx_vport_delete(struct fc_vport *fc_vport)
{
scsi_qla_host_t *ha = shost_priv(fc_vport->shost);
scsi_qla_host_t *vha = fc_vport->dd_data;
scsi_qla_host_t *pha = to_qla_parent(vha);
while (test_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags) ||
test_bit(FCPORT_UPDATE_NEEDED, &pha->dpc_flags))
msleep(1000);
qla24xx_disable_vp(vha);
qla24xx_deallocate_vp_id(vha);
mutex_lock(&ha->vport_lock);
ha->cur_vport_count--;
clear_bit(vha->vp_idx, ha->vp_idx_map);
mutex_unlock(&ha->vport_lock);
kfree(vha->node_name);
kfree(vha->port_name);
@ -1248,11 +1250,12 @@ struct fc_function_template qla2xxx_transport_functions = {
.get_starget_port_id = qla2x00_get_starget_port_id,
.show_starget_port_id = 1,
.get_rport_dev_loss_tmo = qla2x00_get_rport_loss_tmo,
.set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo,
.show_rport_dev_loss_tmo = 1,
.issue_fc_host_lip = qla2x00_issue_lip,
.dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk,
.terminate_rport_io = qla2x00_terminate_rport_io,
.get_fc_host_stats = qla2x00_get_fc_host_stats,
.vport_create = qla24xx_vport_create,
@ -1291,11 +1294,12 @@ struct fc_function_template qla2xxx_transport_vport_functions = {
.get_starget_port_id = qla2x00_get_starget_port_id,
.show_starget_port_id = 1,
.get_rport_dev_loss_tmo = qla2x00_get_rport_loss_tmo,
.set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo,
.show_rport_dev_loss_tmo = 1,
.issue_fc_host_lip = qla2x00_issue_lip,
.dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk,
.terminate_rport_io = qla2x00_terminate_rport_io,
.get_fc_host_stats = qla2x00_get_fc_host_stats,
};

View file

@ -216,7 +216,7 @@ qla24xx_soft_reset(scsi_qla_host_t *ha)
static int
qla2xxx_dump_ram(scsi_qla_host_t *ha, uint32_t addr, uint16_t *ram,
uint16_t ram_words, void **nxt)
uint32_t ram_words, void **nxt)
{
int rval;
uint32_t cnt, stat, timer, words, idx;

View file

@ -864,7 +864,8 @@ struct link_statistics {
uint32_t prim_seq_err_cnt;
uint32_t inval_xmit_word_cnt;
uint32_t inval_crc_cnt;
uint32_t unused1[0x1b];
uint32_t lip_cnt;
uint32_t unused1[0x1a];
uint32_t tx_frames;
uint32_t rx_frames;
uint32_t dumped_frames;
@ -1544,7 +1545,6 @@ typedef struct fc_port {
int login_retry;
atomic_t port_down_timer;
spinlock_t rport_lock;
struct fc_rport *rport, *drport;
u32 supported_classes;
@ -2155,6 +2155,10 @@ struct qla_chip_state_84xx {
uint32_t gold_fw_version;
};
struct qla_statistics {
uint32_t total_isp_aborts;
};
/*
* Linux Host Adapter structure
*/
@ -2166,7 +2170,6 @@ typedef struct scsi_qla_host {
struct pci_dev *pdev;
unsigned long host_no;
unsigned long instance;
volatile struct {
uint32_t init_done :1;
@ -2515,7 +2518,7 @@ typedef struct scsi_qla_host {
uint8_t model_number[16+1];
#define BINZERO "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
char *model_desc;
char model_desc[80];
uint8_t adapter_id[16+1];
uint8_t *node_name;
@ -2596,6 +2599,7 @@ typedef struct scsi_qla_host {
int cur_vport_count;
struct qla_chip_state_84xx *cs84xx;
struct qla_statistics qla_stats;
} scsi_qla_host_t;

View file

@ -62,7 +62,7 @@ extern int ql2xfdmienable;
extern int ql2xallocfwdump;
extern int ql2xextended_error_logging;
extern int ql2xqfullrampup;
extern int num_hosts;
extern int ql2xiidmaenable;
extern int qla2x00_loop_reset(scsi_qla_host_t *);
extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
@ -71,6 +71,8 @@ extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum
extern int qla2x00_post_hwe_work(struct scsi_qla_host *, uint16_t , uint16_t,
uint16_t, uint16_t);
extern void qla2x00_abort_fcport_cmds(fc_port_t *);
/*
* Global Functions in qla_mid.c source file.
*/
@ -312,6 +314,7 @@ extern int qla2xxx_hw_event_log(scsi_qla_host_t *, uint16_t , uint16_t,
uint16_t, uint16_t);
extern void qla2xxx_get_flash_info(scsi_qla_host_t *);
extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t);
/*
* Global Function Prototypes in qla_dbg.c source file.

View file

@ -1661,6 +1661,12 @@ qla2x00_fdmi_register(scsi_qla_host_t *ha)
{
int rval;
if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
DEBUG2(printk("scsi(%ld): FDMI unsupported on "
"ISP2100/ISP2200.\n", ha->host_no));
return QLA_SUCCESS;
}
rval = qla2x00_mgmt_svr_login(ha);
if (rval)
return rval;

View file

@ -334,6 +334,8 @@ static int
qla2x00_isp_firmware(scsi_qla_host_t *ha)
{
int rval;
uint16_t loop_id, topo, sw_cap;
uint8_t domain, area, al_pa;
/* Assume loading risc code */
rval = QLA_FUNCTION_FAILED;
@ -345,6 +347,11 @@ qla2x00_isp_firmware(scsi_qla_host_t *ha)
/* Verify checksum of loaded RISC code. */
rval = qla2x00_verify_checksum(ha, ha->fw_srisc_address);
if (rval == QLA_SUCCESS) {
/* And, verify we are not in ROM code. */
rval = qla2x00_get_adapter_id(ha, &loop_id, &al_pa,
&area, &domain, &topo, &sw_cap);
}
}
if (rval) {
@ -722,7 +729,7 @@ qla24xx_chip_diag(scsi_qla_host_t *ha)
/* Perform RISC reset. */
qla24xx_reset_risc(ha);
ha->fw_transfer_size = REQUEST_ENTRY_SIZE * 1024;
ha->fw_transfer_size = REQUEST_ENTRY_SIZE * ha->request_q_length;
rval = qla2x00_mbx_reg_test(ha);
if (rval) {
@ -768,6 +775,38 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *ha)
mem_size = (ha->fw_memory_size - 0x100000 + 1) *
sizeof(uint32_t);
/* Allocate memory for Fibre Channel Event Buffer. */
if (!IS_QLA25XX(ha))
goto try_eft;
tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma,
GFP_KERNEL);
if (!tc) {
qla_printk(KERN_WARNING, ha, "Unable to allocate "
"(%d KB) for FCE.\n", FCE_SIZE / 1024);
goto try_eft;
}
memset(tc, 0, FCE_SIZE);
rval = qla2x00_enable_fce_trace(ha, tc_dma, FCE_NUM_BUFFERS,
ha->fce_mb, &ha->fce_bufs);
if (rval) {
qla_printk(KERN_WARNING, ha, "Unable to initialize "
"FCE (%d).\n", rval);
dma_free_coherent(&ha->pdev->dev, FCE_SIZE, tc,
tc_dma);
ha->flags.fce_enabled = 0;
goto try_eft;
}
qla_printk(KERN_INFO, ha, "Allocated (%d KB) for FCE...\n",
FCE_SIZE / 1024);
fce_size = sizeof(struct qla2xxx_fce_chain) + EFT_SIZE;
ha->flags.fce_enabled = 1;
ha->fce_dma = tc_dma;
ha->fce = tc;
try_eft:
/* Allocate memory for Extended Trace Buffer. */
tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma,
GFP_KERNEL);
@ -793,38 +832,6 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *ha)
eft_size = EFT_SIZE;
ha->eft_dma = tc_dma;
ha->eft = tc;
/* Allocate memory for Fibre Channel Event Buffer. */
if (!IS_QLA25XX(ha))
goto cont_alloc;
tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma,
GFP_KERNEL);
if (!tc) {
qla_printk(KERN_WARNING, ha, "Unable to allocate "
"(%d KB) for FCE.\n", FCE_SIZE / 1024);
goto cont_alloc;
}
memset(tc, 0, FCE_SIZE);
rval = qla2x00_enable_fce_trace(ha, tc_dma, FCE_NUM_BUFFERS,
ha->fce_mb, &ha->fce_bufs);
if (rval) {
qla_printk(KERN_WARNING, ha, "Unable to initialize "
"FCE (%d).\n", rval);
dma_free_coherent(&ha->pdev->dev, FCE_SIZE, tc,
tc_dma);
ha->flags.fce_enabled = 0;
goto cont_alloc;
}
qla_printk(KERN_INFO, ha, "Allocated (%d KB) for FCE...\n",
FCE_SIZE / 1024);
fce_size = sizeof(struct qla2xxx_fce_chain) + EFT_SIZE;
ha->flags.fce_enabled = 1;
ha->fce_dma = tc_dma;
ha->fce = tc;
}
cont_alloc:
req_q_size = ha->request_q_length * sizeof(request_t);
@ -1501,18 +1508,25 @@ qla2x00_set_model_info(scsi_qla_host_t *ha, uint8_t *model, size_t len, char *de
index = (ha->pdev->subsystem_device & 0xff);
if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
index < QLA_MODEL_NAMES)
ha->model_desc = qla2x00_model_name[index * 2 + 1];
strncpy(ha->model_desc,
qla2x00_model_name[index * 2 + 1],
sizeof(ha->model_desc) - 1);
} else {
index = (ha->pdev->subsystem_device & 0xff);
if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
index < QLA_MODEL_NAMES) {
strcpy(ha->model_number,
qla2x00_model_name[index * 2]);
ha->model_desc = qla2x00_model_name[index * 2 + 1];
strncpy(ha->model_desc,
qla2x00_model_name[index * 2 + 1],
sizeof(ha->model_desc) - 1);
} else {
strcpy(ha->model_number, def);
}
}
if (IS_FWI2_CAPABLE(ha))
qla2xxx_get_vpd_field(ha, "\x82", ha->model_desc,
sizeof(ha->model_desc));
}
/* On sparc systems, obtain port and node WWN from firmware
@ -1864,12 +1878,11 @@ qla2x00_rport_del(void *data)
{
fc_port_t *fcport = data;
struct fc_rport *rport;
unsigned long flags;
spin_lock_irqsave(&fcport->rport_lock, flags);
spin_lock_irq(fcport->ha->host->host_lock);
rport = fcport->drport;
fcport->drport = NULL;
spin_unlock_irqrestore(&fcport->rport_lock, flags);
spin_unlock_irq(fcport->ha->host->host_lock);
if (rport)
fc_remote_port_delete(rport);
}
@ -1898,7 +1911,6 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags)
atomic_set(&fcport->state, FCS_UNCONFIGURED);
fcport->flags = FCF_RLC_SUPPORT;
fcport->supported_classes = FC_COS_UNSPECIFIED;
spin_lock_init(&fcport->rport_lock);
return fcport;
}
@ -2007,8 +2019,10 @@ qla2x00_configure_loop(scsi_qla_host_t *ha)
if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) {
if (test_bit(LOCAL_LOOP_UPDATE, &save_flags))
set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);
if (test_bit(RSCN_UPDATE, &save_flags))
if (test_bit(RSCN_UPDATE, &save_flags)) {
ha->flags.rscn_queue_overflow = 1;
set_bit(RSCN_UPDATE, &ha->dpc_flags);
}
}
return (rval);
@ -2243,28 +2257,24 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
{
struct fc_rport_identifiers rport_ids;
struct fc_rport *rport;
unsigned long flags;
if (fcport->drport)
qla2x00_rport_del(fcport);
if (fcport->rport)
return;
rport_ids.node_name = wwn_to_u64(fcport->node_name);
rport_ids.port_name = wwn_to_u64(fcport->port_name);
rport_ids.port_id = fcport->d_id.b.domain << 16 |
fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa;
rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
rport = fc_remote_port_add(ha->host, 0, &rport_ids);
fcport->rport = rport = fc_remote_port_add(ha->host, 0, &rport_ids);
if (!rport) {
qla_printk(KERN_WARNING, ha,
"Unable to allocate fc remote port!\n");
return;
}
spin_lock_irqsave(&fcport->rport_lock, flags);
fcport->rport = rport;
spin_lock_irq(fcport->ha->host->host_lock);
*((fc_port_t **)rport->dd_data) = fcport;
spin_unlock_irqrestore(&fcport->rport_lock, flags);
spin_unlock_irq(fcport->ha->host->host_lock);
rport->supported_classes = fcport->supported_classes;
@ -2565,7 +2575,8 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports)
} else if (qla2x00_gnn_id(ha, swl) != QLA_SUCCESS) {
kfree(swl);
swl = NULL;
} else if (qla2x00_gfpn_id(ha, swl) == QLA_SUCCESS) {
} else if (ql2xiidmaenable &&
qla2x00_gfpn_id(ha, swl) == QLA_SUCCESS) {
qla2x00_gpsc(ha, swl);
}
}
@ -3220,7 +3231,8 @@ qla2x00_update_fcports(scsi_qla_host_t *ha)
/* Go with deferred removal of rport references. */
list_for_each_entry(fcport, &ha->fcports, list)
if (fcport->drport)
if (fcport->drport &&
atomic_read(&fcport->state) != FCS_UNCONFIGURED)
qla2x00_rport_del(fcport);
}
@ -3243,6 +3255,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
if (ha->flags.online) {
ha->flags.online = 0;
clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
ha->qla_stats.total_isp_aborts++;
qla_printk(KERN_INFO, ha,
"Performing ISP error recovery - ha= %p.\n", ha);
@ -3283,17 +3296,6 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
ha->isp_abort_cnt = 0;
clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags);
if (ha->eft) {
memset(ha->eft, 0, EFT_SIZE);
rval = qla2x00_enable_eft_trace(ha,
ha->eft_dma, EFT_NUM_BUFFERS);
if (rval) {
qla_printk(KERN_WARNING, ha,
"Unable to reinitialize EFT "
"(%d).\n", rval);
}
}
if (ha->fce) {
ha->flags.fce_enabled = 1;
memset(ha->fce, 0,
@ -3308,6 +3310,17 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
ha->flags.fce_enabled = 0;
}
}
if (ha->eft) {
memset(ha->eft, 0, EFT_SIZE);
rval = qla2x00_enable_eft_trace(ha,
ha->eft_dma, EFT_NUM_BUFFERS);
if (rval) {
qla_printk(KERN_WARNING, ha,
"Unable to reinitialize EFT "
"(%d).\n", rval);
}
}
} else { /* failed the ISP abort */
ha->flags.online = 1;
if (test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) {
@ -4026,8 +4039,8 @@ qla2x00_try_to_stop_firmware(scsi_qla_host_t *ha)
ret = qla2x00_stop_firmware(ha);
for (retries = 5; ret != QLA_SUCCESS && ret != QLA_FUNCTION_TIMEOUT &&
retries ; retries--) {
qla2x00_reset_chip(ha);
if (qla2x00_chip_diag(ha) != QLA_SUCCESS)
ha->isp_ops->reset_chip(ha);
if (ha->isp_ops->chip_diag(ha) != QLA_SUCCESS)
continue;
if (qla2x00_setup_chip(ha) != QLA_SUCCESS)
continue;
@ -4049,7 +4062,7 @@ qla24xx_configure_vhba(scsi_qla_host_t *ha)
rval = qla2x00_fw_ready(ha->parent);
if (rval == QLA_SUCCESS) {
clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
qla2x00_marker(ha->parent, 0, 0, MK_SYNC_ALL);
qla2x00_marker(ha, 0, 0, MK_SYNC_ALL);
}
ha->flags.management_server_logged_in = 0;

View file

@ -454,10 +454,11 @@ qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun,
{
int ret;
unsigned long flags = 0;
scsi_qla_host_t *pha = to_qla_parent(ha);
spin_lock_irqsave(&ha->hardware_lock, flags);
spin_lock_irqsave(&pha->hardware_lock, flags);
ret = __qla2x00_marker(ha, loop_id, lun, type);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
spin_unlock_irqrestore(&pha->hardware_lock, flags);
return (ret);
}
@ -672,7 +673,7 @@ qla24xx_start_scsi(srb_t *sp)
{
int ret, nseg;
unsigned long flags;
scsi_qla_host_t *ha;
scsi_qla_host_t *ha, *pha;
struct scsi_cmnd *cmd;
uint32_t *clr_ptr;
uint32_t index;
@ -686,6 +687,7 @@ qla24xx_start_scsi(srb_t *sp)
/* Setup device pointers. */
ret = 0;
ha = sp->ha;
pha = to_qla_parent(ha);
reg = &ha->iobase->isp24;
cmd = sp->cmd;
/* So we know we haven't pci_map'ed anything yet */
@ -700,7 +702,7 @@ qla24xx_start_scsi(srb_t *sp)
}
/* Acquire ring specific lock */
spin_lock_irqsave(&ha->hardware_lock, flags);
spin_lock_irqsave(&pha->hardware_lock, flags);
/* Check for room in outstanding command list. */
handle = ha->current_outstanding_cmd;
@ -795,14 +797,14 @@ qla24xx_start_scsi(srb_t *sp)
ha->response_ring_ptr->signature != RESPONSE_PROCESSED)
qla24xx_process_response_queue(ha);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
spin_unlock_irqrestore(&pha->hardware_lock, flags);
return QLA_SUCCESS;
queuing_error:
if (tot_dsds)
scsi_dma_unmap(cmd);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
spin_unlock_irqrestore(&pha->hardware_lock, flags);
return QLA_FUNCTION_FAILED;
}

View file

@ -542,10 +542,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
break;
case MBA_PORT_UPDATE: /* Port database update */
/* Only handle SCNs for our Vport index. */
if (ha->parent && ha->vp_idx != (mb[3] & 0xff))
break;
/*
* If PORT UPDATE is global (recieved LIP_OCCURED/LIP_RESET
* event etc. earlier indicating loop is down) then process

View file

@ -918,6 +918,8 @@ qla2x00_get_adapter_id(scsi_qla_host_t *ha, uint16_t *id, uint8_t *al_pa,
rval = qla2x00_mailbox_command(ha, mcp);
if (mcp->mb[0] == MBS_COMMAND_ERROR)
rval = QLA_COMMAND_ERROR;
else if (mcp->mb[0] == MBS_INVALID_COMMAND)
rval = QLA_INVALID_COMMAND;
/* Return data. */
*id = mcp->mb[1];
@ -2161,17 +2163,18 @@ qla24xx_abort_command(scsi_qla_host_t *ha, srb_t *sp)
struct abort_entry_24xx *abt;
dma_addr_t abt_dma;
uint32_t handle;
scsi_qla_host_t *pha = to_qla_parent(ha);
DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
fcport = sp->fcport;
spin_lock_irqsave(&ha->hardware_lock, flags);
spin_lock_irqsave(&pha->hardware_lock, flags);
for (handle = 1; handle < MAX_OUTSTANDING_COMMANDS; handle++) {
if (ha->outstanding_cmds[handle] == sp)
if (pha->outstanding_cmds[handle] == sp)
break;
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
spin_unlock_irqrestore(&pha->hardware_lock, flags);
if (handle == MAX_OUTSTANDING_COMMANDS) {
/* Command not found. */
return QLA_FUNCTION_FAILED;

View file

@ -43,6 +43,7 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha)
set_bit(vp_id, ha->vp_idx_map);
ha->num_vhosts++;
ha->cur_vport_count++;
vha->vp_idx = vp_id;
list_add_tail(&vha->vp_list, &ha->vp_list);
mutex_unlock(&ha->vport_lock);
@ -58,6 +59,7 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha)
mutex_lock(&ha->vport_lock);
vp_id = vha->vp_idx;
ha->num_vhosts--;
ha->cur_vport_count--;
clear_bit(vp_id, ha->vp_idx_map);
list_del(&vha->vp_list);
mutex_unlock(&ha->vport_lock);
@ -103,8 +105,8 @@ qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha)
"loop_id=0x%04x :%x\n",
vha->host_no, fcport->loop_id, fcport->vp_idx));
atomic_set(&fcport->state, FCS_DEVICE_DEAD);
qla2x00_mark_device_lost(vha, fcport, 0, 0);
atomic_set(&fcport->state, FCS_UNCONFIGURED);
}
}
@ -276,7 +278,8 @@ qla2x00_do_dpc_vp(scsi_qla_host_t *vha)
clear_bit(RESET_ACTIVE, &vha->dpc_flags);
}
if (test_and_clear_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) {
if (atomic_read(&vha->vp_state) == VP_ACTIVE &&
test_and_clear_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) {
if (!(test_and_set_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags))) {
qla2x00_loop_resync(vha);
clear_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags);
@ -390,7 +393,6 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
vha->parent = ha;
vha->fc_vport = fc_vport;
vha->device_flags = 0;
vha->instance = num_hosts;
vha->vp_idx = qla24xx_allocate_vp_id(vha);
if (vha->vp_idx > ha->max_npiv_vports) {
DEBUG15(printk("scsi(%ld): Couldn't allocate vp_id.\n",
@ -428,7 +430,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
host->max_cmd_len = MAX_CMDSZ;
host->max_channel = MAX_BUSES - 1;
host->max_lun = MAX_LUNS;
host->unique_id = vha->instance;
host->unique_id = host->host_no;
host->max_id = MAX_TARGETS_2200;
host->transportt = qla2xxx_transport_vport_template;
@ -436,12 +438,6 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
vha->host_no, vha));
vha->flags.init_done = 1;
num_hosts++;
mutex_lock(&ha->vport_lock);
set_bit(vha->vp_idx, ha->vp_idx_map);
ha->cur_vport_count++;
mutex_unlock(&ha->vport_lock);
return vha;

View file

@ -27,7 +27,6 @@ char qla2x00_version_str[40];
*/
static struct kmem_cache *srb_cachep;
int num_hosts;
int ql2xlogintimeout = 20;
module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xlogintimeout,
@ -87,6 +86,13 @@ MODULE_PARM_DESC(ql2xqfullrampup,
"depth for a device after a queue-full condition has been "
"detected. Default is 120 seconds.");
int ql2xiidmaenable=1;
module_param(ql2xiidmaenable, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xiidmaenable,
"Enables iIDMA settings "
"Default is 1 - perform iIDMA. 0 - no iIDMA.");
/*
* SCSI host template entry points
*/
@ -388,7 +394,7 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
}
/* Close window on fcport/rport state-transitioning. */
if (!*(fc_port_t **)rport->dd_data) {
if (fcport->drport) {
cmd->result = DID_IMM_RETRY << 16;
goto qc_fail_command;
}
@ -443,7 +449,7 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
int rval;
scsi_qla_host_t *pha = to_qla_parent(ha);
if (unlikely(pci_channel_offline(ha->pdev))) {
if (unlikely(pci_channel_offline(pha->pdev))) {
cmd->result = DID_REQUEUE << 16;
goto qc24_fail_command;
}
@ -455,7 +461,7 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
}
/* Close window on fcport/rport state-transitioning. */
if (!*(fc_port_t **)rport->dd_data) {
if (fcport->drport) {
cmd->result = DID_IMM_RETRY << 16;
goto qc24_fail_command;
}
@ -617,6 +623,40 @@ qla2x00_wait_for_loop_ready(scsi_qla_host_t *ha)
return (return_status);
}
void
qla2x00_abort_fcport_cmds(fc_port_t *fcport)
{
int cnt;
unsigned long flags;
srb_t *sp;
scsi_qla_host_t *ha = fcport->ha;
scsi_qla_host_t *pha = to_qla_parent(ha);
spin_lock_irqsave(&pha->hardware_lock, flags);
for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
sp = pha->outstanding_cmds[cnt];
if (!sp)
continue;
if (sp->fcport != fcport)
continue;
spin_unlock_irqrestore(&pha->hardware_lock, flags);
if (ha->isp_ops->abort_command(ha, sp)) {
DEBUG2(qla_printk(KERN_WARNING, ha,
"Abort failed -- %lx\n", sp->cmd->serial_number));
} else {
if (qla2x00_eh_wait_on_command(ha, sp->cmd) !=
QLA_SUCCESS)
DEBUG2(qla_printk(KERN_WARNING, ha,
"Abort failed while waiting -- %lx\n",
sp->cmd->serial_number));
}
spin_lock_irqsave(&pha->hardware_lock, flags);
}
spin_unlock_irqrestore(&pha->hardware_lock, flags);
}
static void
qla2x00_block_error_handler(struct scsi_cmnd *cmnd)
{
@ -1073,7 +1113,7 @@ qla2xxx_slave_configure(struct scsi_device *sdev)
else
scsi_deactivate_tcq(sdev, ha->max_q_depth);
rport->dev_loss_tmo = ha->port_down_retry_count + 5;
rport->dev_loss_tmo = ha->port_down_retry_count;
return 0;
}
@ -1629,9 +1669,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
}
host->can_queue = ha->request_q_length + 128;
/* load the F/W, read paramaters, and init the H/W */
ha->instance = num_hosts;
mutex_init(&ha->vport_lock);
init_completion(&ha->mbx_cmd_comp);
complete(&ha->mbx_cmd_comp);
@ -1679,7 +1716,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
host->this_id = 255;
host->cmd_per_lun = 3;
host->unique_id = ha->instance;
host->unique_id = host->host_no;
host->max_cmd_len = MAX_CMDSZ;
host->max_channel = MAX_BUSES - 1;
host->max_lun = MAX_LUNS;
@ -1700,8 +1737,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
ha->flags.init_done = 1;
ha->flags.online = 1;
num_hosts++;
ret = scsi_add_host(host, &pdev->dev);
if (ret)
goto probe_failed;
@ -1813,27 +1848,21 @@ static inline void
qla2x00_schedule_rport_del(struct scsi_qla_host *ha, fc_port_t *fcport,
int defer)
{
unsigned long flags;
struct fc_rport *rport;
scsi_qla_host_t *pha = to_qla_parent(ha);
if (!fcport->rport)
return;
rport = fcport->rport;
if (defer) {
spin_lock_irqsave(&fcport->rport_lock, flags);
spin_lock_irq(ha->host->host_lock);
fcport->drport = rport;
fcport->rport = NULL;
*(fc_port_t **)rport->dd_data = NULL;
spin_unlock_irqrestore(&fcport->rport_lock, flags);
set_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags);
} else {
spin_lock_irqsave(&fcport->rport_lock, flags);
fcport->rport = NULL;
*(fc_port_t **)rport->dd_data = NULL;
spin_unlock_irqrestore(&fcport->rport_lock, flags);
spin_unlock_irq(ha->host->host_lock);
set_bit(FCPORT_UPDATE_NEEDED, &pha->dpc_flags);
qla2xxx_wake_dpc(pha);
} else
fc_remote_port_delete(rport);
}
}
/*
@ -1903,7 +1932,7 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer)
scsi_qla_host_t *pha = to_qla_parent(ha);
list_for_each_entry(fcport, &pha->fcports, list) {
if (ha->vp_idx != 0 && ha->vp_idx != fcport->vp_idx)
if (ha->vp_idx != fcport->vp_idx)
continue;
/*
* No point in marking the device as lost, if the device is
@ -1911,17 +1940,10 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer)
*/
if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD)
continue;
if (atomic_read(&fcport->state) == FCS_ONLINE) {
if (defer)
qla2x00_schedule_rport_del(ha, fcport, defer);
else if (ha->vp_idx == fcport->vp_idx)
qla2x00_schedule_rport_del(ha, fcport, defer);
}
if (atomic_read(&fcport->state) == FCS_ONLINE)
qla2x00_schedule_rport_del(ha, fcport, defer);
atomic_set(&fcport->state, FCS_DEVICE_LOST);
}
if (defer)
qla2xxx_wake_dpc(ha);
}
/*
@ -2156,7 +2178,7 @@ qla2x00_alloc_work(struct scsi_qla_host *ha, enum qla_work_type type,
static int
qla2x00_post_work(struct scsi_qla_host *ha, struct qla_work_evt *e, int locked)
{
unsigned long flags;
unsigned long uninitialized_var(flags);
scsi_qla_host_t *pha = to_qla_parent(ha);
if (!locked)
@ -2313,8 +2335,10 @@ qla2x00_do_dpc(void *data)
ha->host_no));
}
if (test_and_clear_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags))
if (test_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags)) {
qla2x00_update_fcports(ha);
clear_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags);
}
if (test_and_clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) &&
(!(test_and_set_bit(RESET_ACTIVE, &ha->dpc_flags)))) {

View file

@ -869,11 +869,9 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
uint32_t i;
uint32_t *dwptr;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
unsigned long flags;
ret = QLA_SUCCESS;
spin_lock_irqsave(&ha->hardware_lock, flags);
/* Enable flash write. */
WRT_REG_DWORD(&reg->ctrl_status,
RD_REG_DWORD(&reg->ctrl_status) | CSRX_FLASH_ENABLE);
@ -907,7 +905,6 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
WRT_REG_DWORD(&reg->ctrl_status,
RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return ret;
}
@ -2305,6 +2302,51 @@ qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf)
return ret;
}
static int
qla2xxx_is_vpd_valid(uint8_t *pos, uint8_t *end)
{
if (pos >= end || *pos != 0x82)
return 0;
pos += 3 + pos[1];
if (pos >= end || *pos != 0x90)
return 0;
pos += 3 + pos[1];
if (pos >= end || *pos != 0x78)
return 0;
return 1;
}
int
qla2xxx_get_vpd_field(scsi_qla_host_t *ha, char *key, char *str, size_t size)
{
uint8_t *pos = ha->vpd;
uint8_t *end = pos + ha->vpd_size;
int len = 0;
if (!IS_FWI2_CAPABLE(ha) || !qla2xxx_is_vpd_valid(pos, end))
return 0;
while (pos < end && *pos != 0x78) {
len = (*pos == 0x82) ? pos[1] : pos[2];
if (!strncmp(pos, key, strlen(key)))
break;
if (*pos != 0x90 && *pos != 0x91)
pos += len;
pos += 3;
}
if (pos < end - len && *pos != 0x78)
return snprintf(str, size, "%.*s", len, pos + 3);
return 0;
}
static int
qla2xxx_hw_event_store(scsi_qla_host_t *ha, uint32_t *fdata)
{

View file

@ -7,7 +7,7 @@
/*
* Driver version
*/
#define QLA2XXX_VERSION "8.02.01-k4"
#define QLA2XXX_VERSION "8.02.01-k6"
#define QLA_DRIVER_MAJOR_VER 8
#define QLA_DRIVER_MINOR_VER 2

View file

@ -46,6 +46,8 @@ MODULE_PARM_DESC(ql4xextended_error_logging,
int ql4_mod_unload = 0;
#define QL4_DEF_QDEPTH 32
/*
* SCSI host template entry points
*/
@ -1387,7 +1389,7 @@ static int qla4xxx_slave_alloc(struct scsi_device *sdev)
sdev->hostdata = ddb;
sdev->tagged_supported = 1;
scsi_activate_tcq(sdev, sdev->host->can_queue);
scsi_activate_tcq(sdev, QL4_DEF_QDEPTH);
return 0;
}

View file

@ -197,10 +197,42 @@ static void
scsi_pool_free_command(struct scsi_host_cmd_pool *pool,
struct scsi_cmnd *cmd)
{
if (cmd->prot_sdb)
kmem_cache_free(scsi_sdb_cache, cmd->prot_sdb);
kmem_cache_free(pool->sense_slab, cmd->sense_buffer);
kmem_cache_free(pool->cmd_slab, cmd);
}
/**
* scsi_host_alloc_command - internal function to allocate command
* @shost: SCSI host whose pool to allocate from
* @gfp_mask: mask for the allocation
*
* Returns a fully allocated command with sense buffer and protection
* data buffer (where applicable) or NULL on failure
*/
static struct scsi_cmnd *
scsi_host_alloc_command(struct Scsi_Host *shost, gfp_t gfp_mask)
{
struct scsi_cmnd *cmd;
cmd = scsi_pool_alloc_command(shost->cmd_pool, gfp_mask);
if (!cmd)
return NULL;
if (scsi_host_get_prot(shost) >= SHOST_DIX_TYPE0_PROTECTION) {
cmd->prot_sdb = kmem_cache_zalloc(scsi_sdb_cache, gfp_mask);
if (!cmd->prot_sdb) {
scsi_pool_free_command(shost->cmd_pool, cmd);
return NULL;
}
}
return cmd;
}
/**
* __scsi_get_command - Allocate a struct scsi_cmnd
* @shost: host to transmit command
@ -214,7 +246,7 @@ struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask)
struct scsi_cmnd *cmd;
unsigned char *buf;
cmd = scsi_pool_alloc_command(shost->cmd_pool, gfp_mask);
cmd = scsi_host_alloc_command(shost, gfp_mask);
if (unlikely(!cmd)) {
unsigned long flags;
@ -457,7 +489,7 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost)
/*
* Get one backup command for this host.
*/
cmd = scsi_pool_alloc_command(shost->cmd_pool, gfp_mask);
cmd = scsi_host_alloc_command(shost, gfp_mask);
if (!cmd) {
scsi_put_host_cmd_pool(gfp_mask);
shost->cmd_pool = NULL;
@ -902,11 +934,20 @@ void scsi_adjust_queue_depth(struct scsi_device *sdev, int tagged, int tags)
spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
/* Check to see if the queue is managed by the block layer.
* If it is, and we fail to adjust the depth, exit. */
if (blk_queue_tagged(sdev->request_queue) &&
blk_queue_resize_tags(sdev->request_queue, tags) != 0)
goto out;
/*
* Check to see if the queue is managed by the block layer.
* If it is, and we fail to adjust the depth, exit.
*
* Do not resize the tag map if it is a host wide share bqt,
* because the size should be the hosts's can_queue. If there
* is more IO than the LLD's can_queue (so there are not enuogh
* tags) request_fn's host queue ready check will handle it.
*/
if (!sdev->host->bqt) {
if (blk_queue_tagged(sdev->request_queue) &&
blk_queue_resize_tags(sdev->request_queue, tags) != 0)
goto out;
}
sdev->queue_depth = tags;
switch (tagged) {

Some files were not shown because too many files have changed in this diff Show more