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,
}
scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
device = scsicmd->device;
if (unlikely(!device || !scsi_device_online(device))) {
if (unlikely(!device)) {
dprintk((KERN_WARNING "aac_valid_context: scsi device corrupt\n"));
aac_fib_complete(fibptr);
return 0;
......@@ -475,16 +475,26 @@ int aac_get_containers(struct aac_dev *dev)
if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS)
maximum_num_containers = MAXIMUM_NUM_CONTAINERS;
fsa_dev_ptr = kzalloc(sizeof(*fsa_dev_ptr) * maximum_num_containers,
GFP_KERNEL);
if (!fsa_dev_ptr)
return -ENOMEM;
if (dev->fsa_dev == NULL ||
dev->maximum_num_containers != maximum_num_containers) {
fsa_dev_ptr = dev->fsa_dev;
dev->fsa_dev = fsa_dev_ptr;
dev->maximum_num_containers = maximum_num_containers;
dev->fsa_dev = kcalloc(maximum_num_containers,
sizeof(*fsa_dev_ptr), GFP_KERNEL);
for (index = 0; index < dev->maximum_num_containers; ) {
fsa_dev_ptr[index].devname[0] = '\0';
kfree(fsa_dev_ptr);
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);
......@@ -492,12 +502,6 @@ int aac_get_containers(struct aac_dev *dev)
printk(KERN_WARNING "aac_get_containers: SendFIB failed.\n");
break;
}
/*
* If there are no more containers, then stop asking.
*/
if (++index >= status)
break;
}
return status;
}
......
......@@ -407,7 +407,7 @@ struct aac_fibhdr {
__le32 SenderFibAddressHigh;/* upper 32bit of phys. FIB address */
__le32 TimeStamp; /* otherwise timestamp for FW internal use */
} u;
u32 Handle; /* FIB handle used for MSGU commnunication */
__le32 Handle; /* FIB handle used for MSGU commnunication */
u32 Previous; /* FW internal use */
u32 Next; /* FW internal use */
};
......@@ -872,18 +872,20 @@ struct rkt_registers {
#define src_inbound rx_inbound
struct src_mu_registers {
/* PCI*| Name */
__le32 reserved0[6]; /* 00h | Reserved */
__le32 IOAR[2]; /* 18h | IOA->host interrupt register */
__le32 IDR; /* 20h | Inbound Doorbell Register */
__le32 IISR; /* 24h | Inbound Int. Status Register */
__le32 reserved1[3]; /* 28h | Reserved */
__le32 OIMR; /* 34h | Outbound Int. Mask Register */
__le32 reserved2[25]; /* 38h | Reserved */
__le32 ODR_R; /* 9ch | Outbound Doorbell Read */
__le32 ODR_C; /* a0h | Outbound Doorbell Clear */
__le32 reserved3[6]; /* a4h | Reserved */
__le32 OMR; /* bch | Outbound Message Register */
/* PCI*| Name */
__le32 reserved0[6]; /* 00h | Reserved */
__le32 IOAR[2]; /* 18h | IOA->host interrupt register */
__le32 IDR; /* 20h | Inbound Doorbell Register */
__le32 IISR; /* 24h | Inbound Int. Status Register */
__le32 reserved1[3]; /* 28h | Reserved */
__le32 OIMR; /* 34h | Outbound Int. Mask Register */
__le32 reserved2[25]; /* 38h | Reserved */
__le32 ODR_R; /* 9ch | Outbound Doorbell Read */
__le32 ODR_C; /* a0h | Outbound Doorbell Clear */
__le32 reserved3[3]; /* a4h | Reserved */
__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_H; /* c4h | Inbound Queue (High address) */
__le32 ODR_MSI; /* c8h | MSI register for sync./AIF */
......@@ -982,6 +984,7 @@ struct fsa_dev_info {
char devname[8];
struct sense_data sense_data;
u32 block_size;
u8 identifier[16];
};
struct fib {
......@@ -1012,6 +1015,7 @@ struct fib {
u32 vector_no;
struct hw_fib *hw_fib_va; /* Actual shared object */
dma_addr_t hw_fib_pa; /* physical address of hw_fib*/
u32 hbacmd_size; /* cmd size for native */
};
#define AAC_DEVTYPE_RAID_MEMBER 1
......@@ -1215,9 +1219,11 @@ struct aac_dev
/*
* negotiated FIB settings
*/
unsigned max_fib_size;
unsigned sg_tablesize;
unsigned max_num_aif;
unsigned int max_fib_size;
unsigned int sg_tablesize;
unsigned int max_num_aif;
unsigned int max_cmd_size; /* max_fib_size or MAX_NATIVE */
/*
* Map for 128 fib objects (64k)
......@@ -1259,18 +1265,17 @@ struct aac_dev
*/
union aac_init *init;
dma_addr_t init_pa; /* Holds physical address of the init struct */
u32 *host_rrq; /* response queue
* if AAC_COMM_MESSAGE_TYPE1 */
/* response queue (if AAC_COMM_MESSAGE_TYPE1) */
__le32 *host_rrq;
dma_addr_t host_rrq_pa; /* phys. address */
/* index into rrq buffer */
u32 host_rrq_idx[AAC_MAX_MSIX];
atomic_t rrq_outstanding[AAC_MAX_MSIX];
u32 fibs_pushed_no;
struct pci_dev *pdev; /* Our PCI interface */
void * printfbuf; /* pointer to buffer used for printf's from the adapter */
void * comm_addr; /* Base address of Comm area */
/* pointer to buffer used for printf's from the adapter */
void *printfbuf;
void *comm_addr; /* Base address of Comm area */
dma_addr_t comm_phys; /* Physical Address of Comm area */
size_t comm_size;
......@@ -1342,6 +1347,8 @@ struct aac_dev
u32 max_msix; /* max. MSI-X vectors */
u32 vector_cap; /* MSI-X vector capab.*/
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_hba_map_info hba_map[AAC_MAX_BUSES][AAC_MAX_TARGETS];
u8 adapter_shutdown;
......@@ -2281,7 +2288,6 @@ int aac_rx_select_comm(struct aac_dev *dev, int comm);
int aac_rx_deliver_producer(struct fib * fib);
char * get_container_type(unsigned type);
extern int numacb;
extern int acbsize;
extern char aac_driver_version[];
extern int startup_timeout;
extern int aif_timeout;
......
......@@ -60,12 +60,17 @@
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
"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));
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->hw_fib_pa);
if (dev->hw_fib_va == NULL)
......@@ -83,9 +88,9 @@ static int fib_map_alloc(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,
(dev->max_fib_size *
(dev->max_cmd_size *
(dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB)),
dev->hw_fib_va, dev->hw_fib_pa);
}
......@@ -176,9 +181,9 @@ int aac_fib_setup(struct aac_dev * dev)
hw_fib->header.SenderSize = cpu_to_le16(dev->max_fib_size);
fibptr->hw_fib_pa = hw_fib_pa;
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 +
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)
* NOTE: we cannot touch the fib after this
* call, because it may have been deallocated.
*/
fib->flags &= FIB_CONTEXT_FLAG_FASTRESP;
fib->callback(fib->callback_data, fib);
} else {
unsigned long flagv;
......@@ -251,8 +250,9 @@ static void aac_aif_callback(void *context, struct fib * fibptr)
BUG_ON(fibptr == NULL);
dev = fibptr->dev;
if (fibptr->hw_fib_va->header.XferState &
cpu_to_le32(NoMoreAifDataAvailable)) {
if ((fibptr->hw_fib_va->header.XferState &
cpu_to_le32(NoMoreAifDataAvailable)) ||
dev->sa_firmware) {
aac_fib_complete(fibptr);
aac_fib_free(fibptr);
return;
......@@ -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
* all QE there are and wake up all the waiters before exiting.
*/
unsigned int aac_intr_normal(struct aac_dev *dev, u32 index,
int isAif, int isFastResponse, struct hw_fib *aif_fib)
unsigned int aac_intr_normal(struct aac_dev *dev, u32 index, int isAif,
int isFastResponse, struct hw_fib *aif_fib)
{
unsigned long mflags;
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,
kfree (fib);
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));
} else {
memcpy(hw_fib,
(struct hw_fib *)(((uintptr_t)(dev->regs.sa)) +
index), sizeof(struct hw_fib));
memcpy(hw_fib, (struct hw_fib *)
(((uintptr_t)(dev->regs.sa)) + index),
sizeof(struct hw_fib));
}
INIT_LIST_HEAD(&fib->fiblink);
fib->type = FSAFS_NTC_FIB_CONTEXT;
......
......@@ -135,8 +135,16 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id)
if (mode & AAC_INT_MODE_AIF) {
/* handle AIF */
if (dev->aif_thread && dev->fsa_dev)
aac_intr_normal(dev, 0, 2, 0, NULL);
if (dev->sa_firmware) {
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)
aac_src_access_devreg(dev, AAC_CLEAR_AIF_BIT);
mode = 0;
......@@ -148,17 +156,19 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id)
for (;;) {
isFastResponse = 0;
/* remove toggle bit (31) */
handle = (dev->host_rrq[index] & 0x7fffffff);
/* check fast response bit (30) */
handle = le32_to_cpu((dev->host_rrq[index])
& 0x7fffffff);
/* check fast response bits (30, 1) */
if (handle & 0x40000000)
isFastResponse = 1;
handle &= 0x0000ffff;
if (handle == 0)
break;
handle >>= 2;
if (dev->msi_enabled && dev->max_msix > 1)
atomic_dec(&dev->rrq_outstanding[vector_no]);
aac_intr_normal(dev, handle, 0, isFastResponse, NULL);
dev->host_rrq[index++] = 0;
aac_intr_normal(dev, handle-1, 0, isFastResponse, NULL);
if (index == (vector_no + 1) * dev->vector_cap)
index = vector_no * dev->vector_cap;
dev->host_rrq_idx[vector_no] = index;
......@@ -392,6 +402,7 @@ static void aac_src_start_adapter(struct aac_dev *dev)
dev->host_rrq_idx[i] = i * dev->vector_cap;
atomic_set(&dev->rrq_outstanding[i], 0);
}
atomic_set(&dev->msix_counter, 0);
dev->fibs_pushed_no = 0;
init = dev->init;
......@@ -565,9 +576,18 @@ static int aac_srcv_ioremap(struct aac_dev *dev, u32 size)
dev->base = dev->regs.src.bar0 = NULL;
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);
if (dev->base == NULL)
if (dev->base == NULL) {
iounmap(dev->regs.src.bar1);
dev->regs.src.bar1 = NULL;
return -1;
}
dev->IndexRegs = &((struct src_registers __iomem *)
dev->base)->u.denali.IndexRegs;
return 0;
......@@ -918,9 +938,9 @@ int aac_srcv_init(struct aac_dev *dev)
if (aac_acquire_irq(dev))
goto error_iounmap;
dev->dbg_base = dev->base_start;
dev->dbg_base_mapped = dev->base;
dev->dbg_size = dev->base_size;
dev->dbg_base = pci_resource_start(dev->pdev, 2);
dev->dbg_base_mapped = dev->regs.src.bar1;
dev->dbg_size = AAC_MIN_SRCV_BAR1_SIZE;
dev->a_ops.adapter_enable_int = aac_src_enable_interrupt_message;
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