aboutsummaryrefslogtreecommitdiff
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/Kconfig4
-rw-r--r--drivers/scsi/aacraid/commctrl.c12
-rw-r--r--drivers/scsi/aacraid/comminit.c2
-rw-r--r--drivers/scsi/aacraid/dpcsup.c2
-rw-r--r--drivers/scsi/arcmsr/arcmsr.h39
-rw-r--r--drivers/scsi/arcmsr/arcmsr_attr.c6
-rw-r--r--drivers/scsi/arcmsr/arcmsr_hba.c205
-rw-r--r--drivers/scsi/arm/scsi.h8
-rw-r--r--drivers/scsi/scsi_lib.c138
-rw-r--r--drivers/scsi/scsi_scan.c3
-rw-r--r--drivers/scsi/scsi_sysfs.c47
-rw-r--r--drivers/scsi/sg.c1
12 files changed, 333 insertions, 134 deletions
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index a5763c6e936..86cf10efb0c 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -172,12 +172,12 @@ config CHR_DEV_SCH
don't need this for those tiny 6-slot cdrom changers. Media
changers are listed as "Type: Medium Changer" in /proc/scsi/scsi.
If you have such hardware and want to use it with linux, say Y
- here. Check <file:Documentation/scsi-changer.txt> for details.
+ here. Check <file:Documentation/scsi/scsi-changer.txt> for details.
If you want to compile this as a module ( = code which can be
inserted in and removed from the running kernel whenever you want),
say M here and read <file:Documentation/kbuild/modules.txt> and
- <file:Documentation/scsi.txt>. The module will be called ch.o.
+ <file:Documentation/scsi/scsi.txt>. The module will be called ch.o.
If unsure, say N.
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index 72b0393b459..1e6d7a9c75b 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -391,7 +391,7 @@ static int close_getadapter_fib(struct aac_dev * dev, void __user *arg)
/*
* Extract the fibctx from the input parameters
*/
- if (fibctx->unique == (u32)(ptrdiff_t)arg) /* We found a winner */
+ if (fibctx->unique == (u32)(uintptr_t)arg) /* We found a winner */
break;
entry = entry->next;
fibctx = NULL;
@@ -590,7 +590,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
}
addr = (u64)upsg->sg[i].addr[0];
addr += ((u64)upsg->sg[i].addr[1]) << 32;
- sg_user[i] = (void __user *)(ptrdiff_t)addr;
+ sg_user[i] = (void __user *)(uintptr_t)addr;
sg_list[i] = p; // save so we can clean up later
sg_indx = i;
@@ -633,7 +633,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
rcode = -ENOMEM;
goto cleanup;
}
- sg_user[i] = (void __user *)(ptrdiff_t)usg->sg[i].addr;
+ sg_user[i] = (void __user *)(uintptr_t)usg->sg[i].addr;
sg_list[i] = p; // save so we can clean up later
sg_indx = i;
@@ -664,7 +664,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
if (actual_fibsize64 == fibsize) {
struct user_sgmap64* usg = (struct user_sgmap64 *)upsg;
for (i = 0; i < upsg->count; i++) {
- u64 addr;
+ uintptr_t addr;
void* p;
/* Does this really need to be GFP_DMA? */
p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA);
@@ -676,7 +676,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
}
addr = (u64)usg->sg[i].addr[0];
addr += ((u64)usg->sg[i].addr[1]) << 32;
- sg_user[i] = (void __user *)(ptrdiff_t)addr;
+ sg_user[i] = (void __user *)addr;
sg_list[i] = p; // save so we can clean up later
sg_indx = i;
@@ -704,7 +704,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
rcode = -ENOMEM;
goto cleanup;
}
- sg_user[i] = (void __user *)(ptrdiff_t)upsg->sg[i].addr;
+ sg_user[i] = (void __user *)(uintptr_t)upsg->sg[i].addr;
sg_list[i] = p; // save so we can clean up later
sg_indx = i;
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index 3009ad8c407..8736813a029 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -110,7 +110,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
/*
* Align the beginning of Headers to commalign
*/
- align = (commalign - ((ptrdiff_t)(base) & (commalign - 1)));
+ align = (commalign - ((uintptr_t)(base) & (commalign - 1)));
base = base + align;
phys = phys + align;
/*
diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c
index fcd25f7d0bc..e6032ffc66a 100644
--- a/drivers/scsi/aacraid/dpcsup.c
+++ b/drivers/scsi/aacraid/dpcsup.c
@@ -254,7 +254,7 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index)
kfree (fib);
return 1;
}
- memcpy(hw_fib, (struct hw_fib *)(((ptrdiff_t)(dev->regs.sa)) +
+ memcpy(hw_fib, (struct hw_fib *)(((uintptr_t)(dev->regs.sa)) +
(index & ~0x00000002L)), sizeof(struct hw_fib));
INIT_LIST_HEAD(&fib->fiblink);
fib->type = FSAFS_NTC_FIB_CONTEXT;
diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h
index ace7a15b413..a67e29f83ae 100644
--- a/drivers/scsi/arcmsr/arcmsr.h
+++ b/drivers/scsi/arcmsr/arcmsr.h
@@ -141,14 +141,14 @@ struct CMD_MESSAGE_FIELD
#define IS_SG64_ADDR 0x01000000 /* bit24 */
struct SG32ENTRY
{
- uint32_t length;
- uint32_t address;
+ __le32 length;
+ __le32 address;
};
struct SG64ENTRY
{
- uint32_t length;
- uint32_t address;
- uint32_t addresshigh;
+ __le32 length;
+ __le32 address;
+ __le32 addresshigh;
};
struct SGENTRY_UNION
{
@@ -339,23 +339,15 @@ struct MessageUnit_B
uint32_t done_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE];
uint32_t postq_index;
uint32_t doneq_index;
- uint32_t *drv2iop_doorbell_reg;
- uint32_t *drv2iop_doorbell_mask_reg;
- uint32_t *iop2drv_doorbell_reg;
- uint32_t *iop2drv_doorbell_mask_reg;
- uint32_t *msgcode_rwbuffer_reg;
- uint32_t *ioctl_wbuffer_reg;
- uint32_t *ioctl_rbuffer_reg;
+ uint32_t __iomem *drv2iop_doorbell_reg;
+ uint32_t __iomem *drv2iop_doorbell_mask_reg;
+ uint32_t __iomem *iop2drv_doorbell_reg;
+ uint32_t __iomem *iop2drv_doorbell_mask_reg;
+ uint32_t __iomem *msgcode_rwbuffer_reg;
+ uint32_t __iomem *ioctl_wbuffer_reg;
+ uint32_t __iomem *ioctl_rbuffer_reg;
};
-struct MessageUnit
-{
- union
- {
- struct MessageUnit_A pmu_A;
- struct MessageUnit_B pmu_B;
- } u;
-};
/*
*******************************************************************************
** Adapter Control Block
@@ -374,7 +366,10 @@ struct AdapterControlBlock
/* Offset is used in making arc cdb physical to virtual calculations */
uint32_t outbound_int_enable;
- struct MessageUnit * pmu;
+ union {
+ struct MessageUnit_A __iomem * pmuA;
+ struct MessageUnit_B * pmuB;
+ };
/* message unit ATU inbound base address0 */
uint32_t acb_flags;
@@ -558,7 +553,7 @@ struct SENSE_DATA
extern void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *);
extern void arcmsr_iop_message_read(struct AdapterControlBlock *);
-extern struct QBUFFER *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *);
+extern struct QBUFFER __iomem *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *);
extern struct class_device_attribute *arcmsr_host_attrs[];
extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *);
void arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb);
diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c
index d04d1aa28fa..7d7b0a55427 100644
--- a/drivers/scsi/arcmsr/arcmsr_attr.c
+++ b/drivers/scsi/arcmsr/arcmsr_attr.c
@@ -85,13 +85,13 @@ static ssize_t arcmsr_sysfs_iop_message_read(struct kobject *kobj,
allxfer_len++;
}
if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
- struct QBUFFER *prbuffer;
- uint8_t *iop_data;
+ struct QBUFFER __iomem *prbuffer;
+ uint8_t __iomem *iop_data;
int32_t iop_len;
acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
prbuffer = arcmsr_get_iop_rqbuffer(acb);
- iop_data = (uint8_t *)prbuffer->data;
+ iop_data = prbuffer->data;
iop_len = readl(&prbuffer->data_len);
while (iop_len > 0) {
acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data);
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index f7a252885a5..d466a2dac1d 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -236,18 +236,22 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
uint32_t intmask_org;
int i, j;
- acb->pmu = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
- if (!acb->pmu) {
+ acb->pmuA = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
+ if (!acb->pmuA) {
printk(KERN_NOTICE "arcmsr%d: memory mapping region fail \n",
acb->host->host_no);
+ return -ENOMEM;
}
dma_coherent = dma_alloc_coherent(&pdev->dev,
ARCMSR_MAX_FREECCB_NUM *
sizeof (struct CommandControlBlock) + 0x20,
&dma_coherent_handle, GFP_KERNEL);
- if (!dma_coherent)
+
+ if (!dma_coherent) {
+ iounmap(acb->pmuA);
return -ENOMEM;
+ }
acb->dma_coherent = dma_coherent;
acb->dma_coherent_handle = dma_coherent_handle;
@@ -287,7 +291,7 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
struct pci_dev *pdev = acb->pdev;
struct MessageUnit_B *reg;
- void *mem_base0, *mem_base1;
+ void __iomem *mem_base0, *mem_base1;
void *dma_coherent;
dma_addr_t dma_coherent_handle, dma_addr;
uint32_t intmask_org;
@@ -328,25 +332,28 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
reg = (struct MessageUnit_B *)(dma_coherent +
ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock));
- acb->pmu = (struct MessageUnit *)reg;
+ acb->pmuB = reg;
mem_base0 = ioremap(pci_resource_start(pdev, 0),
pci_resource_len(pdev, 0));
+ if (!mem_base0)
+ goto out;
+
mem_base1 = ioremap(pci_resource_start(pdev, 2),
pci_resource_len(pdev, 2));
- reg->drv2iop_doorbell_reg = (uint32_t *)((char *)mem_base0 +
- ARCMSR_DRV2IOP_DOORBELL);
- reg->drv2iop_doorbell_mask_reg = (uint32_t *)((char *)mem_base0 +
- ARCMSR_DRV2IOP_DOORBELL_MASK);
- reg->iop2drv_doorbell_reg = (uint32_t *)((char *)mem_base0 +
- ARCMSR_IOP2DRV_DOORBELL);
- reg->iop2drv_doorbell_mask_reg = (uint32_t *)((char *)mem_base0 +
- ARCMSR_IOP2DRV_DOORBELL_MASK);
- reg->ioctl_wbuffer_reg = (uint32_t *)((char *)mem_base1 +
- ARCMSR_IOCTL_WBUFFER);
- reg->ioctl_rbuffer_reg = (uint32_t *)((char *)mem_base1 +
- ARCMSR_IOCTL_RBUFFER);
- reg->msgcode_rwbuffer_reg = (uint32_t *)((char *)mem_base1 +
- ARCMSR_MSGCODE_RWBUFFER);
+ if (!mem_base1) {
+ iounmap(mem_base0);
+ goto out;
+ }
+
+ reg->drv2iop_doorbell_reg = mem_base0 + ARCMSR_DRV2IOP_DOORBELL;
+ reg->drv2iop_doorbell_mask_reg = mem_base0 +
+ ARCMSR_DRV2IOP_DOORBELL_MASK;
+ reg->iop2drv_doorbell_reg = mem_base0 + ARCMSR_IOP2DRV_DOORBELL;
+ reg->iop2drv_doorbell_mask_reg = mem_base0 +
+ ARCMSR_IOP2DRV_DOORBELL_MASK;
+ reg->ioctl_wbuffer_reg = mem_base1 + ARCMSR_IOCTL_WBUFFER;
+ reg->ioctl_rbuffer_reg = mem_base1 + ARCMSR_IOCTL_RBUFFER;
+ reg->msgcode_rwbuffer_reg = mem_base1 + ARCMSR_MSGCODE_RWBUFFER;
acb->vir2phy_offset = (unsigned long)ccb_tmp -(unsigned long)dma_addr;
for (i = 0; i < ARCMSR_MAX_TARGETID; i++)
@@ -362,6 +369,12 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
break;
}
return 0;
+
+out:
+ dma_free_coherent(&acb->pdev->dev,
+ ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock) + 0x20,
+ acb->dma_coherent, acb->dma_coherent_handle);
+ return -ENOMEM;
}
static int arcmsr_probe(struct pci_dev *pdev,
@@ -454,7 +467,6 @@ static int arcmsr_probe(struct pci_dev *pdev,
free_irq(pdev->irq, acb);
out_free_ccb_pool:
arcmsr_free_ccb_pool(acb);
- iounmap(acb->pmu);
out_release_regions:
pci_release_regions(pdev);
out_host_put:
@@ -467,7 +479,7 @@ static int arcmsr_probe(struct pci_dev *pdev,
static uint8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb)
{
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
uint32_t Index;
uint8_t Retries = 0x00;
@@ -488,7 +500,7 @@ static uint8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb)
static uint8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb)
{
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
uint32_t Index;
uint8_t Retries = 0x00;
@@ -509,7 +521,7 @@ static uint8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb)
static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb)
{
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, &reg->inbound_msgaddr0);
if (arcmsr_hba_wait_msgint_ready(acb))
@@ -520,7 +532,7 @@ static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb)
static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb)
{
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
writel(ARCMSR_MESSAGE_ABORT_CMD, reg->drv2iop_doorbell_reg);
if (arcmsr_hbb_wait_msgint_ready(acb))
@@ -566,7 +578,7 @@ static void arcmsr_ccb_complete(struct CommandControlBlock *ccb, int stand_flag)
static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb)
{
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
int retry_count = 30;
writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, &reg->inbound_msgaddr0);
@@ -583,7 +595,7 @@ static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb)
static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb)
{
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
int retry_count = 30;
writel(ARCMSR_MESSAGE_FLUSH_CACHE, reg->drv2iop_doorbell_reg);
@@ -637,7 +649,7 @@ static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb)
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A : {
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
orig_mask = readl(&reg->outbound_intmask)|\
ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE;
writel(orig_mask|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, \
@@ -646,7 +658,7 @@ static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb)
break;
case ACB_ADAPTER_TYPE_B : {
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
orig_mask = readl(reg->iop2drv_doorbell_mask_reg) & \
(~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE);
writel(0, reg->iop2drv_doorbell_mask_reg);
@@ -748,14 +760,13 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb)
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
- struct MessageUnit_A __iomem *reg = \
- (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
uint32_t outbound_intstatus;
- outbound_intstatus = readl(&reg->outbound_intstatus) & \
+ outbound_intstatus = readl(&reg->outbound_intstatus) &
acb->outbound_int_enable;
/*clear and abort all outbound posted Q*/
writel(outbound_intstatus, &reg->outbound_intstatus);/*clear interrupt*/
- while (((flag_ccb = readl(&reg->outbound_queueport)) != 0xFFFFFFFF) \
+ while (((flag_ccb = readl(&reg->outbound_queueport)) != 0xFFFFFFFF)
&& (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) {
arcmsr_drain_donequeue(acb, flag_ccb);
}
@@ -763,7 +774,7 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb)
break;
case ACB_ADAPTER_TYPE_B: {
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
/*clear all outbound posted Q*/
for (i = 0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) {
if ((flag_ccb = readl(&reg->done_qbuffer[i])) != 0) {
@@ -816,7 +827,6 @@ static void arcmsr_remove(struct pci_dev *pdev)
}
free_irq(pdev->irq, acb);
- iounmap(acb->pmu);
arcmsr_free_ccb_pool(acb);
pci_release_regions(pdev);
@@ -859,7 +869,7 @@ static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, \
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A : {
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
mask = intmask_org & ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE |
ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE);
writel(mask, &reg->outbound_intmask);
@@ -868,7 +878,7 @@ static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, \
break;
case ACB_ADAPTER_TYPE_B : {
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
mask = intmask_org | (ARCMSR_IOP2DRV_DATA_WRITE_OK | \
ARCMSR_IOP2DRV_DATA_READ_OK | ARCMSR_IOP2DRV_CDB_DONE);
writel(mask, reg->iop2drv_doorbell_mask_reg);
@@ -882,7 +892,7 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb,
{
struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb;
int8_t *psge = (int8_t *)&arcmsr_cdb->u;
- uint32_t address_lo, address_hi;
+ __le32 address_lo, address_hi;
int arccdbsize = 0x30;
int nseg;
@@ -900,7 +910,8 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb,
BUG_ON(nseg < 0);
if (nseg) {
- int length, i, cdb_sgcount = 0;
+ __le32 length;
+ int i, cdb_sgcount = 0;
struct scatterlist *sg;
/* map stor port SG list to our iop SG List. */
@@ -921,7 +932,7 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb,
pdma_sg->addresshigh = address_hi;
pdma_sg->address = address_lo;
- pdma_sg->length = length|IS_SG64_ADDR;
+ pdma_sg->length = length|cpu_to_le32(IS_SG64_ADDR);
psge += sizeof (struct SG64ENTRY);
arccdbsize += sizeof (struct SG64ENTRY);
}
@@ -947,7 +958,7 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
- struct MessageUnit_A *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
if (arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE)
writel(cdb_shifted_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE,
@@ -959,7 +970,7 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr
break;
case ACB_ADAPTER_TYPE_B: {
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
uint32_t ending_index, index = reg->postq_index;
ending_index = ((index + 1) % ARCMSR_MAX_HBB_POSTQUEUE);
@@ -982,7 +993,7 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr
static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb)
{
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
writel(ARCMSR_INBOUND_MESG0_STOP_BGRB, &reg->inbound_msgaddr0);
@@ -995,7 +1006,7 @@ static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb)
static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb)
{
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
writel(ARCMSR_MESSAGE_STOP_BGRB, reg->drv2iop_doorbell_reg);
@@ -1023,6 +1034,17 @@ static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb)
static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb)
{
+ switch (acb->adapter_type) {
+ case ACB_ADAPTER_TYPE_A: {
+ iounmap(acb->pmuA);
+ break;
+ }
+ case ACB_ADAPTER_TYPE_B: {
+ struct MessageUnit_B *reg = acb->pmuB;
+ iounmap(reg->drv2iop_doorbell_reg - ARCMSR_DRV2IOP_DOORBELL);
+ iounmap(reg->ioctl_wbuffer_reg - ARCMSR_IOCTL_WBUFFER);
+ }
+ }
dma_free_coherent(&acb->pdev->dev,
ARCMSR_MAX_FREECCB_NUM * sizeof (struct CommandControlBlock) + 0x20,
acb->dma_coherent,
@@ -1033,13 +1055,13 @@ void arcmsr_iop_message_read(struct AdapterControlBlock *acb)
{
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, &reg->inbound_doorbell);
}
break;
case ACB_ADAPTER_TYPE_B: {
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
writel(ARCMSR_DRV2IOP_DATA_READ_OK, reg->drv2iop_doorbell_reg);
}
break;
@@ -1050,7 +1072,7 @@ static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb)
{
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
/*
** push inbound doorbell tell iop, driver data write ok
** and wait reply on next hwinterrupt for next Qbuffer post
@@ -1060,7 +1082,7 @@ static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb)
break;
case ACB_ADAPTER_TYPE_B: {
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
/*
** push inbound doorbell tell iop, driver data write ok
** and wait reply on next hwinterrupt for next Qbuffer post
@@ -1071,41 +1093,41 @@ static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb)
}
}
-struct QBUFFER *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *acb)
+struct QBUFFER __iomem *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *acb)
{
- static struct QBUFFER *qbuffer;
+ struct QBUFFER __iomem *qbuffer = NULL;
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
- qbuffer = (struct QBUFFER __iomem *) &reg->message_rbuffer;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
+ qbuffer = (struct QBUFFER __iomem *)&reg->message_rbuffer;
}
break;
case ACB_ADAPTER_TYPE_B: {
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
- qbuffer = (struct QBUFFER __iomem *) reg->ioctl_rbuffer_reg;
+ struct MessageUnit_B *reg = acb->pmuB;
+ qbuffer = (struct QBUFFER __iomem *)reg->ioctl_rbuffer_reg;
}
break;
}
return qbuffer;
}
-static struct QBUFFER *arcmsr_get_iop_wqbuffer(struct AdapterControlBlock *acb)
+static struct QBUFFER __iomem *arcmsr_get_iop_wqbuffer(struct AdapterControlBlock *acb)
{
- static struct QBUFFER *pqbuffer;
+ struct QBUFFER __iomem *pqbuffer = NULL;
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
- pqbuffer = (struct QBUFFER *) &reg->message_wbuffer;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
+ pqbuffer = (struct QBUFFER __iomem *) &reg->message_wbuffer;
}
break;
case ACB_ADAPTER_TYPE_B: {
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
pqbuffer = (struct QBUFFER __iomem *)reg->ioctl_wbuffer_reg;
}
break;
@@ -1115,15 +1137,15 @@ static struct QBUFFER *arcmsr_get_iop_wqbuffer(struct AdapterControlBlock *acb)
static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb)
{
- struct QBUFFER *prbuffer;
+ struct QBUFFER __iomem *prbuffer;
struct QBUFFER *pQbuffer;
- uint8_t *iop_data;
+ uint8_t __iomem *iop_data;
int32_t my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex;
rqbuf_lastindex = acb->rqbuf_lastindex;
rqbuf_firstindex = acb->rqbuf_firstindex;
prbuffer = arcmsr_get_iop_rqbuffer(acb);
- iop_data = (uint8_t *)prbuffer->data;
+ iop_data = (uint8_t __iomem *)prbuffer->data;
iop_len = prbuffer->data_len;
my_empty_len = (rqbuf_firstindex - rqbuf_lastindex -1)&(ARCMSR_MAX_QBUFFER -1);
@@ -1151,8 +1173,8 @@ static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb)
acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED;
if (acb->wqbuf_firstindex != acb->wqbuf_lastindex) {
uint8_t *pQbuffer;
- struct QBUFFER *pwbuffer;
- uint8_t *iop_data;
+ struct QBUFFER __iomem *pwbuffer;
+ uint8_t __iomem *iop_data;
int32_t allxfer_len = 0;
acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED);
@@ -1181,7 +1203,7 @@ static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb)
static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb)
{
uint32_t outbound_doorbell;
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
outbound_doorbell = readl(&reg->outbound_doorbell);
writel(outbound_doorbell, &reg->outbound_doorbell);
@@ -1197,7 +1219,7 @@ static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb)
static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb)
{
uint32_t flag_ccb;
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
while ((flag_ccb = readl(&reg->outbound_queueport)) != 0xFFFFFFFF) {
arcmsr_drain_donequeue(acb, flag_ccb);
@@ -1208,7 +1230,7 @@ static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb)
{
uint32_t index;
uint32_t flag_ccb;
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
index = reg->doneq_index;
@@ -1224,7 +1246,7 @@ static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb)
static int arcmsr_handle_hba_isr(struct AdapterControlBlock *acb)
{
uint32_t outbound_intstatus;
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
outbound_intstatus = readl(&reg->outbound_intstatus) & \
acb->outbound_int_enable;
@@ -1244,7 +1266,7 @@ static int arcmsr_handle_hba_isr(struct AdapterControlBlock *acb)
static int arcmsr_handle_hbb_isr(struct AdapterControlBlock *acb)
{
uint32_t outbound_doorbell;
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
outbound_doorbell = readl(reg->iop2drv_doorbell_reg) & \
acb->outbound_int_enable;
@@ -1305,8 +1327,8 @@ void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb)
{
int32_t wqbuf_firstindex, wqbuf_lastindex;
uint8_t *pQbuffer;
- struct QBUFFER *pwbuffer;
- uint8_t *iop_data;
+ struct QBUFFER __iomem *pwbuffer;
+ uint8_t __iomem *iop_data;
int32_t allxfer_len = 0;
pwbuffer = arcmsr_get_iop_wqbuffer(acb);
@@ -1380,13 +1402,13 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \
}
if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
- struct QBUFFER *prbuffer;
- uint8_t *iop_data;
+ struct QBUFFER __iomem *prbuffer;
+ uint8_t __iomem *iop_data;
int32_t iop_len;
acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
prbuffer = arcmsr_get_iop_rqbuffer(acb);
- iop_data = (uint8_t *)prbuffer->data;
+ iop_data = prbuffer->data;
iop_len = readl(&prbuffer->data_len);
while (iop_len > 0) {
acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data);
@@ -1669,11 +1691,11 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd,
static void arcmsr_get_hba_config(struct AdapterControlBlock *acb)
{
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
char *acb_firm_model = acb->firm_model;
char *acb_firm_version = acb->firm_version;
- char *iop_firm_model = (char *) (&reg->message_rwbuffer[15]);
- char *iop_firm_version = (char *) (&reg->message_rwbuffer[17]);
+ char __iomem *iop_firm_model = (char __iomem *)(&reg->message_rwbuffer[15]);
+ char __iomem *iop_firm_version = (char __iomem *)(&reg->message_rwbuffer[17]);
int count;
writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, &reg->inbound_msgaddr0);
@@ -1710,13 +1732,13 @@ static void arcmsr_get_hba_config(struct AdapterControlBlock *acb)
static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb)
{
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
- uint32_t *lrwbuffer = reg->msgcode_rwbuffer_reg;
+ struct MessageUnit_B *reg = acb->pmuB;
+ uint32_t __iomem *lrwbuffer = reg->msgcode_rwbuffer_reg;
char *acb_firm_model = acb->firm_model;
char *acb_firm_version = acb->firm_version;
- char *iop_firm_model = (char *) (&lrwbuffer[15]);
+ char __iomem *iop_firm_model = (char __iomem *)(&lrwbuffer[15]);
/*firm_model,15,60-67*/
- char *iop_firm_version = (char *) (&lrwbuffer[17]);
+ char __iomem *iop_firm_version = (char __iomem *)(&lrwbuffer[17]);
/*firm_version,17,68-83*/
int count;
@@ -1777,7 +1799,7 @@ static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb)
static void arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb,
struct CommandControlBlock *poll_ccb)
{
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
struct CommandControlBlock *ccb;
uint32_t flag_ccb, outbound_intstatus, poll_ccb_done = 0, poll_count = 0;
@@ -1826,7 +1848,7 @@ static void arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb,
static void arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, \
struct CommandControlBlock *poll_ccb)
{
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
struct CommandControlBlock *ccb;
uint32_t flag_ccb, poll_ccb_done = 0, poll_count = 0;
int index;
@@ -1918,8 +1940,7 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb)
case ACB_ADAPTER_TYPE_A: {
if (ccb_phyaddr_hi32 != 0) {
- struct MessageUnit_A __iomem *reg = \
- (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
uint32_t intmask_org;
intmask_org = arcmsr_disable_outbound_ints(acb);
writel(ARCMSR_SIGNATURE_SET_CONFIG, \
@@ -1940,9 +1961,9 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb)
case ACB_ADAPTER_TYPE_B: {
unsigned long post_queue_phyaddr;
- uint32_t *rwbuffer;
+ uint32_t __iomem *rwbuffer;
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
uint32_t intmask_org;
intmask_org = arcmsr_disable_outbound_ints(acb);
reg->postq_index = 0;
@@ -1994,7 +2015,7 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb)
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
do {
firmware_state = readl(&reg->outbound_msgaddr1);
} while ((firmware_state & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0);
@@ -2002,7 +2023,7 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb)
break;
case ACB_ADAPTER_TYPE_B: {
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
do {
firmware_state = readl(reg->iop2drv_doorbell_reg);
} while ((firmware_state & ARCMSR_MESSAGE_FIRMWARE_OK) == 0);
@@ -2013,7 +2034,7 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb)
static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb)
{
- struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
acb->acb_flags |= ACB_F_MSG_START_BGRB;
writel(ARCMSR_INBOUND_MESG0_START_BGRB, &reg->inbound_msgaddr0);
if (arcmsr_hba_wait_msgint_ready(acb)) {
@@ -2024,7 +2045,7 @@ static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb)
static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb)
{
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
acb->acb_flags |= ACB_F_MSG_START_BGRB;
writel(ARCMSR_MESSAGE_START_BGRB, reg->drv2iop_doorbell_reg);
if (arcmsr_hbb_wait_msgint_ready(acb)) {
@@ -2049,7 +2070,7 @@ static void arcmsr_clear_doorbell_queue_buffer(struct AdapterControlBlock *acb)
{
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
- struct MessageUnit_A *reg = (struct MessageUnit_A *)acb->pmu;
+ struct MessageUnit_A __iomem *reg = acb->pmuA;
uint32_t outbound_doorbell;
/* empty doorbell Qbuffer if door bell ringed */
outbound_doorbell = readl(&reg->outbound_doorbell);
@@ -2060,7 +2081,7 @@ static void arcmsr_clear_doorbell_queue_buffer(struct AdapterControlBlock *acb)
break;
case ACB_ADAPTER_TYPE_B: {
- struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu;
+ struct MessageUnit_B *reg = acb->pmuB;
/*clear interrupt and message state*/
writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN, reg->iop2drv_doorbell_reg);
writel(ARCMSR_DRV2IOP_DATA_READ_OK, reg->drv2iop_doorbell_reg);
diff --git a/drivers/scsi/arm/scsi.h b/drivers/scsi/arm/scsi.h
index 21ba57155be..bb6550e3192 100644
--- a/drivers/scsi/arm/scsi.h
+++ b/drivers/scsi/arm/scsi.h
@@ -38,9 +38,7 @@ static inline int next_SCp(struct scsi_pointer *SCp)
if (ret) {
SCp->buffer++;
SCp->buffers_residual--;
- SCp->ptr = (char *)
- (page_address(SCp->buffer->page) +
- SCp->buffer->offset);
+ SCp->ptr = sg_virt(SCp->buffer);
SCp->this_residual = SCp->buffer->length;
} else {
SCp->ptr = NULL;
@@ -76,9 +74,7 @@ static inline void init_SCp(struct scsi_cmnd *SCpnt)
SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer;
SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;
- SCpnt->SCp.ptr = (char *)
- (page_address(SCpnt->SCp.buffer->page) +
- SCpnt->SCp.buffer->offset);
+ SCpnt->SCp.ptr = sg_virt(SCpnt->SCp.buffer);
SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
SCpnt->SCp.phase = SCpnt->request_bufflen;
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 61fdaf02f25..0e81e4cf887 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -785,7 +785,7 @@ struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask)
* end-of-list
*/
if (!left)
- sg_mark_end(sgl, this);
+ sg_mark_end(&sgl[this - 1]);
/*
* don't allow subsequent mempool allocs to sleep, it would
@@ -2115,6 +2115,142 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state)
EXPORT_SYMBOL(scsi_device_set_state);
/**
+ * sdev_evt_emit - emit a single SCSI device uevent
+ * @sdev: associated SCSI device
+ * @evt: event to emit
+ *
+ * Send a single uevent (scsi_event) to the associated scsi_device.
+ */
+static void scsi_evt_emit(struct scsi_device *sdev, struct scsi_event *evt)
+{
+ int idx = 0;
+ char *envp[3];
+
+ switch (evt->evt_type) {
+ case SDEV_EVT_MEDIA_CHANGE:
+ envp[idx++] = "SDEV_MEDIA_CHANGE=1";
+ break;
+
+ default:
+ /* do nothing */
+ break;
+ }
+
+ envp[idx++] = NULL;
+
+ kobject_uevent_env(&sdev->sdev_gendev.kobj, KOBJ_CHANGE, envp);
+}
+
+/**
+ * sdev_evt_thread - send a uevent for each scsi event
+ * @work: work struct for scsi_device
+ *
+ * Dispatch queued events to their associated scsi_device kobjects
+ * as uevents.
+ */
+void scsi_evt_thread(struct work_struct *work)
+{
+ struct scsi_device *sdev;
+ LIST_HEAD(event_list);
+
+ sdev = container_of(work, struct scsi_device, event_work);
+
+ while (1) {
+ struct scsi_event *evt;
+ struct list_head *this, *tmp;
+ unsigned long flags;
+
+ spin_lock_irqsave(&sdev->list_lock, flags);
+ list_splice_init(&sdev->event_list, &event_list);
+ spin_unlock_irqrestore(&sdev->list_lock, flags);
+
+ if (list_empty(&event_list))
+ break;
+
+ list_for_each_safe(this, tmp, &event_list) {
+ evt = list_entry(this, struct scsi_event, node);
+ list_del(&evt->node);
+ scsi_evt_emit(sdev, evt);
+ kfree(evt);
+ }
+ }
+}
+
+/**
+ * sdev_evt_send - send asserted event to uevent thread
+ * @sdev: scsi_device event occurred on
+ * @evt: event to send
+ *
+ * Assert scsi device event asynchronously.
+ */
+void sdev_evt_send(struct scsi_device *sdev, struct scsi_event *evt)
+{
+ unsigned long flags;
+
+ if (!test_bit(evt->evt_type, sdev->supported_events)) {
+ kfree(evt);
+ return;
+ }
+
+ spin_lock_irqsave(&sdev->list_lock, flags);
+ list_add_tail(&evt->node, &sdev->event_list);
+ schedule_work(&sdev->event_work);
+ spin_unlock_irqrestore(&sdev->list_lock, flags);
+}
+EXPORT_SYMBOL_GPL(sdev_evt_send);
+
+/**
+ * sdev_evt_alloc - allocate a new scsi event
+ * @evt_type: type of event to allocate
+ * @gfpflags: GFP flags for allocation
+ *
+ * Allocates and returns a new scsi_event.
+ */
+struct scsi_event *sdev_evt_alloc(enum scsi_device_event evt_type,
+ gfp_t gfpflags)
+{
+ struct scsi_event *evt = kzalloc(sizeof(struct scsi_event), gfpflags);
+ if (!evt)
+ return NULL;
+
+ evt->evt_type = evt_type;
+ INIT_LIST_HEAD(&evt->node);
+
+ /* evt_type-specific initialization, if any */
+ switch (evt_type) {
+ case SDEV_EVT_MEDIA_CHANGE:
+ default:
+ /* do nothing */
+ break;
+ }
+
+ return evt;
+}
+EXPORT_SYMBOL_GPL(sdev_evt_alloc);
+
+/**
+ * sdev_evt_send_simple - send asserted event to uevent thread
+ * @sdev: scsi_device event occurred on
+ * @evt_type: type of event to send
+ * @gfpflags: GFP flags for allocation
+ *
+ * Assert scsi device event asynchronously, given an event type.
+ */
+void sdev_evt_send_simple(struct scsi_device *sdev,
+ enum scsi_device_event evt_type, gfp_t gfpflags)
+{
+ struct scsi_event *evt = sdev_evt_alloc(evt_type, gfpflags);
+ if (!evt) {
+ sdev_printk(KERN_ERR, sdev, "event %d eaten due to OOM\n",
+ evt_type);
+ return;
+ }
+
+ sdev_evt_send(sdev, evt);
+}
+EXPORT_SYMBOL_GPL(sdev_evt_send_simple);
+
+/**
* scsi_device_quiesce - Block user issued commands.
* @sdev: scsi device to quiesce.
*
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index b53c5f67e37..40ea71cd2ca 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -236,6 +236,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
struct scsi_device *sdev;
int display_failure_msg = 1, ret;
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ extern void scsi_evt_thread(struct work_struct *work);
sdev = kzalloc(sizeof(*sdev) + shost->transportt->device_size,
GFP_ATOMIC);
@@ -254,7 +255,9 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
INIT_LIST_HEAD(&sdev->same_target_siblings);
INIT_LIST_HEAD(&sdev->cmd_list);
INIT_LIST_HEAD(&sdev->starved_entry);
+ INIT_LIST_HEAD(&sdev->event_list);
spin_lock_init(&sdev->list_lock);
+ INIT_WORK(&sdev->event_work, scsi_evt_thread);
sdev->sdev_gendev.parent = get_device(&starget->dev);
sdev->sdev_target = starget;
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index d531ceeb0d8..f374fdcb681 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -268,6 +268,7 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work)
struct scsi_device *sdev;
struct device *parent;
struct scsi_target *starget;
+ struct list_head *this, *tmp;
unsigned long flags;
sdev = container_of(work, struct scsi_device, ew.work);
@@ -282,6 +283,16 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work)
list_del(&sdev->starved_entry);
spin_unlock_irqrestore(sdev->host->host_lock, flags);
+ cancel_work_sync(&sdev->event_work);
+
+ list_for_each_safe(this, tmp, &sdev->event_list) {
+ struct scsi_event *evt;
+
+ evt = list_entry(this, struct scsi_event, node);
+ list_del(&evt->node);
+ kfree(evt);
+ }
+
if (sdev->request_queue) {
sdev->request_queue->queuedata = NULL;
/* user context needed to free queue */
@@ -614,6 +625,41 @@ sdev_show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
}
static DEVICE_ATTR(modalias, S_IRUGO, sdev_show_modalias, NULL);
+#define DECLARE_EVT_SHOW(name, Cap_name) \
+static ssize_t \
+sdev_show_evt_##name(struct device *dev, struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct scsi_device *sdev = to_scsi_device(dev); \
+ int val = test_bit(SDEV_EVT_##Cap_name, sdev->supported_events);\
+ return snprintf(buf, 20, "%d\n", val); \
+}
+
+#define DECLARE_EVT_STORE(name, Cap_name) \
+static ssize_t \
+sdev_store_evt_##name(struct device *dev, struct device_attribute *attr, \
+ const char *buf, size_t count) \
+{ \
+ struct scsi_device *sdev = to_scsi_device(dev); \
+ int val = simple_strtoul(buf, NULL, 0); \
+ if (val == 0) \
+ clear_bit(SDEV_EVT_##Cap_name, sdev->supported_events); \
+ else if (val == 1) \
+ set_bit(SDEV_EVT_##Cap_name, sdev->supported_events); \
+ else \
+ return -EINVAL; \
+ return count; \
+}
+
+#define DECLARE_EVT(name, Cap_name) \
+ DECLARE_EVT_SHOW(name, Cap_name) \
+ DECLARE_EVT_STORE(name, Cap_name) \
+ static DEVICE_ATTR(evt_##name, S_IRUGO, sdev_show_evt_##name, \
+ sdev_store_evt_##name);
+#define REF_EVT(name) &dev_attr_evt_##name.attr
+
+DECLARE_EVT(media_change, MEDIA_CHANGE)
+
/* Default template for device attributes. May NOT be modified */
static struct attribute *scsi_sdev_attrs[] = {
&dev_attr_device_blocked.attr,
@@ -631,6 +677,7 @@ static struct attribute *scsi_sdev_attrs[] = {
&dev_attr_iodone_cnt.attr,
&dev_attr_ioerr_cnt.attr,
&dev_attr_modalias.attr,
+ REF_EVT(media_change),
NULL
};
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index b5fa4f09138..f1871ea0404 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1652,6 +1652,7 @@ sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, int tablesize)
schp->buffer = kzalloc(sg_bufflen, gfp_flags);
if (!schp->buffer)
return -ENOMEM;
+ sg_init_table(schp->buffer, tablesize);
schp->sglist_len = sg_bufflen;
return tablesize; /* number of scat_gath elements allocated */
}