Commit 3ffd6c5a authored by Raghava Aditya Renukunta's avatar Raghava Aditya Renukunta Committed by Martin K. Petersen

scsi: aacraid: Added support for response path

This patch enables the driver to actually process the I/O, or srb replies
from adapter. In addition to any HBA1000 or SmartIOC2000 adapter events.
Signed-off-by: default avatarRaghava Aditya Renukunta <raghavaaditya.renukunta@microsemi.com>
Signed-off-by: default avatarDave Carroll <David.Carroll@microsemi.com>
Reviewed-by: default avatarJohannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 4ec57fb4
...@@ -329,7 +329,7 @@ static inline int aac_valid_context(struct scsi_cmnd *scsicmd, ...@@ -329,7 +329,7 @@ static inline int aac_valid_context(struct scsi_cmnd *scsicmd,
} }
scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
device = scsicmd->device; device = scsicmd->device;
if (unlikely(!device || !scsi_device_online(device))) { if (unlikely(!device)) {
dprintk((KERN_WARNING "aac_valid_context: scsi device corrupt\n")); dprintk((KERN_WARNING "aac_valid_context: scsi device corrupt\n"));
aac_fib_complete(fibptr); aac_fib_complete(fibptr);
return 0; return 0;
...@@ -475,16 +475,26 @@ int aac_get_containers(struct aac_dev *dev) ...@@ -475,16 +475,26 @@ int aac_get_containers(struct aac_dev *dev)
if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS) if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS)
maximum_num_containers = MAXIMUM_NUM_CONTAINERS; maximum_num_containers = MAXIMUM_NUM_CONTAINERS;
fsa_dev_ptr = kzalloc(sizeof(*fsa_dev_ptr) * maximum_num_containers, if (dev->fsa_dev == NULL ||
GFP_KERNEL); dev->maximum_num_containers != maximum_num_containers) {
if (!fsa_dev_ptr)
return -ENOMEM; fsa_dev_ptr = dev->fsa_dev;
dev->fsa_dev = fsa_dev_ptr; dev->fsa_dev = kcalloc(maximum_num_containers,
dev->maximum_num_containers = maximum_num_containers; sizeof(*fsa_dev_ptr), GFP_KERNEL);
for (index = 0; index < dev->maximum_num_containers; ) { kfree(fsa_dev_ptr);
fsa_dev_ptr[index].devname[0] = '\0'; fsa_dev_ptr = NULL;
if (!dev->fsa_dev)
return -ENOMEM;
dev->maximum_num_containers = maximum_num_containers;
}
for (index = 0; index < dev->maximum_num_containers; index++) {
dev->fsa_dev[index].devname[0] = '\0';
dev->fsa_dev[index].valid = 0;
status = aac_probe_container(dev, index); status = aac_probe_container(dev, index);
...@@ -492,12 +502,6 @@ int aac_get_containers(struct aac_dev *dev) ...@@ -492,12 +502,6 @@ int aac_get_containers(struct aac_dev *dev)
printk(KERN_WARNING "aac_get_containers: SendFIB failed.\n"); printk(KERN_WARNING "aac_get_containers: SendFIB failed.\n");
break; break;
} }
/*
* If there are no more containers, then stop asking.
*/
if (++index >= status)
break;
} }
return status; return status;
} }
......
...@@ -407,7 +407,7 @@ struct aac_fibhdr { ...@@ -407,7 +407,7 @@ struct aac_fibhdr {
__le32 SenderFibAddressHigh;/* upper 32bit of phys. FIB address */ __le32 SenderFibAddressHigh;/* upper 32bit of phys. FIB address */
__le32 TimeStamp; /* otherwise timestamp for FW internal use */ __le32 TimeStamp; /* otherwise timestamp for FW internal use */
} u; } u;
u32 Handle; /* FIB handle used for MSGU commnunication */ __le32 Handle; /* FIB handle used for MSGU commnunication */
u32 Previous; /* FW internal use */ u32 Previous; /* FW internal use */
u32 Next; /* FW internal use */ u32 Next; /* FW internal use */
}; };
...@@ -872,18 +872,20 @@ struct rkt_registers { ...@@ -872,18 +872,20 @@ struct rkt_registers {
#define src_inbound rx_inbound #define src_inbound rx_inbound
struct src_mu_registers { struct src_mu_registers {
/* PCI*| Name */ /* PCI*| Name */
__le32 reserved0[6]; /* 00h | Reserved */ __le32 reserved0[6]; /* 00h | Reserved */
__le32 IOAR[2]; /* 18h | IOA->host interrupt register */ __le32 IOAR[2]; /* 18h | IOA->host interrupt register */
__le32 IDR; /* 20h | Inbound Doorbell Register */ __le32 IDR; /* 20h | Inbound Doorbell Register */
__le32 IISR; /* 24h | Inbound Int. Status Register */ __le32 IISR; /* 24h | Inbound Int. Status Register */
__le32 reserved1[3]; /* 28h | Reserved */ __le32 reserved1[3]; /* 28h | Reserved */
__le32 OIMR; /* 34h | Outbound Int. Mask Register */ __le32 OIMR; /* 34h | Outbound Int. Mask Register */
__le32 reserved2[25]; /* 38h | Reserved */ __le32 reserved2[25]; /* 38h | Reserved */
__le32 ODR_R; /* 9ch | Outbound Doorbell Read */ __le32 ODR_R; /* 9ch | Outbound Doorbell Read */
__le32 ODR_C; /* a0h | Outbound Doorbell Clear */ __le32 ODR_C; /* a0h | Outbound Doorbell Clear */
__le32 reserved3[6]; /* a4h | Reserved */ __le32 reserved3[3]; /* a4h | Reserved */
__le32 OMR; /* bch | Outbound Message Register */ __le32 SCR0; /* b0h | Scratchpad 0 */
__le32 reserved4[2]; /* b4h | Reserved */
__le32 OMR; /* bch | Outbound Message Register */
__le32 IQ_L; /* c0h | Inbound Queue (Low address) */ __le32 IQ_L; /* c0h | Inbound Queue (Low address) */
__le32 IQ_H; /* c4h | Inbound Queue (High address) */ __le32 IQ_H; /* c4h | Inbound Queue (High address) */
__le32 ODR_MSI; /* c8h | MSI register for sync./AIF */ __le32 ODR_MSI; /* c8h | MSI register for sync./AIF */
...@@ -982,6 +984,7 @@ struct fsa_dev_info { ...@@ -982,6 +984,7 @@ struct fsa_dev_info {
char devname[8]; char devname[8];
struct sense_data sense_data; struct sense_data sense_data;
u32 block_size; u32 block_size;
u8 identifier[16];
}; };
struct fib { struct fib {
...@@ -1012,6 +1015,7 @@ struct fib { ...@@ -1012,6 +1015,7 @@ struct fib {
u32 vector_no; u32 vector_no;
struct hw_fib *hw_fib_va; /* Actual shared object */ struct hw_fib *hw_fib_va; /* Actual shared object */
dma_addr_t hw_fib_pa; /* physical address of hw_fib*/ dma_addr_t hw_fib_pa; /* physical address of hw_fib*/
u32 hbacmd_size; /* cmd size for native */
}; };
#define AAC_DEVTYPE_RAID_MEMBER 1 #define AAC_DEVTYPE_RAID_MEMBER 1
...@@ -1215,9 +1219,11 @@ struct aac_dev ...@@ -1215,9 +1219,11 @@ struct aac_dev
/* /*
* negotiated FIB settings * negotiated FIB settings
*/ */
unsigned max_fib_size; unsigned int max_fib_size;
unsigned sg_tablesize; unsigned int sg_tablesize;
unsigned max_num_aif; unsigned int max_num_aif;
unsigned int max_cmd_size; /* max_fib_size or MAX_NATIVE */
/* /*
* Map for 128 fib objects (64k) * Map for 128 fib objects (64k)
...@@ -1259,18 +1265,17 @@ struct aac_dev ...@@ -1259,18 +1265,17 @@ struct aac_dev
*/ */
union aac_init *init; union aac_init *init;
dma_addr_t init_pa; /* Holds physical address of the init struct */ dma_addr_t init_pa; /* Holds physical address of the init struct */
/* response queue (if AAC_COMM_MESSAGE_TYPE1) */
u32 *host_rrq; /* response queue __le32 *host_rrq;
* if AAC_COMM_MESSAGE_TYPE1 */
dma_addr_t host_rrq_pa; /* phys. address */ dma_addr_t host_rrq_pa; /* phys. address */
/* index into rrq buffer */ /* index into rrq buffer */
u32 host_rrq_idx[AAC_MAX_MSIX]; u32 host_rrq_idx[AAC_MAX_MSIX];
atomic_t rrq_outstanding[AAC_MAX_MSIX]; atomic_t rrq_outstanding[AAC_MAX_MSIX];
u32 fibs_pushed_no; u32 fibs_pushed_no;
struct pci_dev *pdev; /* Our PCI interface */ struct pci_dev *pdev; /* Our PCI interface */
void * printfbuf; /* pointer to buffer used for printf's from the adapter */ /* pointer to buffer used for printf's from the adapter */
void * comm_addr; /* Base address of Comm area */ void *printfbuf;
void *comm_addr; /* Base address of Comm area */
dma_addr_t comm_phys; /* Physical Address of Comm area */ dma_addr_t comm_phys; /* Physical Address of Comm area */
size_t comm_size; size_t comm_size;
...@@ -1342,6 +1347,8 @@ struct aac_dev ...@@ -1342,6 +1347,8 @@ struct aac_dev
u32 max_msix; /* max. MSI-X vectors */ u32 max_msix; /* max. MSI-X vectors */
u32 vector_cap; /* MSI-X vector capab.*/ u32 vector_cap; /* MSI-X vector capab.*/
int msi_enabled; /* MSI/MSI-X enabled */ int msi_enabled; /* MSI/MSI-X enabled */
atomic_t msix_counter;
struct msix_entry msixentry[AAC_MAX_MSIX];
struct aac_msix_ctx aac_msix[AAC_MAX_MSIX]; /* context */ struct aac_msix_ctx aac_msix[AAC_MAX_MSIX]; /* context */
struct aac_hba_map_info hba_map[AAC_MAX_BUSES][AAC_MAX_TARGETS]; struct aac_hba_map_info hba_map[AAC_MAX_BUSES][AAC_MAX_TARGETS];
u8 adapter_shutdown; u8 adapter_shutdown;
...@@ -2281,7 +2288,6 @@ int aac_rx_select_comm(struct aac_dev *dev, int comm); ...@@ -2281,7 +2288,6 @@ int aac_rx_select_comm(struct aac_dev *dev, int comm);
int aac_rx_deliver_producer(struct fib * fib); int aac_rx_deliver_producer(struct fib * fib);
char * get_container_type(unsigned type); char * get_container_type(unsigned type);
extern int numacb; extern int numacb;
extern int acbsize;
extern char aac_driver_version[]; extern char aac_driver_version[];
extern int startup_timeout; extern int startup_timeout;
extern int aif_timeout; extern int aif_timeout;
......
...@@ -60,12 +60,17 @@ ...@@ -60,12 +60,17 @@
static int fib_map_alloc(struct aac_dev *dev) static int fib_map_alloc(struct aac_dev *dev)
{ {
if (dev->max_fib_size > AAC_MAX_NATIVE_SIZE)
dev->max_cmd_size = AAC_MAX_NATIVE_SIZE;
else
dev->max_cmd_size = dev->max_fib_size;
dprintk((KERN_INFO dprintk((KERN_INFO
"allocate hardware fibs pci_alloc_consistent(%p, %d * (%d + %d), %p)\n", "allocate hardware fibs pci_alloc_consistent(%p, %d * (%d + %d), %p)\n",
dev->pdev, dev->max_fib_size, dev->scsi_host_ptr->can_queue, dev->pdev, dev->max_cmd_size, dev->scsi_host_ptr->can_queue,
AAC_NUM_MGT_FIB, &dev->hw_fib_pa)); AAC_NUM_MGT_FIB, &dev->hw_fib_pa));
dev->hw_fib_va = pci_alloc_consistent(dev->pdev, dev->hw_fib_va = pci_alloc_consistent(dev->pdev,
(dev->max_fib_size + sizeof(struct aac_fib_xporthdr)) (dev->max_cmd_size + sizeof(struct aac_fib_xporthdr))
* (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) + (ALIGN32 - 1), * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) + (ALIGN32 - 1),
&dev->hw_fib_pa); &dev->hw_fib_pa);
if (dev->hw_fib_va == NULL) if (dev->hw_fib_va == NULL)
...@@ -83,9 +88,9 @@ static int fib_map_alloc(struct aac_dev *dev) ...@@ -83,9 +88,9 @@ static int fib_map_alloc(struct aac_dev *dev)
void aac_fib_map_free(struct aac_dev *dev) void aac_fib_map_free(struct aac_dev *dev)
{ {
if (dev->hw_fib_va && dev->max_fib_size) { if (dev->hw_fib_va && dev->max_cmd_size) {
pci_free_consistent(dev->pdev, pci_free_consistent(dev->pdev,
(dev->max_fib_size * (dev->max_cmd_size *
(dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB)), (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB)),
dev->hw_fib_va, dev->hw_fib_pa); dev->hw_fib_va, dev->hw_fib_pa);
} }
...@@ -176,9 +181,9 @@ int aac_fib_setup(struct aac_dev * dev) ...@@ -176,9 +181,9 @@ int aac_fib_setup(struct aac_dev * dev)
hw_fib->header.SenderSize = cpu_to_le16(dev->max_fib_size); hw_fib->header.SenderSize = cpu_to_le16(dev->max_fib_size);
fibptr->hw_fib_pa = hw_fib_pa; fibptr->hw_fib_pa = hw_fib_pa;
hw_fib = (struct hw_fib *)((unsigned char *)hw_fib + hw_fib = (struct hw_fib *)((unsigned char *)hw_fib +
dev->max_fib_size + sizeof(struct aac_fib_xporthdr)); dev->max_cmd_size + sizeof(struct aac_fib_xporthdr));
hw_fib_pa = hw_fib_pa + hw_fib_pa = hw_fib_pa +
dev->max_fib_size + sizeof(struct aac_fib_xporthdr); dev->max_cmd_size + sizeof(struct aac_fib_xporthdr);
} }
/* /*
......
...@@ -122,7 +122,6 @@ unsigned int aac_response_normal(struct aac_queue * q) ...@@ -122,7 +122,6 @@ unsigned int aac_response_normal(struct aac_queue * q)
* NOTE: we cannot touch the fib after this * NOTE: we cannot touch the fib after this
* call, because it may have been deallocated. * call, because it may have been deallocated.
*/ */
fib->flags &= FIB_CONTEXT_FLAG_FASTRESP;
fib->callback(fib->callback_data, fib); fib->callback(fib->callback_data, fib);
} else { } else {
unsigned long flagv; unsigned long flagv;
...@@ -251,8 +250,9 @@ static void aac_aif_callback(void *context, struct fib * fibptr) ...@@ -251,8 +250,9 @@ static void aac_aif_callback(void *context, struct fib * fibptr)
BUG_ON(fibptr == NULL); BUG_ON(fibptr == NULL);
dev = fibptr->dev; dev = fibptr->dev;
if (fibptr->hw_fib_va->header.XferState & if ((fibptr->hw_fib_va->header.XferState &
cpu_to_le32(NoMoreAifDataAvailable)) { cpu_to_le32(NoMoreAifDataAvailable)) ||
dev->sa_firmware) {
aac_fib_complete(fibptr); aac_fib_complete(fibptr);
aac_fib_free(fibptr); aac_fib_free(fibptr);
return; return;
...@@ -282,8 +282,8 @@ static void aac_aif_callback(void *context, struct fib * fibptr) ...@@ -282,8 +282,8 @@ static void aac_aif_callback(void *context, struct fib * fibptr)
* know there is a response on our normal priority queue. We will pull off * know there is a response on our normal priority queue. We will pull off
* all QE there are and wake up all the waiters before exiting. * all QE there are and wake up all the waiters before exiting.
*/ */
unsigned int aac_intr_normal(struct aac_dev *dev, u32 index, unsigned int aac_intr_normal(struct aac_dev *dev, u32 index, int isAif,
int isAif, int isFastResponse, struct hw_fib *aif_fib) int isFastResponse, struct hw_fib *aif_fib)
{ {
unsigned long mflags; unsigned long mflags;
dprintk((KERN_INFO "aac_intr_normal(%p,%x)\n", dev, index)); dprintk((KERN_INFO "aac_intr_normal(%p,%x)\n", dev, index));
...@@ -305,12 +305,14 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index, ...@@ -305,12 +305,14 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index,
kfree (fib); kfree (fib);
return 1; return 1;
} }
if (aif_fib != NULL) { if (dev->sa_firmware) {
fib->hbacmd_size = index; /* store event type */
} else if (aif_fib != NULL) {
memcpy(hw_fib, aif_fib, sizeof(struct hw_fib)); memcpy(hw_fib, aif_fib, sizeof(struct hw_fib));
} else { } else {
memcpy(hw_fib, memcpy(hw_fib, (struct hw_fib *)
(struct hw_fib *)(((uintptr_t)(dev->regs.sa)) + (((uintptr_t)(dev->regs.sa)) + index),
index), sizeof(struct hw_fib)); sizeof(struct hw_fib));
} }
INIT_LIST_HEAD(&fib->fiblink); INIT_LIST_HEAD(&fib->fiblink);
fib->type = FSAFS_NTC_FIB_CONTEXT; fib->type = FSAFS_NTC_FIB_CONTEXT;
......
...@@ -135,8 +135,16 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id) ...@@ -135,8 +135,16 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id)
if (mode & AAC_INT_MODE_AIF) { if (mode & AAC_INT_MODE_AIF) {
/* handle AIF */ /* handle AIF */
if (dev->aif_thread && dev->fsa_dev) if (dev->sa_firmware) {
aac_intr_normal(dev, 0, 2, 0, NULL); u32 events = src_readl(dev, MUnit.SCR0);
aac_intr_normal(dev, events, 1, 0, NULL);
writel(events, &dev->IndexRegs->Mailbox[0]);
src_writel(dev, MUnit.IDR, 1 << 23);
} else {
if (dev->aif_thread && dev->fsa_dev)
aac_intr_normal(dev, 0, 2, 0, NULL);
}
if (dev->msi_enabled) if (dev->msi_enabled)
aac_src_access_devreg(dev, AAC_CLEAR_AIF_BIT); aac_src_access_devreg(dev, AAC_CLEAR_AIF_BIT);
mode = 0; mode = 0;
...@@ -148,17 +156,19 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id) ...@@ -148,17 +156,19 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id)
for (;;) { for (;;) {
isFastResponse = 0; isFastResponse = 0;
/* remove toggle bit (31) */ /* remove toggle bit (31) */
handle = (dev->host_rrq[index] & 0x7fffffff); handle = le32_to_cpu((dev->host_rrq[index])
/* check fast response bit (30) */ & 0x7fffffff);
/* check fast response bits (30, 1) */
if (handle & 0x40000000) if (handle & 0x40000000)
isFastResponse = 1; isFastResponse = 1;
handle &= 0x0000ffff; handle &= 0x0000ffff;
if (handle == 0) if (handle == 0)
break; break;
handle >>= 2;
if (dev->msi_enabled && dev->max_msix > 1) if (dev->msi_enabled && dev->max_msix > 1)
atomic_dec(&dev->rrq_outstanding[vector_no]); atomic_dec(&dev->rrq_outstanding[vector_no]);
aac_intr_normal(dev, handle, 0, isFastResponse, NULL);
dev->host_rrq[index++] = 0; dev->host_rrq[index++] = 0;
aac_intr_normal(dev, handle-1, 0, isFastResponse, NULL);
if (index == (vector_no + 1) * dev->vector_cap) if (index == (vector_no + 1) * dev->vector_cap)
index = vector_no * dev->vector_cap; index = vector_no * dev->vector_cap;
dev->host_rrq_idx[vector_no] = index; dev->host_rrq_idx[vector_no] = index;
...@@ -392,6 +402,7 @@ static void aac_src_start_adapter(struct aac_dev *dev) ...@@ -392,6 +402,7 @@ static void aac_src_start_adapter(struct aac_dev *dev)
dev->host_rrq_idx[i] = i * dev->vector_cap; dev->host_rrq_idx[i] = i * dev->vector_cap;
atomic_set(&dev->rrq_outstanding[i], 0); atomic_set(&dev->rrq_outstanding[i], 0);
} }
atomic_set(&dev->msix_counter, 0);
dev->fibs_pushed_no = 0; dev->fibs_pushed_no = 0;
init = dev->init; init = dev->init;
...@@ -565,9 +576,18 @@ static int aac_srcv_ioremap(struct aac_dev *dev, u32 size) ...@@ -565,9 +576,18 @@ static int aac_srcv_ioremap(struct aac_dev *dev, u32 size)
dev->base = dev->regs.src.bar0 = NULL; dev->base = dev->regs.src.bar0 = NULL;
return 0; return 0;
} }
dev->regs.src.bar1 =
ioremap(pci_resource_start(dev->pdev, 2), AAC_MIN_SRCV_BAR1_SIZE);
dev->base = NULL;
if (dev->regs.src.bar1 == NULL)
return -1;
dev->base = dev->regs.src.bar0 = ioremap(dev->base_start, size); dev->base = dev->regs.src.bar0 = ioremap(dev->base_start, size);
if (dev->base == NULL) if (dev->base == NULL) {
iounmap(dev->regs.src.bar1);
dev->regs.src.bar1 = NULL;
return -1; return -1;
}
dev->IndexRegs = &((struct src_registers __iomem *) dev->IndexRegs = &((struct src_registers __iomem *)
dev->base)->u.denali.IndexRegs; dev->base)->u.denali.IndexRegs;
return 0; return 0;
...@@ -918,9 +938,9 @@ int aac_srcv_init(struct aac_dev *dev) ...@@ -918,9 +938,9 @@ int aac_srcv_init(struct aac_dev *dev)
if (aac_acquire_irq(dev)) if (aac_acquire_irq(dev))
goto error_iounmap; goto error_iounmap;
dev->dbg_base = dev->base_start; dev->dbg_base = pci_resource_start(dev->pdev, 2);
dev->dbg_base_mapped = dev->base; dev->dbg_base_mapped = dev->regs.src.bar1;
dev->dbg_size = dev->base_size; dev->dbg_size = AAC_MIN_SRCV_BAR1_SIZE;
dev->a_ops.adapter_enable_int = aac_src_enable_interrupt_message; dev->a_ops.adapter_enable_int = aac_src_enable_interrupt_message;
aac_adapter_enable_int(dev); aac_adapter_enable_int(dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment