Commit 423400e6 authored by Raghava Aditya Renukunta's avatar Raghava Aditya Renukunta Committed by Martin K. Petersen

scsi: aacraid: Include HBA direct interface

Added support to send direct pasthru srb commands from management utilty
to the  controller.
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 6223a39f
...@@ -86,6 +86,7 @@ enum { ...@@ -86,6 +86,7 @@ enum {
#define AAC_MAX_BUSES 5 #define AAC_MAX_BUSES 5
#define AAC_MAX_TARGETS 256 #define AAC_MAX_TARGETS 256
#define AAC_MAX_NATIVE_SIZE 2048 #define AAC_MAX_NATIVE_SIZE 2048
#define FW_ERROR_BUFFER_SIZE 512
/* Thor AIF events */ /* Thor AIF events */
#define SA_AIF_HOTPLUG (1<<1) #define SA_AIF_HOTPLUG (1<<1)
...@@ -95,6 +96,141 @@ enum { ...@@ -95,6 +96,141 @@ enum {
#define SA_AIF_BPSTAT_CHANGE (1<<30) #define SA_AIF_BPSTAT_CHANGE (1<<30)
#define SA_AIF_BPCFG_CHANGE (1<<31) #define SA_AIF_BPCFG_CHANGE (1<<31)
#define HBA_MAX_SG_EMBEDDED 28
#define HBA_MAX_SG_SEPARATE 90
#define HBA_SENSE_DATA_LEN_MAX 32
#define HBA_REQUEST_TAG_ERROR_FLAG 0x00000002
#define HBA_SGL_FLAGS_EXT 0x80000000UL
struct aac_hba_sgl {
u32 addr_lo; /* Lower 32-bits of SGL element address */
u32 addr_hi; /* Upper 32-bits of SGL element address */
u32 len; /* Length of SGL element in bytes */
u32 flags; /* SGL element flags */
};
enum {
HBA_IU_TYPE_SCSI_CMD_REQ = 0x40,
HBA_IU_TYPE_SCSI_TM_REQ = 0x41,
HBA_IU_TYPE_SATA_REQ = 0x42,
HBA_IU_TYPE_RESP = 0x60,
HBA_IU_TYPE_COALESCED_RESP = 0x61,
HBA_IU_TYPE_INT_COALESCING_CFG_REQ = 0x70
};
enum {
HBA_CMD_BYTE1_DATA_DIR_IN = 0x1,
HBA_CMD_BYTE1_DATA_DIR_OUT = 0x2,
HBA_CMD_BYTE1_DATA_TYPE_DDR = 0x4,
HBA_CMD_BYTE1_CRYPTO_ENABLE = 0x8
};
enum {
HBA_CMD_BYTE1_BITOFF_DATA_DIR_IN = 0x0,
HBA_CMD_BYTE1_BITOFF_DATA_DIR_OUT,
HBA_CMD_BYTE1_BITOFF_DATA_TYPE_DDR,
HBA_CMD_BYTE1_BITOFF_CRYPTO_ENABLE
};
enum {
HBA_RESP_DATAPRES_NO_DATA = 0x0,
HBA_RESP_DATAPRES_RESPONSE_DATA,
HBA_RESP_DATAPRES_SENSE_DATA
};
enum {
HBA_RESP_SVCRES_TASK_COMPLETE = 0x0,
HBA_RESP_SVCRES_FAILURE,
HBA_RESP_SVCRES_TMF_COMPLETE,
HBA_RESP_SVCRES_TMF_SUCCEEDED,
HBA_RESP_SVCRES_TMF_REJECTED,
HBA_RESP_SVCRES_TMF_LUN_INVALID
};
enum {
HBA_RESP_STAT_IO_ERROR = 0x1,
HBA_RESP_STAT_IO_ABORTED,
HBA_RESP_STAT_NO_PATH_TO_DEVICE,
HBA_RESP_STAT_INVALID_DEVICE,
HBA_RESP_STAT_HBAMODE_DISABLED = 0xE,
HBA_RESP_STAT_UNDERRUN = 0x51,
HBA_RESP_STAT_OVERRUN = 0x75
};
struct aac_hba_cmd_req {
u8 iu_type; /* HBA information unit type */
/*
* byte1:
* [1:0] DIR - 0=No data, 0x1 = IN, 0x2 = OUT
* [2] TYPE - 0=PCI, 1=DDR
* [3] CRYPTO_ENABLE - 0=Crypto disabled, 1=Crypto enabled
*/
u8 byte1;
u8 reply_qid; /* Host reply queue to post response to */
u8 reserved1;
__le32 it_nexus; /* Device handle for the request */
__le32 request_id; /* Sender context */
/* Lower 32-bits of tweak value for crypto enabled IOs */
__le32 tweak_value_lo;
u8 cdb[16]; /* SCSI CDB of the command */
u8 lun[8]; /* SCSI LUN of the command */
/* Total data length in bytes to be read/written (if any) */
__le32 data_length;
/* [2:0] Task Attribute, [6:3] Command Priority */
u8 attr_prio;
/* Number of SGL elements embedded in the HBA req */
u8 emb_data_desc_count;
__le16 dek_index; /* DEK index for crypto enabled IOs */
/* Lower 32-bits of reserved error data target location on the host */
__le32 error_ptr_lo;
/* Upper 32-bits of reserved error data target location on the host */
__le32 error_ptr_hi;
/* Length of reserved error data area on the host in bytes */
__le32 error_length;
/* Upper 32-bits of tweak value for crypto enabled IOs */
__le32 tweak_value_hi;
struct aac_hba_sgl sge[HBA_MAX_SG_SEPARATE+2]; /* SG list space */
/*
* structure must not exceed
* AAC_MAX_NATIVE_SIZE-FW_ERROR_BUFFER_SIZE
*/
};
struct aac_hba_resp {
u8 iu_type; /* HBA information unit type */
u8 reserved1[3];
__le32 request_identifier; /* sender context */
__le32 reserved2;
u8 service_response; /* SCSI service response */
u8 status; /* SCSI status */
u8 datapres; /* [1:0] - data present, [7:2] - reserved */
u8 sense_response_data_len; /* Sense/response data length */
__le32 residual_count; /* Residual data length in bytes */
/* Sense/response data */
u8 sense_response_buf[HBA_SENSE_DATA_LEN_MAX];
};
struct aac_native_hba {
union {
struct aac_hba_cmd_req cmd;
u8 cmd_bytes[AAC_MAX_NATIVE_SIZE-FW_ERROR_BUFFER_SIZE];
} cmd;
union {
struct aac_hba_resp err;
u8 resp_bytes[FW_ERROR_BUFFER_SIZE];
} resp;
};
#define CISS_REPORT_PHYSICAL_LUNS 0xc3 #define CISS_REPORT_PHYSICAL_LUNS 0xc3
#define WRITE_HOST_WELLNESS 0xa5 #define WRITE_HOST_WELLNESS 0xa5
#define CISS_IDENTIFY_PHYSICAL_DEVICE 0x15 #define CISS_IDENTIFY_PHYSICAL_DEVICE 0x15
...@@ -468,10 +604,10 @@ enum aac_queue_types { ...@@ -468,10 +604,10 @@ enum aac_queue_types {
/* transport FIB header (PMC) */ /* transport FIB header (PMC) */
struct aac_fib_xporthdr { struct aac_fib_xporthdr {
u64 HostAddress; /* FIB host address w/o xport header */ __le64 HostAddress; /* FIB host address w/o xport header */
u32 Size; /* FIB size excluding xport header */ __le32 Size; /* FIB size excluding xport header */
u32 Handle; /* driver handle to reference the FIB */ __le32 Handle; /* driver handle to reference the FIB */
u64 Reserved[2]; __le64 Reserved[2];
}; };
#define ALIGN32 32 #define ALIGN32 32
...@@ -978,17 +1114,20 @@ struct src_mu_registers { ...@@ -978,17 +1114,20 @@ struct src_mu_registers {
__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 */
__le32 reserved5; /* cch | Reserved */
__le32 IQN_L; /* d0h | Inbound (native cmd) low */
__le32 IQN_H; /* d4h | Inbound (native cmd) high */
}; };
struct src_registers { struct src_registers {
struct src_mu_registers MUnit; /* 00h - cbh */ struct src_mu_registers MUnit; /* 00h - cbh */
union { union {
struct { struct {
__le32 reserved1[130789]; /* cch - 7fc5fh */ __le32 reserved1[130786]; /* d8h - 7fc5fh */
struct src_inbound IndexRegs; /* 7fc60h */ struct src_inbound IndexRegs; /* 7fc60h */
} tupelo; } tupelo;
struct { struct {
__le32 reserved1[973]; /* cch - fffh */ __le32 reserved1[970]; /* d8h - fffh */
struct src_inbound IndexRegs; /* 1000h */ struct src_inbound IndexRegs; /* 1000h */
} denali; } denali;
} u; } u;
...@@ -1102,8 +1241,10 @@ struct fib { ...@@ -1102,8 +1241,10 @@ struct fib {
struct list_head fiblink; struct list_head fiblink;
void *data; void *data;
u32 vector_no; u32 vector_no;
struct hw_fib *hw_fib_va; /* Actual shared object */ struct hw_fib *hw_fib_va; /* also used for native */
dma_addr_t hw_fib_pa; /* physical address of hw_fib*/ dma_addr_t hw_fib_pa; /* physical address of hw_fib*/
dma_addr_t hw_sgl_pa; /* extra sgl for native */
dma_addr_t hw_error_pa; /* error buffer for native */
u32 hbacmd_size; /* cmd size for native */ u32 hbacmd_size; /* cmd size for native */
}; };
...@@ -1285,6 +1426,7 @@ struct aac_bus_info_response { ...@@ -1285,6 +1426,7 @@ struct aac_bus_info_response {
#define AAC_OPT_NEW_COMM cpu_to_le32(1<<17) #define AAC_OPT_NEW_COMM cpu_to_le32(1<<17)
#define AAC_OPT_NEW_COMM_64 cpu_to_le32(1<<18) #define AAC_OPT_NEW_COMM_64 cpu_to_le32(1<<18)
#define AAC_OPT_EXTENDED cpu_to_le32(1<<23) #define AAC_OPT_EXTENDED cpu_to_le32(1<<23)
#define AAC_OPT_NATIVE_HBA cpu_to_le32(1<<25)
#define AAC_OPT_NEW_COMM_TYPE1 cpu_to_le32(1<<28) #define AAC_OPT_NEW_COMM_TYPE1 cpu_to_le32(1<<28)
#define AAC_OPT_NEW_COMM_TYPE2 cpu_to_le32(1<<29) #define AAC_OPT_NEW_COMM_TYPE2 cpu_to_le32(1<<29)
#define AAC_OPT_NEW_COMM_TYPE3 cpu_to_le32(1<<30) #define AAC_OPT_NEW_COMM_TYPE3 cpu_to_le32(1<<30)
...@@ -1322,8 +1464,8 @@ struct aac_dev ...@@ -1322,8 +1464,8 @@ struct aac_dev
/* /*
* Map for 128 fib objects (64k) * Map for 128 fib objects (64k)
*/ */
dma_addr_t hw_fib_pa; dma_addr_t hw_fib_pa; /* also used for native cmd */
struct hw_fib *hw_fib_va; struct hw_fib *hw_fib_va; /* also used for native cmd */
struct hw_fib *aif_base_va; struct hw_fib *aif_base_va;
/* /*
* Fib Headers * Fib Headers
...@@ -1498,6 +1640,8 @@ struct aac_dev ...@@ -1498,6 +1640,8 @@ struct aac_dev
#define FIB_CONTEXT_FLAG (0x00000002) #define FIB_CONTEXT_FLAG (0x00000002)
#define FIB_CONTEXT_FLAG_WAIT (0x00000004) #define FIB_CONTEXT_FLAG_WAIT (0x00000004)
#define FIB_CONTEXT_FLAG_FASTRESP (0x00000008) #define FIB_CONTEXT_FLAG_FASTRESP (0x00000008)
#define FIB_CONTEXT_FLAG_NATIVE_HBA (0x00000010)
#define FIB_CONTEXT_FLAG_NATIVE_HBA_TMF (0x00000020)
/* /*
* Define the command values * Define the command values
...@@ -2157,6 +2301,8 @@ struct aac_common ...@@ -2157,6 +2301,8 @@ struct aac_common
#ifdef DBG #ifdef DBG
u32 FibsSent; u32 FibsSent;
u32 FibRecved; u32 FibRecved;
u32 NativeSent;
u32 NativeRecved;
u32 NoResponseSent; u32 NoResponseSent;
u32 NoResponseRecved; u32 NoResponseRecved;
u32 AsyncSent; u32 AsyncSent;
...@@ -2168,7 +2314,6 @@ struct aac_common ...@@ -2168,7 +2314,6 @@ struct aac_common
extern struct aac_common aac_config; extern struct aac_common aac_config;
/* /*
* The following macro is used when sending and receiving FIBs. It is * The following macro is used when sending and receiving FIBs. It is
* only used for debugging. * only used for debugging.
...@@ -2295,9 +2440,10 @@ extern struct aac_common aac_config; ...@@ -2295,9 +2440,10 @@ extern struct aac_common aac_config;
/* PMC NEW COMM: Request the event data */ /* PMC NEW COMM: Request the event data */
#define AifReqEvent 200 #define AifReqEvent 200
#define AifRawDeviceRemove 203 /* RAW device deleted */
#define AifNativeDeviceAdd 204 /* native HBA device added */
#define AifNativeDeviceRemove 205 /* native HBA device removed */
/* RAW device deleted */
#define AifRawDeviceRemove 203
/* /*
* Adapter Initiated FIB command structures. Start with the adapter * Adapter Initiated FIB command structures. Start with the adapter
...@@ -2342,9 +2488,12 @@ void aac_fib_free(struct fib * context); ...@@ -2342,9 +2488,12 @@ void aac_fib_free(struct fib * context);
void aac_fib_init(struct fib * context); void aac_fib_init(struct fib * context);
void aac_printf(struct aac_dev *dev, u32 val); void aac_printf(struct aac_dev *dev, u32 val);
int aac_fib_send(u16 command, struct fib * context, unsigned long size, int priority, int wait, int reply, fib_callback callback, void *ctxt); int aac_fib_send(u16 command, struct fib * context, unsigned long size, int priority, int wait, int reply, fib_callback callback, void *ctxt);
int aac_hba_send(u8 command, struct fib *context,
fib_callback callback, void *ctxt);
int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry); int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry);
void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum); void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum);
int aac_fib_complete(struct fib * context); int aac_fib_complete(struct fib * context);
void aac_hba_callback(void *context, struct fib *fibptr);
#define fib_data(fibctx) ((void *)(fibctx)->hw_fib_va->data) #define fib_data(fibctx) ((void *)(fibctx)->hw_fib_va->data)
struct aac_dev *aac_init_adapter(struct aac_dev *dev); struct aac_dev *aac_init_adapter(struct aac_dev *dev);
void aac_src_access_devreg(struct aac_dev *dev, int mode); void aac_src_access_devreg(struct aac_dev *dev, int mode);
......
This diff is collapsed.
...@@ -65,6 +65,11 @@ static int fib_map_alloc(struct aac_dev *dev) ...@@ -65,6 +65,11 @@ static int fib_map_alloc(struct aac_dev *dev)
dev->max_cmd_size = AAC_MAX_NATIVE_SIZE; dev->max_cmd_size = AAC_MAX_NATIVE_SIZE;
else else
dev->max_cmd_size = dev->max_fib_size; dev->max_cmd_size = dev->max_fib_size;
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",
...@@ -153,7 +158,7 @@ int aac_fib_setup(struct aac_dev * dev) ...@@ -153,7 +158,7 @@ int aac_fib_setup(struct aac_dev * dev)
(hw_fib_pa - dev->hw_fib_pa)); (hw_fib_pa - dev->hw_fib_pa));
dev->hw_fib_pa = hw_fib_pa; dev->hw_fib_pa = hw_fib_pa;
memset(dev->hw_fib_va, 0, memset(dev->hw_fib_va, 0,
(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)); (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB));
/* add Xport header */ /* add Xport header */
...@@ -179,8 +184,18 @@ int aac_fib_setup(struct aac_dev * dev) ...@@ -179,8 +184,18 @@ int aac_fib_setup(struct aac_dev * dev)
sema_init(&fibptr->event_wait, 0); sema_init(&fibptr->event_wait, 0);
spin_lock_init(&fibptr->event_lock); spin_lock_init(&fibptr->event_lock);
hw_fib->header.XferState = cpu_to_le32(0xffffffff); hw_fib->header.XferState = cpu_to_le32(0xffffffff);
hw_fib->header.SenderSize = cpu_to_le16(dev->max_fib_size); hw_fib->header.SenderSize =
cpu_to_le16(dev->max_fib_size); /* ?? max_cmd_size */
fibptr->hw_fib_pa = hw_fib_pa; fibptr->hw_fib_pa = hw_fib_pa;
fibptr->hw_sgl_pa = hw_fib_pa +
offsetof(struct aac_hba_cmd_req, sge[2]);
/*
* one element is for the ptr to the separate sg list,
* second element for 32 byte alignment
*/
fibptr->hw_error_pa = hw_fib_pa +
offsetof(struct aac_native_hba, resp.resp_bytes[0]);
hw_fib = (struct hw_fib *)((unsigned char *)hw_fib + hw_fib = (struct hw_fib *)((unsigned char *)hw_fib +
dev->max_cmd_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 +
...@@ -282,7 +297,8 @@ void aac_fib_free(struct fib *fibptr) ...@@ -282,7 +297,8 @@ void aac_fib_free(struct fib *fibptr)
spin_lock_irqsave(&fibptr->dev->fib_lock, flags); spin_lock_irqsave(&fibptr->dev->fib_lock, flags);
if (unlikely(fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) if (unlikely(fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT))
aac_config.fib_timeouts++; aac_config.fib_timeouts++;
if (fibptr->hw_fib_va->header.XferState != 0) { if (!(fibptr->flags & FIB_CONTEXT_FLAG_NATIVE_HBA) &&
fibptr->hw_fib_va->header.XferState != 0) {
printk(KERN_WARNING "aac_fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n", printk(KERN_WARNING "aac_fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n",
(void*)fibptr, (void*)fibptr,
le32_to_cpu(fibptr->hw_fib_va->header.XferState)); le32_to_cpu(fibptr->hw_fib_va->header.XferState));
...@@ -510,8 +526,15 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, ...@@ -510,8 +526,15 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
* Map the fib into 32bits by using the fib number * Map the fib into 32bits by using the fib number
*/ */
hw_fib->header.SenderFibAddress = cpu_to_le32(((u32)(fibptr - dev->fibs)) << 2); hw_fib->header.SenderFibAddress =
hw_fib->header.Handle = (u32)(fibptr - dev->fibs) + 1; cpu_to_le32(((u32)(fibptr - dev->fibs)) << 2);
/* use the same shifted value for handle to be compatible
* with the new native hba command handle
*/
hw_fib->header.Handle =
cpu_to_le32((((u32)(fibptr - dev->fibs)) << 2) + 1);
/* /*
* Set FIB state to indicate where it came from and if we want a * Set FIB state to indicate where it came from and if we want a
* response from the adapter. Also load the command from the * response from the adapter. Also load the command from the
...@@ -679,6 +702,82 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, ...@@ -679,6 +702,82 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
return 0; return 0;
} }
int aac_hba_send(u8 command, struct fib *fibptr, fib_callback callback,
void *callback_data)
{
struct aac_dev *dev = fibptr->dev;
int wait;
unsigned long flags = 0;
unsigned long mflags = 0;
fibptr->flags = (FIB_CONTEXT_FLAG | FIB_CONTEXT_FLAG_NATIVE_HBA);
if (callback) {
wait = 0;
fibptr->callback = callback;
fibptr->callback_data = callback_data;
} else
wait = 1;
if (command == HBA_IU_TYPE_SCSI_CMD_REQ) {
struct aac_hba_cmd_req *hbacmd =
(struct aac_hba_cmd_req *)fibptr->hw_fib_va;
hbacmd->iu_type = command;
/* bit1 of request_id must be 0 */
hbacmd->request_id =
cpu_to_le32((((u32)(fibptr - dev->fibs)) << 2) + 1);
} else
return -EINVAL;
if (wait) {
spin_lock_irqsave(&dev->manage_lock, mflags);
if (dev->management_fib_count >= AAC_NUM_MGT_FIB) {
spin_unlock_irqrestore(&dev->manage_lock, mflags);
return -EBUSY;
}
dev->management_fib_count++;
spin_unlock_irqrestore(&dev->manage_lock, mflags);
spin_lock_irqsave(&fibptr->event_lock, flags);
}
if (aac_adapter_deliver(fibptr) != 0) {
if (wait) {
spin_unlock_irqrestore(&fibptr->event_lock, flags);
spin_lock_irqsave(&dev->manage_lock, mflags);
dev->management_fib_count--;
spin_unlock_irqrestore(&dev->manage_lock, mflags);
}
return -EBUSY;
}
FIB_COUNTER_INCREMENT(aac_config.NativeSent);
if (wait) {
spin_unlock_irqrestore(&fibptr->event_lock, flags);
/* Only set for first known interruptable command */
if (down_interruptible(&fibptr->event_wait)) {
fibptr->done = 2;
up(&fibptr->event_wait);
}
spin_lock_irqsave(&fibptr->event_lock, flags);
if ((fibptr->done == 0) || (fibptr->done == 2)) {
fibptr->done = 2; /* Tell interrupt we aborted */
spin_unlock_irqrestore(&fibptr->event_lock, flags);
return -ERESTARTSYS;
}
spin_unlock_irqrestore(&fibptr->event_lock, flags);
WARN_ON(fibptr->done == 0);
if (unlikely(fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT))
return -ETIMEDOUT;
return 0;
}
return -EINPROGRESS;
}
/** /**
* aac_consumer_get - get the top of the queue * aac_consumer_get - get the top of the queue
* @dev: Adapter * @dev: Adapter
...@@ -837,11 +936,17 @@ int aac_fib_complete(struct fib *fibptr) ...@@ -837,11 +936,17 @@ int aac_fib_complete(struct fib *fibptr)
{ {
struct hw_fib * hw_fib = fibptr->hw_fib_va; struct hw_fib * hw_fib = fibptr->hw_fib_va;
if (fibptr->flags & FIB_CONTEXT_FLAG_NATIVE_HBA) {
fib_dealloc(fibptr);
return 0;
}
/* /*
* Check for a fib which has already been completed * Check for a fib which has already been completed or with a
* status wait timeout
*/ */
if (hw_fib->header.XferState == 0) if (hw_fib->header.XferState == 0 || fibptr->done == 2)
return 0; return 0;
/* /*
* If we plan to do anything check the structure type first. * If we plan to do anything check the structure type first.
...@@ -994,20 +1099,9 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) ...@@ -994,20 +1099,9 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
lun = (container >> 16) & 0xFF; lun = (container >> 16) & 0xFF;
container = (u32)-1; container = (u32)-1;
channel = aac_phys_to_logical(channel); channel = aac_phys_to_logical(channel);
device_config_needed = device_config_needed = DELETE;
(((__le32 *)aifcmd->data)[0] ==
cpu_to_le32(AifRawDeviceRemove)) ? DELETE : ADD;
if (device_config_needed == ADD) {
device = scsi_device_lookup(
dev->scsi_host_ptr,
channel, id, lun);
if (device) {
scsi_remove_device(device);
scsi_device_put(device);
}
}
break; break;
/* /*
* Morph or Expand complete * Morph or Expand complete
*/ */
......
...@@ -346,7 +346,7 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index, int isAif, ...@@ -346,7 +346,7 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index, int isAif,
(fib_callback)aac_aif_callback, fibctx); (fib_callback)aac_aif_callback, fibctx);
} else { } else {
struct fib *fib = &dev->fibs[index]; struct fib *fib = &dev->fibs[index];
struct hw_fib * hwfib = fib->hw_fib_va; int start_callback = 0;
/* /*
* Remove this fib from the Outstanding I/O queue. * Remove this fib from the Outstanding I/O queue.
...@@ -364,45 +364,77 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index, int isAif, ...@@ -364,45 +364,77 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index, int isAif,
return 0; return 0;
} }
FIB_COUNTER_INCREMENT(aac_config.FibRecved);
if (fib->flags & FIB_CONTEXT_FLAG_NATIVE_HBA) {
if (isFastResponse)
fib->flags |= FIB_CONTEXT_FLAG_FASTRESP;
if (fib->callback) {
start_callback = 1;
} else {
unsigned long flagv;
int complete = 0;
dprintk((KERN_INFO "event_wait up\n"));
spin_lock_irqsave(&fib->event_lock, flagv);
if (fib->done == 2) {
fib->done = 1;
complete = 1;
} else {
fib->done = 1;
up(&fib->event_wait);
}
spin_unlock_irqrestore(&fib->event_lock, flagv);
spin_lock_irqsave(&dev->manage_lock, mflags);
dev->management_fib_count--;
spin_unlock_irqrestore(&dev->manage_lock,
mflags);
FIB_COUNTER_INCREMENT(aac_config.NativeRecved);
if (complete)
aac_fib_complete(fib);
}
} else {
struct hw_fib *hwfib = fib->hw_fib_va;
if (isFastResponse) { if (isFastResponse) {
/* /* Doctor the fib */
* Doctor the fib
*/
*(__le32 *)hwfib->data = cpu_to_le32(ST_OK); *(__le32 *)hwfib->data = cpu_to_le32(ST_OK);
hwfib->header.XferState |= cpu_to_le32(AdapterProcessed); hwfib->header.XferState |=
cpu_to_le32(AdapterProcessed);
fib->flags |= FIB_CONTEXT_FLAG_FASTRESP; fib->flags |= FIB_CONTEXT_FLAG_FASTRESP;
} }
FIB_COUNTER_INCREMENT(aac_config.FibRecved); if (hwfib->header.Command ==
cpu_to_le16(NuFileSystem)) {
if (hwfib->header.Command == cpu_to_le16(NuFileSystem))
{
__le32 *pstatus = (__le32 *)hwfib->data; __le32 *pstatus = (__le32 *)hwfib->data;
if (*pstatus & cpu_to_le32(0xffff0000)) if (*pstatus & cpu_to_le32(0xffff0000))
*pstatus = cpu_to_le32(ST_OK); *pstatus = cpu_to_le32(ST_OK);
} }
if (hwfib->header.XferState & cpu_to_le32(NoResponseExpected | Async)) if (hwfib->header.XferState &
{ cpu_to_le32(NoResponseExpected | Async)) {
if (hwfib->header.XferState & cpu_to_le32(NoResponseExpected)) if (hwfib->header.XferState & cpu_to_le32(
FIB_COUNTER_INCREMENT(aac_config.NoResponseRecved); NoResponseExpected))
FIB_COUNTER_INCREMENT(
aac_config.NoResponseRecved);
else else
FIB_COUNTER_INCREMENT(aac_config.AsyncRecved); FIB_COUNTER_INCREMENT(
/* aac_config.AsyncRecved);
* NOTE: we cannot touch the fib after this start_callback = 1;
* call, because it may have been deallocated.
*/
if (likely(fib->callback && fib->callback_data)) {
fib->flags &= FIB_CONTEXT_FLAG_FASTRESP;
fib->callback(fib->callback_data, fib);
} else
dev_info(&dev->pdev->dev,
"Invalid callback_fib[%d] (*%p)(%p)\n",
index, fib->callback, fib->callback_data);
} else { } else {
unsigned long flagv; unsigned long flagv;
int complete = 0;
dprintk((KERN_INFO "event_wait up\n")); dprintk((KERN_INFO "event_wait up\n"));
spin_lock_irqsave(&fib->event_lock, flagv); spin_lock_irqsave(&fib->event_lock, flagv);
if (!fib->done) { if (fib->done == 2) {
fib->done = 1;
complete = 1;
} else {
fib->done = 1; fib->done = 1;
up(&fib->event_wait); up(&fib->event_wait);
} }
...@@ -410,15 +442,27 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index, int isAif, ...@@ -410,15 +442,27 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index, int isAif,
spin_lock_irqsave(&dev->manage_lock, mflags); spin_lock_irqsave(&dev->manage_lock, mflags);
dev->management_fib_count--; dev->management_fib_count--;
spin_unlock_irqrestore(&dev->manage_lock, mflags); spin_unlock_irqrestore(&dev->manage_lock,
mflags);
FIB_COUNTER_INCREMENT(aac_config.NormalRecved); FIB_COUNTER_INCREMENT(aac_config.NormalRecved);
if (fib->done == 2) { if (complete)
spin_lock_irqsave(&fib->event_lock, flagv);
fib->done = 0;
spin_unlock_irqrestore(&fib->event_lock, flagv);
aac_fib_complete(fib); aac_fib_complete(fib);
} }
}
if (start_callback) {
/*
* NOTE: we cannot touch the fib after this
* call, because it may have been deallocated.
*/
if (likely(fib->callback && fib->callback_data)) {
fib->callback(fib->callback_data, fib);
} else {
aac_fib_complete(fib);
aac_fib_free(fib);
}
} }
return 0; return 0;
......
...@@ -1110,6 +1110,7 @@ static void __aac_shutdown(struct aac_dev * aac) ...@@ -1110,6 +1110,7 @@ static void __aac_shutdown(struct aac_dev * aac)
{ {
int i; int i;
aac->adapter_shutdown = 1;
aac_send_shutdown(aac); aac_send_shutdown(aac);
if (aac->aif_thread) { if (aac->aif_thread) {
......
...@@ -457,6 +457,11 @@ static int aac_src_check_health(struct aac_dev *dev) ...@@ -457,6 +457,11 @@ static int aac_src_check_health(struct aac_dev *dev)
return 0; return 0;
} }
static inline u32 aac_get_vector(struct aac_dev *dev)
{
return atomic_inc_return(&dev->msix_counter)%dev->max_msix;
}
/** /**
* aac_src_deliver_message * aac_src_deliver_message
* @fib: fib to issue * @fib: fib to issue
...@@ -470,67 +475,100 @@ static int aac_src_deliver_message(struct fib *fib) ...@@ -470,67 +475,100 @@ static int aac_src_deliver_message(struct fib *fib)
u32 fibsize; u32 fibsize;
dma_addr_t address; dma_addr_t address;
struct aac_fib_xporthdr *pFibX; struct aac_fib_xporthdr *pFibX;
int native_hba;
#if !defined(writeq) #if !defined(writeq)
unsigned long flags; unsigned long flags;
#endif #endif
u16 hdr_size = le16_to_cpu(fib->hw_fib_va->header.Size);
u16 vector_no; u16 vector_no;
atomic_inc(&q->numpending); atomic_inc(&q->numpending);
if (dev->msi_enabled && fib->hw_fib_va->header.Command != AifRequest && native_hba = (fib->flags & FIB_CONTEXT_FLAG_NATIVE_HBA) ? 1 : 0;
dev->max_msix > 1) {
if (dev->msi_enabled && dev->max_msix > 1 &&
(native_hba || fib->hw_fib_va->header.Command != AifRequest)) {
if ((dev->comm_interface == AAC_COMM_MESSAGE_TYPE3)
&& dev->sa_firmware)
vector_no = aac_get_vector(dev);
else
vector_no = fib->vector_no; vector_no = fib->vector_no;
if (native_hba) {
((struct aac_hba_cmd_req *)fib->hw_fib_va)->reply_qid
= vector_no;
((struct aac_hba_cmd_req *)fib->hw_fib_va)->request_id
+= (vector_no << 16);
} else {
fib->hw_fib_va->header.Handle += (vector_no << 16); fib->hw_fib_va->header.Handle += (vector_no << 16);
}
} else { } else {
vector_no = 0; vector_no = 0;
} }
atomic_inc(&dev->rrq_outstanding[vector_no]); atomic_inc(&dev->rrq_outstanding[vector_no]);
if ((dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) || if (native_hba) {
(dev->comm_interface == AAC_COMM_MESSAGE_TYPE3)) { address = fib->hw_fib_pa;
fibsize = (fib->hbacmd_size + 127) / 128 - 1;
if (fibsize > 31)
fibsize = 31;
address |= fibsize;
#if defined(writeq)
src_writeq(dev, MUnit.IQN_L, (u64)address);
#else
spin_lock_irqsave(&fib->dev->iq_lock, flags);
src_writel(dev, MUnit.IQN_H,
upper_32_bits(address) & 0xffffffff);
src_writel(dev, MUnit.IQN_L, address & 0xffffffff);
spin_unlock_irqrestore(&fib->dev->iq_lock, flags);
#endif
} else {
if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2 ||
dev->comm_interface == AAC_COMM_MESSAGE_TYPE3) {
/* Calculate the amount to the fibsize bits */ /* Calculate the amount to the fibsize bits */
fibsize = (hdr_size + 127) / 128 - 1; fibsize = (le16_to_cpu(fib->hw_fib_va->header.Size)
if (fibsize > (ALIGN32 - 1)) + 127) / 128 - 1;
return -EMSGSIZE;
/* New FIB header, 32-bit */ /* New FIB header, 32-bit */
address = fib->hw_fib_pa; address = fib->hw_fib_pa;
fib->hw_fib_va->header.StructType = FIB_MAGIC2; fib->hw_fib_va->header.StructType = FIB_MAGIC2;
fib->hw_fib_va->header.SenderFibAddress = (u32)address; fib->hw_fib_va->header.SenderFibAddress =
cpu_to_le32((u32)address);
fib->hw_fib_va->header.u.TimeStamp = 0; fib->hw_fib_va->header.u.TimeStamp = 0;
BUG_ON(upper_32_bits(address) != 0L); WARN_ON(((u32)(((address) >> 16) >> 16)) != 0L);
address |= fibsize;
} else { } else {
/* Calculate the amount to the fibsize bits */ /* Calculate the amount to the fibsize bits */
fibsize = (sizeof(struct aac_fib_xporthdr) + hdr_size + 127) / 128 - 1; fibsize = (sizeof(struct aac_fib_xporthdr) +
if (fibsize > (ALIGN32 - 1)) le16_to_cpu(fib->hw_fib_va->header.Size)
return -EMSGSIZE; + 127) / 128 - 1;
/* Fill XPORT header */ /* Fill XPORT header */
pFibX = (void *)fib->hw_fib_va - sizeof(struct aac_fib_xporthdr); pFibX = (struct aac_fib_xporthdr *)
pFibX->Handle = cpu_to_le32(fib->hw_fib_va->header.Handle); ((unsigned char *)fib->hw_fib_va -
pFibX->HostAddress = cpu_to_le64(fib->hw_fib_pa); sizeof(struct aac_fib_xporthdr));
pFibX->Size = cpu_to_le32(hdr_size); pFibX->Handle = fib->hw_fib_va->header.Handle;
pFibX->HostAddress =
/* cpu_to_le64((u64)fib->hw_fib_pa);
* The xport header has been 32-byte aligned for us so that fibsize pFibX->Size = cpu_to_le32(
* can be masked out of this address by hardware. -- BenC le16_to_cpu(fib->hw_fib_va->header.Size));
*/ address = fib->hw_fib_pa -
address = fib->hw_fib_pa - sizeof(struct aac_fib_xporthdr); (u64)sizeof(struct aac_fib_xporthdr);
if (address & (ALIGN32 - 1))
return -EINVAL;
address |= fibsize;
} }
if (fibsize > 31)
fibsize = 31;
address |= fibsize;
#if defined(writeq) #if defined(writeq)
src_writeq(dev, MUnit.IQ_L, (u64)address); src_writeq(dev, MUnit.IQ_L, (u64)address);
#else #else
spin_lock_irqsave(&fib->dev->iq_lock, flags); spin_lock_irqsave(&fib->dev->iq_lock, flags);
src_writel(dev, MUnit.IQ_H, upper_32_bits(address) & 0xffffffff); src_writel(dev, MUnit.IQ_H,
upper_32_bits(address) & 0xffffffff);
src_writel(dev, MUnit.IQ_L, address & 0xffffffff); src_writel(dev, MUnit.IQ_L, address & 0xffffffff);
spin_unlock_irqrestore(&fib->dev->iq_lock, flags); spin_unlock_irqrestore(&fib->dev->iq_lock, flags);
#endif #endif
}
return 0; return 0;
} }
......
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