Commit 28bc6fb9 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi

Pull SCSI updates from James Bottomley:
 "This is mostly updates of the usual driver suspects: arcmsr,
  scsi_debug, mpt3sas, lpfc, cxlflash, qla2xxx, aacraid, megaraid_sas,
  hisi_sas.

  We also have a rework of the libsas hotplug handling to make it more
  robust, a slew of 32 bit time conversions and fixes, and a host of the
  usual minor updates and style changes. The biggest potential for
  regressions is the libsas hotplug changes, but so far they seem stable
  under testing"

* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (313 commits)
  scsi: qla2xxx: Fix logo flag for qlt_free_session_done()
  scsi: arcmsr: avoid do_gettimeofday
  scsi: core: Add VENDOR_SPECIFIC sense code definitions
  scsi: qedi: Drop cqe response during connection recovery
  scsi: fas216: fix sense buffer initialization
  scsi: ibmvfc: Remove unneeded semicolons
  scsi: hisi_sas: fix a bug in hisi_sas_dev_gone()
  s...
parents 0be600a5 a2390348
......@@ -8,7 +8,10 @@ Main node required properties:
(b) "hisilicon,hip06-sas-v2" for v2 hw in hip06 chipset
(c) "hisilicon,hip07-sas-v2" for v2 hw in hip07 chipset
- sas-addr : array of 8 bytes for host SAS address
- reg : Address and length of the SAS register
- reg : Contains two regions. The first is the address and length of the SAS
register. The second is the address and length of CPLD register for
SGPIO control. The second is optional, and should be set only when
we use a CPLD for directly attached disk LED control.
- hisilicon,sas-syscon: phandle of syscon used for sas control
- ctrl-reset-reg : offset to controller reset register in ctrl reg
- ctrl-reset-sts-reg : offset to controller reset status register in ctrl reg
......
......@@ -224,6 +224,14 @@ mid to lowlevel SCSI driver interface
.. kernel-doc:: drivers/scsi/hosts.c
:export:
drivers/scsi/scsi_common.c
~~~~~~~~~~~~~~~~~~~~~~~~~~
general support functions
.. kernel-doc:: drivers/scsi/scsi_common.c
:export:
Transport classes
-----------------
......@@ -332,5 +340,5 @@ todo
~~~~
Parallel (fast/wide/ultra) SCSI, USB, SATA, SAS, Fibre Channel,
FireWire, ATAPI devices, Infiniband, I20, iSCSI, Parallel ports,
FireWire, ATAPI devices, Infiniband, I2O, iSCSI, Parallel ports,
netlink...
......@@ -958,7 +958,7 @@ mpt_put_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
{
u32 mf_dma_addr;
int req_offset;
u16 req_idx; /* Request index */
u16 req_idx; /* Request index */
/* ensure values are reset properly! */
mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx; /* byte */
......@@ -994,7 +994,7 @@ mpt_put_msg_frame_hi_pri(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
{
u32 mf_dma_addr;
int req_offset;
u16 req_idx; /* Request index */
u16 req_idx; /* Request index */
/* ensure values are reset properly! */
mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx;
......@@ -1128,11 +1128,12 @@ mpt_add_sge_64bit_1078(void *pAddr, u32 flagslength, dma_addr_t dma_addr)
static void
mpt_add_chain(void *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
{
SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
pChain->Length = cpu_to_le16(length);
pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT;
pChain->NextChainOffset = next;
pChain->Address = cpu_to_le32(dma_addr);
SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
pChain->Length = cpu_to_le16(length);
pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT;
pChain->NextChainOffset = next;
pChain->Address = cpu_to_le32(dma_addr);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
......@@ -1147,18 +1148,18 @@ mpt_add_chain(void *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
static void
mpt_add_chain_64bit(void *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
{
SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
u32 tmp = dma_addr & 0xFFFFFFFF;
SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
u32 tmp = dma_addr & 0xFFFFFFFF;
pChain->Length = cpu_to_le16(length);
pChain->Flags = (MPI_SGE_FLAGS_CHAIN_ELEMENT |
MPI_SGE_FLAGS_64_BIT_ADDRESSING);
pChain->Length = cpu_to_le16(length);
pChain->Flags = (MPI_SGE_FLAGS_CHAIN_ELEMENT |
MPI_SGE_FLAGS_64_BIT_ADDRESSING);
pChain->NextChainOffset = next;
pChain->NextChainOffset = next;
pChain->Address.Low = cpu_to_le32(tmp);
tmp = (u32)(upper_32_bits(dma_addr));
pChain->Address.High = cpu_to_le32(tmp);
pChain->Address.Low = cpu_to_le32(tmp);
tmp = (u32)(upper_32_bits(dma_addr));
pChain->Address.High = cpu_to_le32(tmp);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
......@@ -1360,7 +1361,7 @@ mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
ioc->add_sge(psge, flags_length, ioc->HostPageBuffer_dma);
ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE;
return 0;
return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
......@@ -2152,7 +2153,7 @@ mpt_suspend(struct pci_dev *pdev, pm_message_t state)
device_state);
/* put ioc into READY_STATE */
if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
if (SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
printk(MYIOC_s_ERR_FMT
"pci-suspend: IOC msg unit reset failed!\n", ioc->name);
}
......@@ -6348,7 +6349,7 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
u8 page_type = 0, extend_page;
unsigned long timeleft;
unsigned long flags;
int in_isr;
int in_isr;
u8 issue_hard_reset = 0;
u8 retry_count = 0;
......@@ -7697,7 +7698,7 @@ mpt_display_event_info(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply)
break;
}
if (ds)
strncpy(evStr, ds, EVENT_DESCR_STR_SZ);
strlcpy(evStr, ds, EVENT_DESCR_STR_SZ);
devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
......@@ -8092,15 +8093,15 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
static void
mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info, u8 cb_idx)
{
union loginfo_type {
u32 loginfo;
struct {
u32 subcode:16;
u32 code:8;
u32 originator:4;
u32 bus_type:4;
}dw;
};
union loginfo_type {
u32 loginfo;
struct {
u32 subcode:16;
u32 code:8;
u32 originator:4;
u32 bus_type:4;
} dw;
};
union loginfo_type sas_loginfo;
char *originator_desc = NULL;
char *code_desc = NULL;
......
......@@ -2481,24 +2481,13 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
else
karg.host_no = -1;
/* Reformat the fw_version into a string
*/
karg.fw_version[0] = ioc->facts.FWVersion.Struct.Major >= 10 ?
((ioc->facts.FWVersion.Struct.Major / 10) + '0') : '0';
karg.fw_version[1] = (ioc->facts.FWVersion.Struct.Major % 10 ) + '0';
karg.fw_version[2] = '.';
karg.fw_version[3] = ioc->facts.FWVersion.Struct.Minor >= 10 ?
((ioc->facts.FWVersion.Struct.Minor / 10) + '0') : '0';
karg.fw_version[4] = (ioc->facts.FWVersion.Struct.Minor % 10 ) + '0';
karg.fw_version[5] = '.';
karg.fw_version[6] = ioc->facts.FWVersion.Struct.Unit >= 10 ?
((ioc->facts.FWVersion.Struct.Unit / 10) + '0') : '0';
karg.fw_version[7] = (ioc->facts.FWVersion.Struct.Unit % 10 ) + '0';
karg.fw_version[8] = '.';
karg.fw_version[9] = ioc->facts.FWVersion.Struct.Dev >= 10 ?
((ioc->facts.FWVersion.Struct.Dev / 10) + '0') : '0';
karg.fw_version[10] = (ioc->facts.FWVersion.Struct.Dev % 10 ) + '0';
karg.fw_version[11] = '\0';
/* Reformat the fw_version into a string */
snprintf(karg.fw_version, sizeof(karg.fw_version),
"%.2hhu.%.2hhu.%.2hhu.%.2hhu",
ioc->facts.FWVersion.Struct.Major,
ioc->facts.FWVersion.Struct.Minor,
ioc->facts.FWVersion.Struct.Unit,
ioc->facts.FWVersion.Struct.Dev);
/* Issue a config request to get the device serial number
*/
......
......@@ -1165,7 +1165,6 @@ mptsas_schedule_target_reset(void *iocp)
* issue target reset to next device in the queue
*/
head = &hd->target_reset_list;
if (list_empty(head))
return;
......
......@@ -369,7 +369,6 @@ static int twa_aen_drain_queue(TW_Device_Extension *tw_dev, int no_check_reset)
static void twa_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_Header *header)
{
u32 local_time;
struct timeval time;
TW_Event *event;
unsigned short aen;
char host[16];
......@@ -392,8 +391,8 @@ static void twa_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_H
memset(event, 0, sizeof(TW_Event));
event->severity = TW_SEV_OUT(header->status_block.severity__reserved);
do_gettimeofday(&time);
local_time = (u32)(time.tv_sec - (sys_tz.tz_minuteswest * 60));
/* event->time_stamp_sec overflows in y2106 */
local_time = (u32)(ktime_get_real_seconds() - (sys_tz.tz_minuteswest * 60));
event->time_stamp_sec = local_time;
event->aen_code = aen;
event->retrieved = TW_AEN_NOT_RETRIEVED;
......@@ -473,11 +472,10 @@ static char *twa_aen_severity_lookup(unsigned char severity_code)
static void twa_aen_sync_time(TW_Device_Extension *tw_dev, int request_id)
{
u32 schedulertime;
struct timeval utc;
TW_Command_Full *full_command_packet;
TW_Command *command_packet;
TW_Param_Apache *param;
u32 local_time;
time64_t local_time;
/* Fill out the command packet */
full_command_packet = tw_dev->command_packet_virt[request_id];
......@@ -499,9 +497,8 @@ static void twa_aen_sync_time(TW_Device_Extension *tw_dev, int request_id)
/* Convert system time in UTC to local time seconds since last
Sunday 12:00AM */
do_gettimeofday(&utc);
local_time = (u32)(utc.tv_sec - (sys_tz.tz_minuteswest * 60));
schedulertime = local_time - (3 * 86400);
local_time = (ktime_get_real_seconds() - (sys_tz.tz_minuteswest * 60));
div_u64_rem(local_time - (3 * 86400), 604800, &schedulertime);
schedulertime = cpu_to_le32(schedulertime % 604800);
memcpy(param->data, &schedulertime, sizeof(u32));
......@@ -648,8 +645,7 @@ static long twa_chrdev_ioctl(struct file *file, unsigned int cmd, unsigned long
TW_Command_Full *full_command_packet;
TW_Compatibility_Info *tw_compat_info;
TW_Event *event;
struct timeval current_time;
u32 current_time_ms;
ktime_t current_time;
TW_Device_Extension *tw_dev = twa_device_extension_list[iminor(inode)];
int retval = TW_IOCTL_ERROR_OS_EFAULT;
void __user *argp = (void __user *)arg;
......@@ -840,17 +836,17 @@ static long twa_chrdev_ioctl(struct file *file, unsigned int cmd, unsigned long
break;
case TW_IOCTL_GET_LOCK:
tw_lock = (TW_Lock *)tw_ioctl->data_buffer;
do_gettimeofday(&current_time);
current_time_ms = (current_time.tv_sec * 1000) + (current_time.tv_usec / 1000);
current_time = ktime_get();
if ((tw_lock->force_flag == 1) || (tw_dev->ioctl_sem_lock == 0) || (current_time_ms >= tw_dev->ioctl_msec)) {
if ((tw_lock->force_flag == 1) || (tw_dev->ioctl_sem_lock == 0) ||
ktime_after(current_time, tw_dev->ioctl_time)) {
tw_dev->ioctl_sem_lock = 1;
tw_dev->ioctl_msec = current_time_ms + tw_lock->timeout_msec;
tw_dev->ioctl_time = ktime_add_ms(current_time, tw_lock->timeout_msec);
tw_ioctl->driver_command.status = 0;
tw_lock->time_remaining_msec = tw_lock->timeout_msec;
} else {
tw_ioctl->driver_command.status = TW_IOCTL_ERROR_STATUS_LOCKED;
tw_lock->time_remaining_msec = tw_dev->ioctl_msec - current_time_ms;
tw_lock->time_remaining_msec = ktime_ms_delta(tw_dev->ioctl_time, current_time);
}
break;
case TW_IOCTL_RELEASE_LOCK:
......
......@@ -666,7 +666,7 @@ typedef struct TAG_TW_Device_Extension {
unsigned char event_queue_wrapped;
unsigned int error_sequence_id;
int ioctl_sem_lock;
u32 ioctl_msec;
ktime_t ioctl_time;
int chrdev_request_id;
wait_queue_head_t ioctl_wqueue;
struct mutex ioctl_lock;
......
......@@ -221,7 +221,6 @@ static char *twl_aen_severity_lookup(unsigned char severity_code)
static void twl_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_Header *header)
{
u32 local_time;
struct timeval time;
TW_Event *event;
unsigned short aen;
char host[16];
......@@ -240,8 +239,8 @@ static void twl_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_H
memset(event, 0, sizeof(TW_Event));
event->severity = TW_SEV_OUT(header->status_block.severity__reserved);
do_gettimeofday(&time);
local_time = (u32)(time.tv_sec - (sys_tz.tz_minuteswest * 60));
/* event->time_stamp_sec overflows in y2106 */
local_time = (u32)(ktime_get_real_seconds() - (sys_tz.tz_minuteswest * 60));
event->time_stamp_sec = local_time;
event->aen_code = aen;
event->retrieved = TW_AEN_NOT_RETRIEVED;
......@@ -408,11 +407,10 @@ static int twl_aen_read_queue(TW_Device_Extension *tw_dev, int request_id)
static void twl_aen_sync_time(TW_Device_Extension *tw_dev, int request_id)
{
u32 schedulertime;
struct timeval utc;
TW_Command_Full *full_command_packet;
TW_Command *command_packet;
TW_Param_Apache *param;
u32 local_time;
time64_t local_time;
/* Fill out the command packet */
full_command_packet = tw_dev->command_packet_virt[request_id];
......@@ -434,10 +432,9 @@ static void twl_aen_sync_time(TW_Device_Extension *tw_dev, int request_id)
/* Convert system time in UTC to local time seconds since last
Sunday 12:00AM */
do_gettimeofday(&utc);
local_time = (u32)(utc.tv_sec - (sys_tz.tz_minuteswest * 60));
schedulertime = local_time - (3 * 86400);
schedulertime = cpu_to_le32(schedulertime % 604800);
local_time = (ktime_get_real_seconds() - (sys_tz.tz_minuteswest * 60));
div_u64_rem(local_time - (3 * 86400), 604800, &schedulertime);
schedulertime = cpu_to_le32(schedulertime);
memcpy(param->data, &schedulertime, sizeof(u32));
......
......@@ -42,6 +42,8 @@
#include <linux/highmem.h> /* For flush_kernel_dcache_page */
#include <linux/module.h>
#include <asm/unaligned.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
......@@ -913,8 +915,15 @@ static void setinqstr(struct aac_dev *dev, void *data, int tindex)
memset(str, ' ', sizeof(*str));
if (sup_adap_info->adapter_type_text[0]) {
char *cp = sup_adap_info->adapter_type_text;
int c;
char *cp;
char *cname = kmemdup(sup_adap_info->adapter_type_text,
sizeof(sup_adap_info->adapter_type_text),
GFP_ATOMIC);
if (!cname)
return;
cp = cname;
if ((cp[0] == 'A') && (cp[1] == 'O') && (cp[2] == 'C'))
inqstrcpy("SMC", str->vid);
else {
......@@ -923,7 +932,7 @@ static void setinqstr(struct aac_dev *dev, void *data, int tindex)
++cp;
c = *cp;
*cp = '\0';
inqstrcpy(sup_adap_info->adapter_type_text, str->vid);
inqstrcpy(cname, str->vid);
*cp = c;
while (*cp && *cp != ' ')
++cp;
......@@ -931,14 +940,11 @@ static void setinqstr(struct aac_dev *dev, void *data, int tindex)
while (*cp == ' ')
++cp;
/* last six chars reserved for vol type */
c = 0;
if (strlen(cp) > sizeof(str->pid)) {
c = cp[sizeof(str->pid)];
if (strlen(cp) > sizeof(str->pid))
cp[sizeof(str->pid)] = '\0';
}
inqstrcpy (cp, str->pid);
if (c)
cp[sizeof(str->pid)] = c;
kfree(cname);
} else {
struct aac_driver_ident *mp = aac_get_driver_ident(dev->cardtype);
......@@ -1660,87 +1666,309 @@ static int aac_adapter_hba(struct fib *fib, struct scsi_cmnd *cmd)
(void *) cmd);
}
int aac_issue_bmic_identify(struct aac_dev *dev, u32 bus, u32 target)
static int aac_send_safw_bmic_cmd(struct aac_dev *dev,
struct aac_srb_unit *srbu, void *xfer_buf, int xfer_len)
{
struct fib *fibptr;
struct aac_srb *srbcmd;
struct sgmap64 *sg64;
struct aac_ciss_identify_pd *identify_resp;
dma_addr_t addr;
u32 vbus, vid;
u16 fibsize, datasize;
int rcode = -ENOMEM;
struct fib *fibptr;
dma_addr_t addr;
int rcode;
int fibsize;
struct aac_srb *srb;
struct aac_srb_reply *srb_reply;
struct sgmap64 *sg64;
u32 vbus;
u32 vid;
if (!dev->sa_firmware)
return 0;
/* allocate FIB */
fibptr = aac_fib_alloc(dev);
if (!fibptr)
goto out;
return -ENOMEM;
fibsize = sizeof(struct aac_srb) -
sizeof(struct sgentry) + sizeof(struct sgentry64);
datasize = sizeof(struct aac_ciss_identify_pd);
aac_fib_init(fibptr);
fibptr->hw_fib_va->header.XferState &=
~cpu_to_le32(FastResponseCapable);
identify_resp = dma_alloc_coherent(&dev->pdev->dev, datasize, &addr,
GFP_KERNEL);
if (!identify_resp)
goto fib_free_ptr;
fibsize = sizeof(struct aac_srb) - sizeof(struct sgentry) +
sizeof(struct sgentry64);
vbus = (u32)le16_to_cpu(dev->supplement_adapter_info.virt_device_bus);
vid = (u32)le16_to_cpu(dev->supplement_adapter_info.virt_device_target);
/* allocate DMA buffer for response */
addr = dma_map_single(&dev->pdev->dev, xfer_buf, xfer_len,
DMA_BIDIRECTIONAL);
if (dma_mapping_error(&dev->pdev->dev, addr)) {
rcode = -ENOMEM;
goto fib_error;
}
aac_fib_init(fibptr);
srb = fib_data(fibptr);
memcpy(srb, &srbu->srb, sizeof(struct aac_srb));
srbcmd = (struct aac_srb *) fib_data(fibptr);
srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi);
srbcmd->channel = cpu_to_le32(vbus);
srbcmd->id = cpu_to_le32(vid);
srbcmd->lun = 0;
srbcmd->flags = cpu_to_le32(SRB_DataIn);
srbcmd->timeout = cpu_to_le32(10);
srbcmd->retry_limit = 0;
srbcmd->cdb_size = cpu_to_le32(12);
srbcmd->count = cpu_to_le32(datasize);
vbus = (u32)le16_to_cpu(
dev->supplement_adapter_info.virt_device_bus);
vid = (u32)le16_to_cpu(
dev->supplement_adapter_info.virt_device_target);
memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
srbcmd->cdb[0] = 0x26;
srbcmd->cdb[2] = (u8)((AAC_MAX_LUN + target) & 0x00FF);
srbcmd->cdb[6] = CISS_IDENTIFY_PHYSICAL_DEVICE;
/* set the common request fields */
srb->channel = cpu_to_le32(vbus);
srb->id = cpu_to_le32(vid);
srb->lun = 0;
srb->function = cpu_to_le32(SRBF_ExecuteScsi);
srb->timeout = 0;
srb->retry_limit = 0;
srb->cdb_size = cpu_to_le32(16);
srb->count = cpu_to_le32(xfer_len);
sg64 = (struct sgmap64 *)&srb->sg;
sg64->count = cpu_to_le32(1);
sg64->sg[0].addr[1] = cpu_to_le32(upper_32_bits(addr));
sg64->sg[0].addr[0] = cpu_to_le32(lower_32_bits(addr));
sg64->sg[0].count = cpu_to_le32(xfer_len);
sg64 = (struct sgmap64 *)&srbcmd->sg;
sg64->count = cpu_to_le32(1);
sg64->sg[0].addr[1] = cpu_to_le32((u32)(((addr) >> 16) >> 16));
sg64->sg[0].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff));
sg64->sg[0].count = cpu_to_le32(datasize);
/*
* Copy the updated data for other dumping or other usage if needed
*/
memcpy(&srbu->srb, srb, sizeof(struct aac_srb));
/* issue request to the controller */
rcode = aac_fib_send(ScsiPortCommand64, fibptr, fibsize, FsaNormal,
1, 1, NULL, NULL);
if (rcode == -ERESTARTSYS)
rcode = -ERESTART;
if (unlikely(rcode < 0))
goto bmic_error;
srb_reply = (struct aac_srb_reply *)fib_data(fibptr);
memcpy(&srbu->srb_reply, srb_reply, sizeof(struct aac_srb_reply));
bmic_error:
dma_unmap_single(&dev->pdev->dev, addr, xfer_len, DMA_BIDIRECTIONAL);
fib_error:
aac_fib_complete(fibptr);
aac_fib_free(fibptr);
return rcode;
}
static void aac_set_safw_target_qd(struct aac_dev *dev, int bus, int target)
{
struct aac_ciss_identify_pd *identify_resp;
rcode = aac_fib_send(ScsiPortCommand64,
fibptr, fibsize, FsaNormal, 1, 1, NULL, NULL);
if (dev->hba_map[bus][target].devtype != AAC_DEVTYPE_NATIVE_RAW)
return;
identify_resp = dev->hba_map[bus][target].safw_identify_resp;
if (identify_resp == NULL) {
dev->hba_map[bus][target].qd_limit = 32;
return;
}
if (identify_resp->current_queue_depth_limit <= 0 ||
identify_resp->current_queue_depth_limit > 32)
identify_resp->current_queue_depth_limit > 255)
dev->hba_map[bus][target].qd_limit = 32;
else
dev->hba_map[bus][target].qd_limit =
identify_resp->current_queue_depth_limit;
}
dma_free_coherent(&dev->pdev->dev, datasize, identify_resp, addr);
static int aac_issue_safw_bmic_identify(struct aac_dev *dev,
struct aac_ciss_identify_pd **identify_resp, u32 bus, u32 target)
{
int rcode = -ENOMEM;
int datasize;
struct aac_srb_unit srbu;
struct aac_srb *srbcmd;
struct aac_ciss_identify_pd *identify_reply;
aac_fib_complete(fibptr);
datasize = sizeof(struct aac_ciss_identify_pd);
identify_reply = kmalloc(datasize, GFP_KERNEL);
if (!identify_reply)
goto out;
memset(&srbu, 0, sizeof(struct aac_srb_unit));
srbcmd = &srbu.srb;
srbcmd->flags = cpu_to_le32(SRB_DataIn);
srbcmd->cdb[0] = 0x26;
srbcmd->cdb[2] = (u8)((AAC_MAX_LUN + target) & 0x00FF);
srbcmd->cdb[6] = CISS_IDENTIFY_PHYSICAL_DEVICE;
rcode = aac_send_safw_bmic_cmd(dev, &srbu, identify_reply, datasize);
if (unlikely(rcode < 0))
goto mem_free_all;
*identify_resp = identify_reply;
out:
return rcode;
mem_free_all:
kfree(identify_reply);
goto out;
}
static inline void aac_free_safw_ciss_luns(struct aac_dev *dev)
{
kfree(dev->safw_phys_luns);
dev->safw_phys_luns = NULL;
}
/**
* aac_get_safw_ciss_luns() Process topology change
* @dev: aac_dev structure
*
* Execute a CISS REPORT PHYS LUNS and process the results into
* the current hba_map.
*/
static int aac_get_safw_ciss_luns(struct aac_dev *dev)
{
int rcode = -ENOMEM;
int datasize;
struct aac_srb *srbcmd;
struct aac_srb_unit srbu;
struct aac_ciss_phys_luns_resp *phys_luns;
datasize = sizeof(struct aac_ciss_phys_luns_resp) +
(AAC_MAX_TARGETS - 1) * sizeof(struct _ciss_lun);
phys_luns = kmalloc(datasize, GFP_KERNEL);
if (phys_luns == NULL)
goto out;
memset(&srbu, 0, sizeof(struct aac_srb_unit));
srbcmd = &srbu.srb;
srbcmd->flags = cpu_to_le32(SRB_DataIn);
srbcmd->cdb[0] = CISS_REPORT_PHYSICAL_LUNS;
srbcmd->cdb[1] = 2; /* extended reporting */
srbcmd->cdb[8] = (u8)(datasize >> 8);
srbcmd->cdb[9] = (u8)(datasize);
rcode = aac_send_safw_bmic_cmd(dev, &srbu, phys_luns, datasize);
if (unlikely(rcode < 0))
goto mem_free_all;
if (phys_luns->resp_flag != 2) {
rcode = -ENOMSG;
goto mem_free_all;
}
dev->safw_phys_luns = phys_luns;
out:
return rcode;
mem_free_all:
kfree(phys_luns);
goto out;
}
static inline u32 aac_get_safw_phys_lun_count(struct aac_dev *dev)
{
return get_unaligned_be32(&dev->safw_phys_luns->list_length[0])/24;
}
static inline u32 aac_get_safw_phys_bus(struct aac_dev *dev, int lun)
{
return dev->safw_phys_luns->lun[lun].level2[1] & 0x3f;
}
static inline u32 aac_get_safw_phys_target(struct aac_dev *dev, int lun)
{
return dev->safw_phys_luns->lun[lun].level2[0];
}
static inline u32 aac_get_safw_phys_expose_flag(struct aac_dev *dev, int lun)
{
return dev->safw_phys_luns->lun[lun].bus >> 6;
}
static inline u32 aac_get_safw_phys_attribs(struct aac_dev *dev, int lun)
{
return dev->safw_phys_luns->lun[lun].node_ident[9];
}
static inline u32 aac_get_safw_phys_nexus(struct aac_dev *dev, int lun)
{
return *((u32 *)&dev->safw_phys_luns->lun[lun].node_ident[12]);
}
static inline u32 aac_get_safw_phys_device_type(struct aac_dev *dev, int lun)
{
return dev->safw_phys_luns->lun[lun].node_ident[8];
}
static inline void aac_free_safw_identify_resp(struct aac_dev *dev,
int bus, int target)
{
kfree(dev->hba_map[bus][target].safw_identify_resp);
dev->hba_map[bus][target].safw_identify_resp = NULL;
}
static inline void aac_free_safw_all_identify_resp(struct aac_dev *dev,
int lun_count)
{
int luns;
int i;
u32 bus;
u32 target;
luns = aac_get_safw_phys_lun_count(dev);
if (luns < lun_count)
lun_count = luns;
else if (lun_count < 0)
lun_count = luns;
for (i = 0; i < lun_count; i++) {
bus = aac_get_safw_phys_bus(dev, i);
target = aac_get_safw_phys_target(dev, i);
aac_free_safw_identify_resp(dev, bus, target);
}
}
static int aac_get_safw_attr_all_targets(struct aac_dev *dev)
{
int i;
int rcode = 0;
u32 lun_count;
u32 bus;
u32 target;
struct aac_ciss_identify_pd *identify_resp = NULL;
lun_count = aac_get_safw_phys_lun_count(dev);
for (i = 0; i < lun_count; ++i) {
bus = aac_get_safw_phys_bus(dev, i);
target = aac_get_safw_phys_target(dev, i);
rcode = aac_issue_safw_bmic_identify(dev,
&identify_resp, bus, target);
if (unlikely(rcode < 0))
goto free_identify_resp;
dev->hba_map[bus][target].safw_identify_resp = identify_resp;
}
fib_free_ptr:
aac_fib_free(fibptr);
out:
return rcode;
free_identify_resp:
aac_free_safw_all_identify_resp(dev, i);
goto out;
}
/**
* aac_update hba_map()- update current hba map with data from FW
* aac_set_safw_attr_all_targets- update current hba map with data from FW
* @dev: aac_dev structure
* @phys_luns: FW information from report phys luns
* @rescan: Indicates scan type
*
* Update our hba map with the information gathered from the FW
*/
void aac_update_hba_map(struct aac_dev *dev,
struct aac_ciss_phys_luns_resp *phys_luns, int rescan)
static void aac_set_safw_attr_all_targets(struct aac_dev *dev)
{
/* ok and extended reporting */
u32 lun_count, nexus;
......@@ -1748,24 +1976,21 @@ void aac_update_hba_map(struct aac_dev *dev,
u8 expose_flag, attribs;
u8 devtype;
lun_count = ((phys_luns->list_length[0] << 24)
+ (phys_luns->list_length[1] << 16)
+ (phys_luns->list_length[2] << 8)
+ (phys_luns->list_length[3])) / 24;
lun_count = aac_get_safw_phys_lun_count(dev);
dev->scan_counter++;
for (i = 0; i < lun_count; ++i) {
bus = phys_luns->lun[i].level2[1] & 0x3f;
target = phys_luns->lun[i].level2[0];
expose_flag = phys_luns->lun[i].bus >> 6;
attribs = phys_luns->lun[i].node_ident[9];
nexus = *((u32 *) &phys_luns->lun[i].node_ident[12]);
bus = aac_get_safw_phys_bus(dev, i);
target = aac_get_safw_phys_target(dev, i);
expose_flag = aac_get_safw_phys_expose_flag(dev, i);
attribs = aac_get_safw_phys_attribs(dev, i);
nexus = aac_get_safw_phys_nexus(dev, i);
if (bus >= AAC_MAX_BUSES || target >= AAC_MAX_TARGETS)
continue;
dev->hba_map[bus][target].expose = expose_flag;
if (expose_flag != 0) {
devtype = AAC_DEVTYPE_RAID_MEMBER;
goto update_devtype;
......@@ -1778,95 +2003,45 @@ void aac_update_hba_map(struct aac_dev *dev,
} else
devtype = AAC_DEVTYPE_ARC_RAW;
if (devtype != AAC_DEVTYPE_NATIVE_RAW)
goto update_devtype;
dev->hba_map[bus][target].scan_counter = dev->scan_counter;
if (aac_issue_bmic_identify(dev, bus, target) < 0)
dev->hba_map[bus][target].qd_limit = 32;
aac_set_safw_target_qd(dev, bus, target);
update_devtype:
if (rescan == AAC_INIT)
dev->hba_map[bus][target].devtype = devtype;
else
dev->hba_map[bus][target].new_devtype = devtype;
dev->hba_map[bus][target].devtype = devtype;
}
}
/**
* aac_report_phys_luns() Process topology change
* @dev: aac_dev structure
* @fibptr: fib pointer
*
* Execute a CISS REPORT PHYS LUNS and process the results into
* the current hba_map.
*/
int aac_report_phys_luns(struct aac_dev *dev, struct fib *fibptr, int rescan)
static int aac_setup_safw_targets(struct aac_dev *dev)
{
int fibsize, datasize;
struct aac_ciss_phys_luns_resp *phys_luns;
struct aac_srb *srbcmd;
struct sgmap64 *sg64;
dma_addr_t addr;
u32 vbus, vid;
int rcode = 0;
/* Thor SA Firmware -> CISS_REPORT_PHYSICAL_LUNS */
fibsize = sizeof(struct aac_srb) - sizeof(struct sgentry)
+ sizeof(struct sgentry64);
datasize = sizeof(struct aac_ciss_phys_luns_resp)
+ (AAC_MAX_TARGETS - 1) * sizeof(struct _ciss_lun);
phys_luns = dma_alloc_coherent(&dev->pdev->dev, datasize, &addr,
GFP_KERNEL);
if (phys_luns == NULL) {
rcode = -ENOMEM;
goto err_out;
}
vbus = (u32) le16_to_cpu(
dev->supplement_adapter_info.virt_device_bus);
vid = (u32) le16_to_cpu(
dev->supplement_adapter_info.virt_device_target);
rcode = aac_get_containers(dev);
if (unlikely(rcode < 0))
goto out;
aac_fib_init(fibptr);
rcode = aac_get_safw_ciss_luns(dev);
if (unlikely(rcode < 0))
goto out;
srbcmd = (struct aac_srb *) fib_data(fibptr);
srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi);
srbcmd->channel = cpu_to_le32(vbus);
srbcmd->id = cpu_to_le32(vid);
srbcmd->lun = 0;
srbcmd->flags = cpu_to_le32(SRB_DataIn);
srbcmd->timeout = cpu_to_le32(10);
srbcmd->retry_limit = 0;
srbcmd->cdb_size = cpu_to_le32(12);
srbcmd->count = cpu_to_le32(datasize);
rcode = aac_get_safw_attr_all_targets(dev);
if (unlikely(rcode < 0))
goto free_ciss_luns;
memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
srbcmd->cdb[0] = CISS_REPORT_PHYSICAL_LUNS;
srbcmd->cdb[1] = 2; /* extended reporting */
srbcmd->cdb[8] = (u8)(datasize >> 8);
srbcmd->cdb[9] = (u8)(datasize);
sg64 = (struct sgmap64 *) &srbcmd->sg;
sg64->count = cpu_to_le32(1);
sg64->sg[0].addr[1] = cpu_to_le32(upper_32_bits(addr));
sg64->sg[0].addr[0] = cpu_to_le32(lower_32_bits(addr));
sg64->sg[0].count = cpu_to_le32(datasize);
rcode = aac_fib_send(ScsiPortCommand64, fibptr, fibsize,
FsaNormal, 1, 1, NULL, NULL);
/* analyse data */
if (rcode >= 0 && phys_luns->resp_flag == 2) {
/* ok and extended reporting */
aac_update_hba_map(dev, phys_luns, rescan);
}
aac_set_safw_attr_all_targets(dev);
dma_free_coherent(&dev->pdev->dev, datasize, phys_luns, addr);
err_out:
aac_free_safw_all_identify_resp(dev, -1);
free_ciss_luns:
aac_free_safw_ciss_luns(dev);
out:
return rcode;
}
int aac_setup_safw_adapter(struct aac_dev *dev)
{
return aac_setup_safw_targets(dev);
}
int aac_get_adapter_info(struct aac_dev* dev)
{
struct fib* fibptr;
......@@ -1969,12 +2144,6 @@ int aac_get_adapter_info(struct aac_dev* dev)
dev->maximum_num_channels = le32_to_cpu(bus_info->BusCount);
}
if (!dev->sync_mode && dev->sa_firmware &&
dev->supplement_adapter_info.virt_device_bus != 0xffff) {
/* Thor SA Firmware -> CISS_REPORT_PHYSICAL_LUNS */
rcode = aac_report_phys_luns(dev, fibptr, AAC_INIT);
}
if (!dev->in_reset) {
char buffer[16];
tmp = le32_to_cpu(dev->adapter_info.kernelrev);
......@@ -2739,14 +2908,6 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
}
} else { /* check for physical non-dasd devices */
bus = aac_logical_to_phys(scmd_channel(scsicmd));
if (bus < AAC_MAX_BUSES && cid < AAC_MAX_TARGETS &&
(dev->hba_map[bus][cid].expose
== AAC_HIDE_DISK)){
if (scsicmd->cmnd[0] == INQUIRY) {
scsicmd->result = DID_NO_CONNECT << 16;
goto scsi_done_ret;
}
}
if (bus < AAC_MAX_BUSES && cid < AAC_MAX_TARGETS &&
dev->hba_map[bus][cid].devtype
......
......@@ -41,6 +41,7 @@
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <scsi/scsi_host.h>
/*------------------------------------------------------------------------------
* D E F I N E S
......@@ -97,7 +98,7 @@ enum {
#define PMC_GLOBAL_INT_BIT0 0x00000001
#ifndef AAC_DRIVER_BUILD
# define AAC_DRIVER_BUILD 50834
# define AAC_DRIVER_BUILD 50877
# define AAC_DRIVER_BRANCH "-custom"
#endif
#define MAXIMUM_NUM_CONTAINERS 32
......@@ -117,9 +118,13 @@ enum {
/* Thor: 5 phys. buses: #0: empty, 1-4: 256 targets each */
#define AAC_MAX_BUSES 5
#define AAC_MAX_TARGETS 256
#define AAC_BUS_TARGET_LOOP (AAC_MAX_BUSES * AAC_MAX_TARGETS)
#define AAC_MAX_NATIVE_SIZE 2048
#define FW_ERROR_BUFFER_SIZE 512
#define get_bus_number(x) (x/AAC_MAX_TARGETS)
#define get_target_number(x) (x%AAC_MAX_TARGETS)
/* Thor AIF events */
#define SA_AIF_HOTPLUG (1<<1)
#define SA_AIF_HARDWARE (1<<2)
......@@ -1334,17 +1339,17 @@ struct fib {
#define AAC_DEVTYPE_RAID_MEMBER 1
#define AAC_DEVTYPE_ARC_RAW 2
#define AAC_DEVTYPE_NATIVE_RAW 3
#define AAC_EXPOSE_DISK 0
#define AAC_HIDE_DISK 3
#define AAC_SAFW_RESCAN_DELAY (10 * HZ)
struct aac_hba_map_info {
__le32 rmw_nexus; /* nexus for native HBA devices */
u8 devtype; /* device type */
u8 new_devtype;
u8 reset_state; /* 0 - no reset, 1..x - */
/* after xth TM LUN reset */
u16 qd_limit;
u8 expose; /*checks if to expose or not*/
u32 scan_counter;
struct aac_ciss_identify_pd *safw_identify_resp;
};
/*
......@@ -1560,6 +1565,7 @@ struct aac_dev
spinlock_t fib_lock;
struct mutex ioctl_mutex;
struct mutex scan_mutex;
struct aac_queue_block *queues;
/*
* The user API will use an IOCTL to register itself to receive
......@@ -1605,6 +1611,7 @@ struct aac_dev
int maximum_num_channels;
struct fsa_dev_info *fsa_dev;
struct task_struct *thread;
struct delayed_work safw_rescan_work;
int cardtype;
/*
*This lock will protect the two 32-bit
......@@ -1668,9 +1675,11 @@ struct aac_dev
u32 vector_cap; /* MSI-X vector capab.*/
int msi_enabled; /* MSI/MSI-X enabled */
atomic_t msix_counter;
u32 scan_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];
struct aac_ciss_phys_luns_resp *safw_phys_luns;
u8 adapter_shutdown;
u32 handle_pci_error;
bool init_reset;
......@@ -2023,6 +2032,12 @@ struct aac_srb_reply
__le32 sense_data_size;
u8 sense_data[AAC_SENSE_BUFFERSIZE]; // Can this be SCSI_SENSE_BUFFERSIZE
};
struct aac_srb_unit {
struct aac_srb srb;
struct aac_srb_reply srb_reply;
};
/*
* SRB Flags
*/
......@@ -2627,16 +2642,41 @@ static inline int aac_adapter_check_health(struct aac_dev *dev)
return (dev)->a_ops.adapter_check_health(dev);
}
int aac_scan_host(struct aac_dev *dev);
static inline void aac_schedule_safw_scan_worker(struct aac_dev *dev)
{
schedule_delayed_work(&dev->safw_rescan_work, AAC_SAFW_RESCAN_DELAY);
}
static inline void aac_safw_rescan_worker(struct work_struct *work)
{
struct aac_dev *dev = container_of(to_delayed_work(work),
struct aac_dev, safw_rescan_work);
wait_event(dev->scsi_host_ptr->host_wait,
!scsi_host_in_recovery(dev->scsi_host_ptr));
aac_scan_host(dev);
}
static inline void aac_cancel_safw_rescan_worker(struct aac_dev *dev)
{
if (dev->sa_firmware)
cancel_delayed_work_sync(&dev->safw_rescan_work);
}
/* SCp.phase values */
#define AAC_OWNER_MIDLEVEL 0x101
#define AAC_OWNER_LOWLEVEL 0x102
#define AAC_OWNER_ERROR_HANDLER 0x103
#define AAC_OWNER_FIRMWARE 0x106
void aac_safw_rescan_worker(struct work_struct *work);
int aac_acquire_irq(struct aac_dev *dev);
void aac_free_irq(struct aac_dev *dev);
int aac_report_phys_luns(struct aac_dev *dev, struct fib *fibptr, int rescan);
int aac_issue_bmic_identify(struct aac_dev *dev, u32 bus, u32 target);
int aac_setup_safw_adapter(struct aac_dev *dev);
const char *aac_driverinfo(struct Scsi_Host *);
void aac_fib_vector_assign(struct aac_dev *dev);
struct fib *aac_fib_alloc(struct aac_dev *dev);
......
......@@ -1052,9 +1052,13 @@ static int aac_send_reset_adapter(struct aac_dev *dev, void __user *arg)
if (copy_from_user((void *)&reset, arg, sizeof(struct aac_reset_iop)))
return -EFAULT;
dev->adapter_shutdown = 1;
mutex_unlock(&dev->ioctl_mutex);
retval = aac_reset_adapter(dev, 0, reset.reset_type);
return retval;
mutex_lock(&dev->ioctl_mutex);
return retval;
}
int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg)
......
......@@ -42,6 +42,8 @@
#include <linux/completion.h>
#include <linux/mm.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_cmnd.h>
#include "aacraid.h"
......@@ -284,6 +286,38 @@ static void aac_queue_init(struct aac_dev * dev, struct aac_queue * q, u32 *mem,
q->entries = qsize;
}
static void aac_wait_for_io_completion(struct aac_dev *aac)
{
unsigned long flagv = 0;
int i = 0;
for (i = 60; i; --i) {
struct scsi_device *dev;
struct scsi_cmnd *command;
int active = 0;
__shost_for_each_device(dev, aac->scsi_host_ptr) {
spin_lock_irqsave(&dev->list_lock, flagv);
list_for_each_entry(command, &dev->cmd_list, list) {
if (command->SCp.phase == AAC_OWNER_FIRMWARE) {
active++;
break;
}
}
spin_unlock_irqrestore(&dev->list_lock, flagv);
if (active)
break;
}
/*
* We can exit If all the commands are complete
*/
if (active == 0)
break;
ssleep(1);
}
}
/**
* aac_send_shutdown - shutdown an adapter
* @dev: Adapter to shutdown
......@@ -295,12 +329,10 @@ int aac_send_shutdown(struct aac_dev * dev)
{
struct fib * fibctx;
struct aac_close *cmd;
int status;
int status = 0;
fibctx = aac_fib_alloc(dev);
if (!fibctx)
return -ENOMEM;
aac_fib_init(fibctx);
if (aac_adapter_check_health(dev))
return status;
if (!dev->adapter_shutdown) {
mutex_lock(&dev->ioctl_mutex);
......@@ -308,6 +340,13 @@ int aac_send_shutdown(struct aac_dev * dev)
mutex_unlock(&dev->ioctl_mutex);
}
aac_wait_for_io_completion(dev);
fibctx = aac_fib_alloc(dev);
if (!fibctx)
return -ENOMEM;
aac_fib_init(fibctx);
cmd = (struct aac_close *) fib_data(fibctx);
cmd->command = cpu_to_le32(VM_CloseAll);
cmd->cid = cpu_to_le32(0xfffffffe);
......
......@@ -33,6 +33,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/crash_dump.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/pci.h>
......@@ -1629,28 +1630,28 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type)
command->scsi_done(command);
}
/*
* Any Device that was already marked offline needs to be cleaned up
* Any Device that was already marked offline needs to be marked
* running
*/
__shost_for_each_device(dev, host) {
if (!scsi_device_online(dev)) {
sdev_printk(KERN_INFO, dev, "Removing offline device\n");
scsi_remove_device(dev);
scsi_device_put(dev);
}
if (!scsi_device_online(dev))
scsi_device_set_state(dev, SDEV_RUNNING);
}
retval = 0;
out:
aac->in_reset = 0;
scsi_unblock_requests(host);
/*
* Issue bus rescan to catch any configuration that might have
* occurred
*/
if (!retval) {
dev_info(&aac->pdev->dev, "Issuing bus rescan\n");
scsi_scan_host(host);
if (!retval && !is_kdump_kernel()) {
dev_info(&aac->pdev->dev, "Scheduling bus rescan\n");
aac_schedule_safw_scan_worker(aac);
}
if (jafo) {
spin_lock_irq(host->host_lock);
}
......@@ -1681,31 +1682,6 @@ int aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type)
*/
host = aac->scsi_host_ptr;
scsi_block_requests(host);
if (forced < 2) for (retval = 60; retval; --retval) {
struct scsi_device * dev;
struct scsi_cmnd * command;
int active = 0;
__shost_for_each_device(dev, host) {
spin_lock_irqsave(&dev->list_lock, flagv);
list_for_each_entry(command, &dev->cmd_list, list) {
if (command->SCp.phase == AAC_OWNER_FIRMWARE) {
active++;
break;
}
}
spin_unlock_irqrestore(&dev->list_lock, flagv);
if (active)
break;
}
/*
* We can exit If all the commands are complete
*/
if (active == 0)
break;
ssleep(1);
}
/* Quiesce build, flush cache, write through mode */
if (forced < 2)
......@@ -1874,42 +1850,124 @@ int aac_check_health(struct aac_dev * aac)
return BlinkLED;
}
static inline int is_safw_raid_volume(struct aac_dev *aac, int bus, int target)
{
return bus == CONTAINER_CHANNEL && target < aac->maximum_num_containers;
}
static struct scsi_device *aac_lookup_safw_scsi_device(struct aac_dev *dev,
int bus,
int target)
{
if (bus != CONTAINER_CHANNEL)
bus = aac_phys_to_logical(bus);
return scsi_device_lookup(dev->scsi_host_ptr, bus, target, 0);
}
static int aac_add_safw_device(struct aac_dev *dev, int bus, int target)
{
if (bus != CONTAINER_CHANNEL)
bus = aac_phys_to_logical(bus);
return scsi_add_device(dev->scsi_host_ptr, bus, target, 0);
}
static void aac_put_safw_scsi_device(struct scsi_device *sdev)
{
if (sdev)
scsi_device_put(sdev);
}
static void aac_resolve_luns(struct aac_dev *dev)
static void aac_remove_safw_device(struct aac_dev *dev, int bus, int target)
{
int bus, target, channel;
struct scsi_device *sdev;
u8 devtype;
u8 new_devtype;
for (bus = 0; bus < AAC_MAX_BUSES; bus++) {
for (target = 0; target < AAC_MAX_TARGETS; target++) {
sdev = aac_lookup_safw_scsi_device(dev, bus, target);
scsi_remove_device(sdev);
aac_put_safw_scsi_device(sdev);
}
if (bus == CONTAINER_CHANNEL)
channel = CONTAINER_CHANNEL;
else
channel = aac_phys_to_logical(bus);
static inline int aac_is_safw_scan_count_equal(struct aac_dev *dev,
int bus, int target)
{
return dev->hba_map[bus][target].scan_counter == dev->scan_counter;
}
devtype = dev->hba_map[bus][target].devtype;
new_devtype = dev->hba_map[bus][target].new_devtype;
static int aac_is_safw_target_valid(struct aac_dev *dev, int bus, int target)
{
if (is_safw_raid_volume(dev, bus, target))
return dev->fsa_dev[target].valid;
else
return aac_is_safw_scan_count_equal(dev, bus, target);
}
sdev = scsi_device_lookup(dev->scsi_host_ptr, channel,
target, 0);
static int aac_is_safw_device_exposed(struct aac_dev *dev, int bus, int target)
{
int is_exposed = 0;
struct scsi_device *sdev;
if (!sdev && new_devtype)
scsi_add_device(dev->scsi_host_ptr, channel,
target, 0);
else if (sdev && new_devtype != devtype)
scsi_remove_device(sdev);
else if (sdev && new_devtype == devtype)
scsi_rescan_device(&sdev->sdev_gendev);
sdev = aac_lookup_safw_scsi_device(dev, bus, target);
if (sdev)
is_exposed = 1;
aac_put_safw_scsi_device(sdev);
if (sdev)
scsi_device_put(sdev);
return is_exposed;
}
dev->hba_map[bus][target].devtype = new_devtype;
}
static int aac_update_safw_host_devices(struct aac_dev *dev)
{
int i;
int bus;
int target;
int is_exposed = 0;
int rcode = 0;
rcode = aac_setup_safw_adapter(dev);
if (unlikely(rcode < 0)) {
goto out;
}
for (i = 0; i < AAC_BUS_TARGET_LOOP; i++) {
bus = get_bus_number(i);
target = get_target_number(i);
is_exposed = aac_is_safw_device_exposed(dev, bus, target);
if (aac_is_safw_target_valid(dev, bus, target) && !is_exposed)
aac_add_safw_device(dev, bus, target);
else if (!aac_is_safw_target_valid(dev, bus, target) &&
is_exposed)
aac_remove_safw_device(dev, bus, target);
}
out:
return rcode;
}
static int aac_scan_safw_host(struct aac_dev *dev)
{
int rcode = 0;
rcode = aac_update_safw_host_devices(dev);
if (rcode)
aac_schedule_safw_scan_worker(dev);
return rcode;
}
int aac_scan_host(struct aac_dev *dev)
{
int rcode = 0;
mutex_lock(&dev->scan_mutex);
if (dev->sa_firmware)
rcode = aac_scan_safw_host(dev);
else
scsi_scan_host(dev->scsi_host_ptr);
mutex_unlock(&dev->scan_mutex);
return rcode;
}
/**
......@@ -1922,10 +1980,8 @@ static void aac_resolve_luns(struct aac_dev *dev)
*/
static void aac_handle_sa_aif(struct aac_dev *dev, struct fib *fibptr)
{
int i, bus, target, container, rcode = 0;
int i;
u32 events = 0;
struct fib *fib;
struct scsi_device *sdev;
if (fibptr->hbacmd_size & SA_AIF_HOTPLUG)
events = SA_AIF_HOTPLUG;
......@@ -1947,44 +2003,8 @@ static void aac_handle_sa_aif(struct aac_dev *dev, struct fib *fibptr)
case SA_AIF_LDEV_CHANGE:
case SA_AIF_BPCFG_CHANGE:
fib = aac_fib_alloc(dev);
if (!fib) {
pr_err("aac_handle_sa_aif: out of memory\n");
return;
}
for (bus = 0; bus < AAC_MAX_BUSES; bus++)
for (target = 0; target < AAC_MAX_TARGETS; target++)
dev->hba_map[bus][target].new_devtype = 0;
rcode = aac_report_phys_luns(dev, fib, AAC_RESCAN);
if (rcode != -ERESTARTSYS)
aac_fib_free(fib);
aac_resolve_luns(dev);
if (events == SA_AIF_LDEV_CHANGE ||
events == SA_AIF_BPCFG_CHANGE) {
aac_get_containers(dev);
for (container = 0; container <
dev->maximum_num_containers; ++container) {
sdev = scsi_device_lookup(dev->scsi_host_ptr,
CONTAINER_CHANNEL,
container, 0);
if (dev->fsa_dev[container].valid && !sdev) {
scsi_add_device(dev->scsi_host_ptr,
CONTAINER_CHANNEL,
container, 0);
} else if (!dev->fsa_dev[container].valid &&
sdev) {
scsi_remove_device(sdev);
scsi_device_put(sdev);
} else if (sdev) {
scsi_rescan_device(&sdev->sdev_gendev);
scsi_device_put(sdev);
}
}
}
aac_scan_host(dev);
break;
case SA_AIF_BPSTAT_CHANGE:
......
......@@ -683,6 +683,9 @@ static int aac_eh_abort(struct scsi_cmnd* cmd)
u32 bus, cid;
int ret = FAILED;
if (aac_adapter_check_health(aac))
return ret;
bus = aac_logical_to_phys(scmd_channel(cmd));
cid = scmd_id(cmd);
if (aac->hba_map[bus][cid].devtype == AAC_DEVTYPE_NATIVE_RAW) {
......@@ -690,7 +693,6 @@ static int aac_eh_abort(struct scsi_cmnd* cmd)
struct aac_hba_tm_req *tmf;
int status;
u64 address;
__le32 managed_request_id;
pr_err("%s: Host adapter abort request (%d,%d,%d,%d)\n",
AAC_DRIVERNAME,
......@@ -703,8 +705,6 @@ static int aac_eh_abort(struct scsi_cmnd* cmd)
(fib->flags & FIB_CONTEXT_FLAG_NATIVE_HBA) &&
(fib->callback_data == cmd)) {
found = 1;
managed_request_id = ((struct aac_hba_cmd_req *)
fib->hw_fib_va)->request_id;
break;
}
}
......@@ -1375,18 +1375,15 @@ static ssize_t aac_store_reset_adapter(struct device *device,
const char *buf, size_t count)
{
int retval = -EACCES;
int bled = 0;
struct aac_dev *aac;
if (!capable(CAP_SYS_ADMIN))
return retval;
aac = (struct aac_dev *)class_to_shost(device)->hostdata;
bled = buf[0] == '!' ? 1:0;
retval = aac_reset_adapter(aac, bled, IOP_HWSOFT_RESET);
retval = aac_reset_adapter(shost_priv(class_to_shost(device)),
buf[0] == '!', IOP_HWSOFT_RESET);
if (retval >= 0)
retval = count;
return retval;
}
......@@ -1689,6 +1686,9 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
spin_lock_init(&aac->fib_lock);
mutex_init(&aac->ioctl_mutex);
mutex_init(&aac->scan_mutex);
INIT_DELAYED_WORK(&aac->safw_rescan_work, aac_safw_rescan_worker);
/*
* Map in the registers from the adapter.
*/
......@@ -1792,7 +1792,8 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
error = scsi_add_host(shost, &pdev->dev);
if (error)
goto out_deinit;
scsi_scan_host(shost);
aac_scan_host(aac);
pci_enable_pcie_error_reporting(pdev);
pci_save_state(pdev);
......@@ -1877,6 +1878,7 @@ static int aac_suspend(struct pci_dev *pdev, pm_message_t state)
struct aac_dev *aac = (struct aac_dev *)shost->hostdata;
scsi_block_requests(shost);
aac_cancel_safw_rescan_worker(aac);
aac_send_shutdown(aac);
aac_release_resources(aac);
......@@ -1935,6 +1937,7 @@ static void aac_remove_one(struct pci_dev *pdev)
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct aac_dev *aac = (struct aac_dev *)shost->hostdata;
aac_cancel_safw_rescan_worker(aac);
scsi_remove_host(shost);
__aac_shutdown(aac);
......@@ -1992,6 +1995,7 @@ static pci_ers_result_t aac_pci_error_detected(struct pci_dev *pdev,
aac->handle_pci_error = 1;
scsi_block_requests(aac->scsi_host_ptr);
aac_cancel_safw_rescan_worker(aac);
aac_flush_ios(aac);
aac_release_resources(aac);
......@@ -2076,7 +2080,7 @@ static void aac_pci_resume(struct pci_dev *pdev)
if (sdev->sdev_state == SDEV_OFFLINE)
sdev->sdev_state = SDEV_RUNNING;
scsi_unblock_requests(aac->scsi_host_ptr);
scsi_scan_host(aac->scsi_host_ptr);
aac_scan_host(aac);
pci_save_state(pdev);
dev_err(&pdev->dev, "aacraid: PCI error - resume\n");
......
......@@ -329,6 +329,22 @@ int aac_sa_init(struct aac_dev *dev)
instance = dev->id;
name = dev->name;
/*
* Fill in the function dispatch table.
*/
dev->a_ops.adapter_interrupt = aac_sa_interrupt_adapter;
dev->a_ops.adapter_disable_int = aac_sa_disable_interrupt;
dev->a_ops.adapter_enable_int = aac_sa_enable_interrupt;
dev->a_ops.adapter_notify = aac_sa_notify_adapter;
dev->a_ops.adapter_sync_cmd = sa_sync_cmd;
dev->a_ops.adapter_check_health = aac_sa_check_health;
dev->a_ops.adapter_restart = aac_sa_restart_adapter;
dev->a_ops.adapter_start = aac_sa_start_adapter;
dev->a_ops.adapter_intr = aac_sa_intr;
dev->a_ops.adapter_deliver = aac_rx_deliver_producer;
dev->a_ops.adapter_ioremap = aac_sa_ioremap;
if (aac_sa_ioremap(dev, dev->base_size)) {
printk(KERN_WARNING "%s: unable to map adapter.\n", name);
goto error_iounmap;
......@@ -362,22 +378,6 @@ int aac_sa_init(struct aac_dev *dev)
msleep(1);
}
/*
* Fill in the function dispatch table.
*/
dev->a_ops.adapter_interrupt = aac_sa_interrupt_adapter;
dev->a_ops.adapter_disable_int = aac_sa_disable_interrupt;
dev->a_ops.adapter_enable_int = aac_sa_enable_interrupt;
dev->a_ops.adapter_notify = aac_sa_notify_adapter;
dev->a_ops.adapter_sync_cmd = sa_sync_cmd;
dev->a_ops.adapter_check_health = aac_sa_check_health;
dev->a_ops.adapter_restart = aac_sa_restart_adapter;
dev->a_ops.adapter_start = aac_sa_start_adapter;
dev->a_ops.adapter_intr = aac_sa_intr;
dev->a_ops.adapter_deliver = aac_rx_deliver_producer;
dev->a_ops.adapter_ioremap = aac_sa_ioremap;
/*
* First clear out all interrupts. Then enable the one's that
* we can handle.
......
This diff is collapsed.
This diff is collapsed.
......@@ -2011,7 +2011,7 @@ static void fas216_rq_sns_done(FAS216_Info *info, struct scsi_cmnd *SCpnt,
* have valid data in the sense buffer that could
* confuse the higher levels.
*/
memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));
memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
//printk("scsi%d.%c: sense buffer: ", info->host->host_no, '0' + SCpnt->device->id);
//{ int i; for (i = 0; i < 32; i++) printk("%02x ", SCpnt->sense_buffer[i]); printk("\n"); }
/*
......
......@@ -1957,7 +1957,7 @@ bfa_get_pciids(struct bfa_pciid_s **pciids, int *npciids)
{BFA_PCI_VENDOR_ID_BROCADE, BFA_PCI_DEVICE_ID_CT_FC},
};
*npciids = sizeof(__pciids) / sizeof(__pciids[0]);
*npciids = ARRAY_SIZE(__pciids);
*pciids = __pciids;
}
......
......@@ -35,10 +35,10 @@
#define BFA_TRC_TS(_trcm) \
({ \
struct timeval tv; \
struct timespec64 ts; \
\
do_gettimeofday(&tv); \
(tv.tv_sec*1000000+tv.tv_usec); \
ktime_get_ts64(&ts); \
(ts.tv_sec*1000000+ts.tv_nsec / 1000); \
})
#ifndef BFA_TRC_TS
......
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