Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6: (38 commits) [SCSI] More buffer->request_buffer changes [SCSI] mptfusion: bump version to 3.04.01 [SCSI] mptfusion: misc fix's [SCSI] mptfusion: firmware download boot fix's [SCSI] mptfusion: task abort fix's [SCSI] mptfusion: sas nexus loss support [SCSI] mptfusion: sas loginfo update [SCSI] mptfusion: mptctl panic when loading [SCSI] mptfusion: sas enclosures with smart drive [SCSI] NCR_D700: misc fixes (section and argument ordering) [SCSI] scsi_debug: must_check fixes [SCSI] scsi_transport_sas: kill the use of channel [SCSI] scsi_transport_sas: add expander backlink [SCSI] hide EH backup data outside the scsi_cmnd [SCSI] ibmvscsi: handle inactive SCSI target during probe [SCSI] ibmvscsi: allocate lpevents for ibmvscsi on iseries [SCSI] aic7[9x]xx: Remove last vestiges of reverse_scan [SCSI] aha152x: stop poking at saved scsi_cmnd members [SCSI] st.c: Improve sense output [SCSI] lpfc 8.1.7: Change version number to 8.1.7 ...
This commit is contained in:
commit
00ab956f2f
55 changed files with 805 additions and 681 deletions
|
@ -429,7 +429,7 @@ static inline void fcp_scsi_receive(fc_channel *fc, int token, int status, fc_hd
|
|||
|
||||
if (fcmd->data) {
|
||||
if (SCpnt->use_sg)
|
||||
dma_unmap_sg(fc->dev, (struct scatterlist *)SCpnt->buffer,
|
||||
dma_unmap_sg(fc->dev, (struct scatterlist *)SCpnt->request_buffer,
|
||||
SCpnt->use_sg,
|
||||
SCpnt->sc_data_direction);
|
||||
else
|
||||
|
@ -810,7 +810,7 @@ static int fcp_scsi_queue_it(fc_channel *fc, Scsi_Cmnd *SCpnt, fcp_cmnd *fcmd, i
|
|||
SCpnt->request_bufflen,
|
||||
SCpnt->sc_data_direction);
|
||||
} else {
|
||||
struct scatterlist *sg = (struct scatterlist *)SCpnt->buffer;
|
||||
struct scatterlist *sg = (struct scatterlist *)SCpnt->request_buffer;
|
||||
int nents;
|
||||
|
||||
FCD(("XXX: Use_sg %d %d\n", SCpnt->use_sg, sg->length))
|
||||
|
|
|
@ -48,10 +48,8 @@ config FUSION_SAS
|
|||
List of supported controllers:
|
||||
|
||||
LSISAS1064
|
||||
LSISAS1066
|
||||
LSISAS1068
|
||||
LSISAS1064E
|
||||
LSISAS1066E
|
||||
LSISAS1068E
|
||||
|
||||
config FUSION_MAX_SGE
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#EXTRA_CFLAGS += -DMPT_DEBUG_EXIT
|
||||
#EXTRA_CFLAGS += -DMPT_DEBUG_FAIL
|
||||
|
||||
|
||||
#
|
||||
# driver/module specifics...
|
||||
#
|
||||
|
|
|
@ -436,8 +436,6 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
|
|||
*/
|
||||
if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) {
|
||||
freereq = 0;
|
||||
devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p does not return Request frame\n",
|
||||
ioc->name, pEvReply));
|
||||
} else {
|
||||
devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
|
||||
ioc->name, pEvReply));
|
||||
|
@ -678,19 +676,19 @@ int
|
|||
mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
|
||||
{
|
||||
MPT_ADAPTER *ioc;
|
||||
const struct pci_device_id *id;
|
||||
|
||||
if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) {
|
||||
if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
|
||||
|
||||
/* call per pci device probe entry point */
|
||||
list_for_each_entry(ioc, &ioc_list, list) {
|
||||
if(dd_cbfunc->probe) {
|
||||
dd_cbfunc->probe(ioc->pcidev,
|
||||
ioc->pcidev->driver->id_table);
|
||||
}
|
||||
id = ioc->pcidev->driver ?
|
||||
ioc->pcidev->driver->id_table : NULL;
|
||||
if (dd_cbfunc->probe)
|
||||
dd_cbfunc->probe(ioc->pcidev, id);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1056,9 +1054,8 @@ mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
|
|||
|
||||
dinitprintk((MYIOC_s_INFO_FMT
|
||||
"host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",
|
||||
ioc->name,
|
||||
ioc->HostPageBuffer,
|
||||
ioc->HostPageBuffer_dma,
|
||||
ioc->name, ioc->HostPageBuffer,
|
||||
(u32)ioc->HostPageBuffer_dma,
|
||||
host_page_buffer_sz));
|
||||
ioc->alloc_total += host_page_buffer_sz;
|
||||
ioc->HostPageBuffer_sz = host_page_buffer_sz;
|
||||
|
@ -1380,6 +1377,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
printk(KERN_WARNING MYNAM
|
||||
": WARNING - %s did not initialize properly! (%d)\n",
|
||||
ioc->name, r);
|
||||
|
||||
list_del(&ioc->list);
|
||||
if (ioc->alt_ioc)
|
||||
ioc->alt_ioc->alt_ioc = NULL;
|
||||
|
@ -1762,9 +1760,9 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
|
|||
* chips (mpt_adapter_disable,
|
||||
* mpt_diag_reset)
|
||||
*/
|
||||
ioc->cached_fw = NULL;
|
||||
ddlprintk((MYIOC_s_INFO_FMT ": mpt_upload: alt_%s has cached_fw=%p \n",
|
||||
ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
|
||||
ioc->alt_ioc->cached_fw = NULL;
|
||||
}
|
||||
} else {
|
||||
printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
|
||||
|
@ -1885,7 +1883,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
|
|||
/* FIXME? Examine results here? */
|
||||
}
|
||||
|
||||
out:
|
||||
out:
|
||||
if ((ret != 0) && irq_allocated) {
|
||||
free_irq(ioc->pci_irq, ioc);
|
||||
if (mpt_msi_enable)
|
||||
|
@ -2670,6 +2668,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
|
|||
dinitprintk((MYIOC_s_INFO_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n",
|
||||
ioc->name, count));
|
||||
|
||||
ioc->aen_event_read_flag=0;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -2737,6 +2736,8 @@ mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
|
|||
if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
|
||||
ioc->cached_fw = ioc->alt_ioc->cached_fw; /* use alt_ioc's memory */
|
||||
ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
|
||||
ioc->alloc_total += size;
|
||||
ioc->alt_ioc->alloc_total -= size;
|
||||
} else {
|
||||
if ( (ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma) ) )
|
||||
ioc->alloc_total += size;
|
||||
|
@ -3166,6 +3167,7 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
|
|||
static int
|
||||
mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
|
||||
{
|
||||
MPT_ADAPTER *iocp=NULL;
|
||||
u32 diag0val;
|
||||
u32 doorbell;
|
||||
int hard_reset_done = 0;
|
||||
|
@ -3301,17 +3303,23 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
|
|||
/* FIXME? Examine results here? */
|
||||
}
|
||||
|
||||
if (ioc->cached_fw) {
|
||||
if (ioc->cached_fw)
|
||||
iocp = ioc;
|
||||
else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
|
||||
iocp = ioc->alt_ioc;
|
||||
if (iocp) {
|
||||
/* If the DownloadBoot operation fails, the
|
||||
* IOC will be left unusable. This is a fatal error
|
||||
* case. _diag_reset will return < 0
|
||||
*/
|
||||
for (count = 0; count < 30; count ++) {
|
||||
diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
|
||||
diag0val = CHIPREG_READ32(&iocp->chip->Diagnostic);
|
||||
if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
|
||||
break;
|
||||
}
|
||||
|
||||
dprintk((MYIOC_s_INFO_FMT "cached_fw: diag0val=%x count=%d\n",
|
||||
iocp->name, diag0val, count));
|
||||
/* wait 1 sec */
|
||||
if (sleepFlag == CAN_SLEEP) {
|
||||
msleep (1000);
|
||||
|
@ -3320,7 +3328,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
|
|||
}
|
||||
}
|
||||
if ((count = mpt_downloadboot(ioc,
|
||||
(MpiFwHeader_t *)ioc->cached_fw, sleepFlag)) < 0) {
|
||||
(MpiFwHeader_t *)iocp->cached_fw, sleepFlag)) < 0) {
|
||||
printk(KERN_WARNING MYNAM
|
||||
": firmware downloadboot failure (%d)!\n", count);
|
||||
}
|
||||
|
@ -3907,18 +3915,18 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
|
|||
|
||||
if (sleepFlag == CAN_SLEEP) {
|
||||
while (--cntdn) {
|
||||
msleep (1);
|
||||
intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
|
||||
if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
|
||||
break;
|
||||
msleep (1);
|
||||
count++;
|
||||
}
|
||||
} else {
|
||||
while (--cntdn) {
|
||||
mdelay (1);
|
||||
intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
|
||||
if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
|
||||
break;
|
||||
mdelay (1);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
@ -4883,6 +4891,7 @@ mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
|
|||
pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma);
|
||||
if (!pIoc4)
|
||||
return;
|
||||
ioc->alloc_total += iocpage4sz;
|
||||
} else {
|
||||
ioc4_dma = ioc->spi_data.IocPg4_dma;
|
||||
iocpage4sz = ioc->spi_data.IocPg4Sz;
|
||||
|
@ -4899,6 +4908,7 @@ mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
|
|||
} else {
|
||||
pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma);
|
||||
ioc->spi_data.pIocPg4 = NULL;
|
||||
ioc->alloc_total -= iocpage4sz;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5030,19 +5040,18 @@ SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
|
|||
EventAck_t *pAck;
|
||||
|
||||
if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
|
||||
printk(MYIOC_s_WARN_FMT "Unable to allocate event ACK "
|
||||
"request frame for Event=%x EventContext=%x EventData=%x!\n",
|
||||
ioc->name, evnp->Event, le32_to_cpu(evnp->EventContext),
|
||||
le32_to_cpu(evnp->Data[0]));
|
||||
dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
|
||||
ioc->name,__FUNCTION__));
|
||||
return -1;
|
||||
}
|
||||
memset(pAck, 0, sizeof(*pAck));
|
||||
|
||||
dprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name));
|
||||
devtverboseprintk((MYIOC_s_INFO_FMT "Sending EventAck\n", ioc->name));
|
||||
|
||||
pAck->Function = MPI_FUNCTION_EVENT_ACK;
|
||||
pAck->ChainOffset = 0;
|
||||
pAck->Reserved[0] = pAck->Reserved[1] = 0;
|
||||
pAck->MsgFlags = 0;
|
||||
pAck->Reserved1[0] = pAck->Reserved1[1] = pAck->Reserved1[2] = 0;
|
||||
pAck->Event = evnp->Event;
|
||||
pAck->EventContext = evnp->EventContext;
|
||||
|
||||
|
@ -5704,9 +5713,9 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
|
|||
break;
|
||||
case MPI_EVENT_EVENT_CHANGE:
|
||||
if (evData0)
|
||||
ds = "Events(ON) Change";
|
||||
ds = "Events ON";
|
||||
else
|
||||
ds = "Events(OFF) Change";
|
||||
ds = "Events OFF";
|
||||
break;
|
||||
case MPI_EVENT_INTEGRATED_RAID:
|
||||
{
|
||||
|
@ -5777,8 +5786,27 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
|
|||
break;
|
||||
case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
|
||||
snprintf(evStr, EVENT_DESCR_STR_SZ,
|
||||
"SAS Device Status Change: No Persistancy "
|
||||
"Added: id=%d", id);
|
||||
"SAS Device Status Change: No Persistancy: id=%d", id);
|
||||
break;
|
||||
case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
|
||||
snprintf(evStr, EVENT_DESCR_STR_SZ,
|
||||
"SAS Device Status Change: Internal Device Reset : id=%d", id);
|
||||
break;
|
||||
case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
|
||||
snprintf(evStr, EVENT_DESCR_STR_SZ,
|
||||
"SAS Device Status Change: Internal Task Abort : id=%d", id);
|
||||
break;
|
||||
case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
|
||||
snprintf(evStr, EVENT_DESCR_STR_SZ,
|
||||
"SAS Device Status Change: Internal Abort Task Set : id=%d", id);
|
||||
break;
|
||||
case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
|
||||
snprintf(evStr, EVENT_DESCR_STR_SZ,
|
||||
"SAS Device Status Change: Internal Clear Task Set : id=%d", id);
|
||||
break;
|
||||
case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
|
||||
snprintf(evStr, EVENT_DESCR_STR_SZ,
|
||||
"SAS Device Status Change: Internal Query Task : id=%d", id);
|
||||
break;
|
||||
default:
|
||||
snprintf(evStr, EVENT_DESCR_STR_SZ,
|
||||
|
@ -6034,7 +6062,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
|
|||
* @ioc: Pointer to MPT_ADAPTER structure
|
||||
* @log_info: U32 LogInfo reply word from the IOC
|
||||
*
|
||||
* Refer to lsi/fc_log.h.
|
||||
* Refer to lsi/mpi_log_fc.h.
|
||||
*/
|
||||
static void
|
||||
mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
|
||||
|
@ -6131,8 +6159,10 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
|
|||
"Invalid SAS Address", /* 01h */
|
||||
NULL, /* 02h */
|
||||
"Invalid Page", /* 03h */
|
||||
NULL, /* 04h */
|
||||
"Task Terminated" /* 05h */
|
||||
"Diag Message Error", /* 04h */
|
||||
"Task Terminated", /* 05h */
|
||||
"Enclosure Management", /* 06h */
|
||||
"Target Mode" /* 07h */
|
||||
};
|
||||
static char *pl_code_str[] = {
|
||||
NULL, /* 00h */
|
||||
|
@ -6158,7 +6188,7 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
|
|||
"IO Executed", /* 14h */
|
||||
"Persistant Reservation Out Not Affiliation Owner", /* 15h */
|
||||
"Open Transmit DMA Abort", /* 16h */
|
||||
NULL, /* 17h */
|
||||
"IO Device Missing Delay Retry", /* 17h */
|
||||
NULL, /* 18h */
|
||||
NULL, /* 19h */
|
||||
NULL, /* 1Ah */
|
||||
|
@ -6238,7 +6268,7 @@ static void
|
|||
mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
|
||||
{
|
||||
u32 status = ioc_status & MPI_IOCSTATUS_MASK;
|
||||
char *desc = "";
|
||||
char *desc = NULL;
|
||||
|
||||
switch (status) {
|
||||
case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
|
||||
|
@ -6348,7 +6378,7 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
|
|||
desc = "Others";
|
||||
break;
|
||||
}
|
||||
if (desc != "")
|
||||
if (desc != NULL)
|
||||
printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc);
|
||||
}
|
||||
|
||||
|
@ -6386,7 +6416,6 @@ EXPORT_SYMBOL(mpt_alloc_fw_memory);
|
|||
EXPORT_SYMBOL(mpt_free_fw_memory);
|
||||
EXPORT_SYMBOL(mptbase_sas_persist_operation);
|
||||
|
||||
|
||||
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
||||
/*
|
||||
* fusion_init - Fusion MPT base driver initialization routine.
|
||||
|
|
|
@ -75,8 +75,8 @@
|
|||
#define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR
|
||||
#endif
|
||||
|
||||
#define MPT_LINUX_VERSION_COMMON "3.04.00"
|
||||
#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.00"
|
||||
#define MPT_LINUX_VERSION_COMMON "3.04.01"
|
||||
#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.01"
|
||||
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
|
||||
|
||||
#define show_mptmod_ver(s,ver) \
|
||||
|
@ -307,8 +307,8 @@ typedef struct _SYSIF_REGS
|
|||
u32 HostIndex; /* 50 Host Index register */
|
||||
u32 Reserved4[15]; /* 54-8F */
|
||||
u32 Fubar; /* 90 For Fubar usage */
|
||||
u32 Reserved5[1050];/* 94-10F8 */
|
||||
u32 Reset_1078; /* 10FC Reset 1078 */
|
||||
u32 Reserved5[1050];/* 94-10F8 */
|
||||
u32 Reset_1078; /* 10FC Reset 1078 */
|
||||
} SYSIF_REGS;
|
||||
|
||||
/*
|
||||
|
@ -363,6 +363,7 @@ typedef struct _VirtDevice {
|
|||
#define MPT_TARGET_FLAGS_VALID_56 0x10
|
||||
#define MPT_TARGET_FLAGS_SAF_TE_ISSUED 0x20
|
||||
#define MPT_TARGET_FLAGS_RAID_COMPONENT 0x40
|
||||
#define MPT_TARGET_FLAGS_LED_ON 0x80
|
||||
|
||||
/*
|
||||
* /proc/mpt interface
|
||||
|
@ -634,7 +635,6 @@ typedef struct _MPT_ADAPTER
|
|||
u16 handle;
|
||||
int sas_index; /* index refrencing */
|
||||
MPT_SAS_MGMT sas_mgmt;
|
||||
int num_ports;
|
||||
struct work_struct sas_persist_task;
|
||||
|
||||
struct work_struct fc_setup_reset_work;
|
||||
|
@ -644,7 +644,6 @@ typedef struct _MPT_ADAPTER
|
|||
struct work_struct fc_rescan_work;
|
||||
char fc_rescan_work_q_name[KOBJ_NAME_LEN];
|
||||
struct workqueue_struct *fc_rescan_work_q;
|
||||
u8 port_serial_number;
|
||||
} MPT_ADAPTER;
|
||||
|
||||
/*
|
||||
|
@ -982,7 +981,7 @@ typedef struct _MPT_SCSI_HOST {
|
|||
wait_queue_head_t scandv_waitq;
|
||||
int scandv_wait_done;
|
||||
long last_queue_full;
|
||||
u8 mpt_pq_filter;
|
||||
u16 tm_iocstatus;
|
||||
} MPT_SCSI_HOST;
|
||||
|
||||
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
||||
|
|
|
@ -2332,7 +2332,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
|
|||
}
|
||||
|
||||
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
||||
/* Prototype Routine for the HP HOST INFO command.
|
||||
/* Prototype Routine for the HOST INFO command.
|
||||
*
|
||||
* Outputs: None.
|
||||
* Return: 0 if successful
|
||||
|
@ -2568,7 +2568,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
|
|||
}
|
||||
|
||||
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
||||
/* Prototype Routine for the HP TARGET INFO command.
|
||||
/* Prototype Routine for the TARGET INFO command.
|
||||
*
|
||||
* Outputs: None.
|
||||
* Return: 0 if successful
|
||||
|
|
|
@ -354,9 +354,6 @@ struct mpt_ioctl_command32 {
|
|||
|
||||
|
||||
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
||||
/*
|
||||
* HP Specific IOCTL Defines and Structures
|
||||
*/
|
||||
|
||||
#define CPQFCTS_IOC_MAGIC 'Z'
|
||||
#define HP_IOC_MAGIC 'Z'
|
||||
|
@ -364,8 +361,6 @@ struct mpt_ioctl_command32 {
|
|||
#define HP_GETHOSTINFO1 _IOR(HP_IOC_MAGIC, 20, hp_host_info_rev0_t)
|
||||
#define HP_GETTARGETINFO _IOR(HP_IOC_MAGIC, 21, hp_target_info_t)
|
||||
|
||||
/* All HP IOCTLs must include this header
|
||||
*/
|
||||
typedef struct _hp_header {
|
||||
unsigned int iocnum;
|
||||
unsigned int host;
|
||||
|
|
|
@ -77,10 +77,6 @@ MODULE_DESCRIPTION(my_NAME);
|
|||
MODULE_LICENSE("GPL");
|
||||
|
||||
/* Command line args */
|
||||
static int mpt_pq_filter = 0;
|
||||
module_param(mpt_pq_filter, int, 0);
|
||||
MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)");
|
||||
|
||||
#define MPTFC_DEV_LOSS_TMO (60)
|
||||
static int mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO; /* reasonable default */
|
||||
module_param(mptfc_dev_loss_tmo, int, 0);
|
||||
|
@ -513,8 +509,7 @@ mptfc_slave_alloc(struct scsi_device *sdev)
|
|||
|
||||
if (vtarget->num_luns == 0) {
|
||||
vtarget->ioc_id = hd->ioc->id;
|
||||
vtarget->tflags = MPT_TARGET_FLAGS_Q_YES |
|
||||
MPT_TARGET_FLAGS_VALID_INQUIRY;
|
||||
vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
|
||||
hd->Targets[sdev->id] = vtarget;
|
||||
}
|
||||
|
||||
|
@ -1129,13 +1124,6 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
hd->timer.data = (unsigned long) hd;
|
||||
hd->timer.function = mptscsih_timer_expired;
|
||||
|
||||
hd->mpt_pq_filter = mpt_pq_filter;
|
||||
|
||||
ddvprintk((MYIOC_s_INFO_FMT
|
||||
"mpt_pq_filter %x\n",
|
||||
ioc->name,
|
||||
mpt_pq_filter));
|
||||
|
||||
init_waitqueue_head(&hd->scandv_waitq);
|
||||
hd->scandv_wait_done = 0;
|
||||
hd->last_queue_full = 0;
|
||||
|
|
|
@ -67,20 +67,19 @@
|
|||
#define my_VERSION MPT_LINUX_VERSION_COMMON
|
||||
#define MYNAM "mptsas"
|
||||
|
||||
/*
|
||||
* Reserved channel for integrated raid
|
||||
*/
|
||||
#define MPTSAS_RAID_CHANNEL 1
|
||||
|
||||
MODULE_AUTHOR(MODULEAUTHOR);
|
||||
MODULE_DESCRIPTION(my_NAME);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static int mpt_pq_filter;
|
||||
module_param(mpt_pq_filter, int, 0);
|
||||
MODULE_PARM_DESC(mpt_pq_filter,
|
||||
"Enable peripheral qualifier filter: enable=1 "
|
||||
"(default=0)");
|
||||
|
||||
static int mpt_pt_clear;
|
||||
module_param(mpt_pt_clear, int, 0);
|
||||
MODULE_PARM_DESC(mpt_pt_clear,
|
||||
"Clear persistency table: enable=1 "
|
||||
" Clear persistency table: enable=1 "
|
||||
"(default=MPTSCSIH_PT_CLEAR=0)");
|
||||
|
||||
static int mptsasDoneCtx = -1;
|
||||
|
@ -144,7 +143,6 @@ struct mptsas_devinfo {
|
|||
* Specific details on ports, wide/narrow
|
||||
*/
|
||||
struct mptsas_portinfo_details{
|
||||
u8 port_id; /* port number provided to transport */
|
||||
u16 num_phys; /* number of phys belong to this port */
|
||||
u64 phy_bitmask; /* TODO, extend support for 255 phys */
|
||||
struct sas_rphy *rphy; /* transport layer rphy object */
|
||||
|
@ -350,10 +348,10 @@ mptsas_port_delete(struct mptsas_portinfo_details * port_details)
|
|||
port_info = port_details->port_info;
|
||||
phy_info = port_info->phy_info;
|
||||
|
||||
dsaswideprintk((KERN_DEBUG "%s: [%p]: port=%02d num_phys=%02d "
|
||||
dsaswideprintk((KERN_DEBUG "%s: [%p]: num_phys=%02d "
|
||||
"bitmask=0x%016llX\n",
|
||||
__FUNCTION__, port_details, port_details->port_id,
|
||||
port_details->num_phys, port_details->phy_bitmask));
|
||||
__FUNCTION__, port_details, port_details->num_phys,
|
||||
port_details->phy_bitmask));
|
||||
|
||||
for (i = 0; i < port_info->num_phys; i++, phy_info++) {
|
||||
if(phy_info->port_details != port_details)
|
||||
|
@ -462,9 +460,8 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
|
|||
* phy be removed by firmware events.
|
||||
*/
|
||||
dsaswideprintk((KERN_DEBUG
|
||||
"%s: [%p]: port=%d deleting phy = %d\n",
|
||||
__FUNCTION__, port_details,
|
||||
port_details->port_id, i));
|
||||
"%s: [%p]: deleting phy = %d\n",
|
||||
__FUNCTION__, port_details, i));
|
||||
port_details->num_phys--;
|
||||
port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
|
||||
memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
|
||||
|
@ -493,7 +490,6 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
|
|||
goto out;
|
||||
port_details->num_phys = 1;
|
||||
port_details->port_info = port_info;
|
||||
port_details->port_id = ioc->port_serial_number++;
|
||||
if (phy_info->phy_id < 64 )
|
||||
port_details->phy_bitmask |=
|
||||
(1 << phy_info->phy_id);
|
||||
|
@ -525,12 +521,8 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
|
|||
mptsas_get_port(phy_info_cmp);
|
||||
port_details->starget =
|
||||
mptsas_get_starget(phy_info_cmp);
|
||||
port_details->port_id =
|
||||
phy_info_cmp->port_details->port_id;
|
||||
port_details->num_phys =
|
||||
phy_info_cmp->port_details->num_phys;
|
||||
// port_info->port_serial_number--;
|
||||
ioc->port_serial_number--;
|
||||
if (!phy_info_cmp->port_details->num_phys)
|
||||
kfree(phy_info_cmp->port_details);
|
||||
} else
|
||||
|
@ -554,11 +546,11 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
|
|||
if (!port_details)
|
||||
continue;
|
||||
dsaswideprintk((KERN_DEBUG
|
||||
"%s: [%p]: phy_id=%02d port_id=%02d num_phys=%02d "
|
||||
"%s: [%p]: phy_id=%02d num_phys=%02d "
|
||||
"bitmask=0x%016llX\n",
|
||||
__FUNCTION__,
|
||||
port_details, i, port_details->port_id,
|
||||
port_details->num_phys, port_details->phy_bitmask));
|
||||
port_details, i, port_details->num_phys,
|
||||
port_details->phy_bitmask));
|
||||
dsaswideprintk((KERN_DEBUG"\t\tport = %p rphy=%p\n",
|
||||
port_details->port, port_details->rphy));
|
||||
}
|
||||
|
@ -651,16 +643,13 @@ mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
|
|||
static int
|
||||
mptsas_slave_configure(struct scsi_device *sdev)
|
||||
{
|
||||
struct Scsi_Host *host = sdev->host;
|
||||
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
|
||||
|
||||
/*
|
||||
* RAID volumes placed beyond the last expected port.
|
||||
* Ignore sending sas mode pages in that case..
|
||||
*/
|
||||
if (sdev->channel < hd->ioc->num_ports)
|
||||
sas_read_port_mode_page(sdev);
|
||||
if (sdev->channel == MPTSAS_RAID_CHANNEL)
|
||||
goto out;
|
||||
|
||||
sas_read_port_mode_page(sdev);
|
||||
|
||||
out:
|
||||
return mptscsih_slave_configure(sdev);
|
||||
}
|
||||
|
||||
|
@ -689,10 +678,7 @@ mptsas_target_alloc(struct scsi_target *starget)
|
|||
|
||||
hd->Targets[target_id] = vtarget;
|
||||
|
||||
/*
|
||||
* RAID volumes placed beyond the last expected port.
|
||||
*/
|
||||
if (starget->channel == hd->ioc->num_ports)
|
||||
if (starget->channel == MPTSAS_RAID_CHANNEL)
|
||||
goto out;
|
||||
|
||||
rphy = dev_to_rphy(starget->dev.parent);
|
||||
|
@ -743,7 +729,7 @@ mptsas_target_destroy(struct scsi_target *starget)
|
|||
if (!starget->hostdata)
|
||||
return;
|
||||
|
||||
if (starget->channel == hd->ioc->num_ports)
|
||||
if (starget->channel == MPTSAS_RAID_CHANNEL)
|
||||
goto out;
|
||||
|
||||
rphy = dev_to_rphy(starget->dev.parent);
|
||||
|
@ -783,10 +769,7 @@ mptsas_slave_alloc(struct scsi_device *sdev)
|
|||
starget = scsi_target(sdev);
|
||||
vdev->vtarget = starget->hostdata;
|
||||
|
||||
/*
|
||||
* RAID volumes placed beyond the last expected port.
|
||||
*/
|
||||
if (sdev->channel == hd->ioc->num_ports)
|
||||
if (sdev->channel == MPTSAS_RAID_CHANNEL)
|
||||
goto out;
|
||||
|
||||
rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
|
||||
|
@ -1608,11 +1591,7 @@ static int mptsas_probe_one_phy(struct device *dev,
|
|||
if (phy_info->sas_port_add_phy) {
|
||||
|
||||
if (!port) {
|
||||
port = sas_port_alloc(dev,
|
||||
phy_info->port_details->port_id);
|
||||
dsaswideprintk((KERN_DEBUG
|
||||
"sas_port_alloc: port=%p dev=%p port_id=%d\n",
|
||||
port, dev, phy_info->port_details->port_id));
|
||||
port = sas_port_alloc_num(dev);
|
||||
if (!port) {
|
||||
error = -ENOMEM;
|
||||
goto out;
|
||||
|
@ -1625,6 +1604,9 @@ static int mptsas_probe_one_phy(struct device *dev,
|
|||
goto out;
|
||||
}
|
||||
mptsas_set_port(phy_info, port);
|
||||
dsaswideprintk((KERN_DEBUG
|
||||
"sas_port_alloc: port=%p dev=%p port_id=%d\n",
|
||||
port, dev, port->port_identifier));
|
||||
}
|
||||
dsaswideprintk((KERN_DEBUG "sas_port_add_phy: phy_id=%d\n",
|
||||
phy_info->phy_id));
|
||||
|
@ -1736,7 +1718,6 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
|
|||
hba = NULL;
|
||||
}
|
||||
mutex_unlock(&ioc->sas_topology_mutex);
|
||||
ioc->num_ports = port_info->num_phys;
|
||||
|
||||
for (i = 0; i < port_info->num_phys; i++) {
|
||||
mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
|
||||
|
@ -1939,7 +1920,8 @@ mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
|
|||
expander_sas_address)
|
||||
continue;
|
||||
#ifdef MPT_DEBUG_SAS_WIDE
|
||||
dev_printk(KERN_DEBUG, &port->dev, "delete\n");
|
||||
dev_printk(KERN_DEBUG, &port->dev,
|
||||
"delete port (%d)\n", port->port_identifier);
|
||||
#endif
|
||||
sas_port_delete(port);
|
||||
mptsas_port_delete(phy_info->port_details);
|
||||
|
@ -1984,7 +1966,7 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
|
|||
if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
|
||||
goto out;
|
||||
for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
|
||||
scsi_add_device(ioc->sh, ioc->num_ports,
|
||||
scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
|
||||
ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
|
||||
}
|
||||
out:
|
||||
|
@ -2185,7 +2167,8 @@ mptsas_hotplug_work(void *arg)
|
|||
ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
|
||||
|
||||
#ifdef MPT_DEBUG_SAS_WIDE
|
||||
dev_printk(KERN_DEBUG, &port->dev, "delete\n");
|
||||
dev_printk(KERN_DEBUG, &port->dev,
|
||||
"delete port (%d)\n", port->port_identifier);
|
||||
#endif
|
||||
sas_port_delete(port);
|
||||
mptsas_port_delete(phy_info->port_details);
|
||||
|
@ -2289,35 +2272,26 @@ mptsas_hotplug_work(void *arg)
|
|||
mptsas_set_rphy(phy_info, rphy);
|
||||
break;
|
||||
case MPTSAS_ADD_RAID:
|
||||
sdev = scsi_device_lookup(
|
||||
ioc->sh,
|
||||
ioc->num_ports,
|
||||
ev->id,
|
||||
0);
|
||||
sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
|
||||
ev->id, 0);
|
||||
if (sdev) {
|
||||
scsi_device_put(sdev);
|
||||
break;
|
||||
}
|
||||
printk(MYIOC_s_INFO_FMT
|
||||
"attaching raid volume, channel %d, id %d\n",
|
||||
ioc->name, ioc->num_ports, ev->id);
|
||||
scsi_add_device(ioc->sh,
|
||||
ioc->num_ports,
|
||||
ev->id,
|
||||
0);
|
||||
ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
|
||||
scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, ev->id, 0);
|
||||
mpt_findImVolumes(ioc);
|
||||
break;
|
||||
case MPTSAS_DEL_RAID:
|
||||
sdev = scsi_device_lookup(
|
||||
ioc->sh,
|
||||
ioc->num_ports,
|
||||
ev->id,
|
||||
0);
|
||||
sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
|
||||
ev->id, 0);
|
||||
if (!sdev)
|
||||
break;
|
||||
printk(MYIOC_s_INFO_FMT
|
||||
"removing raid volume, channel %d, id %d\n",
|
||||
ioc->name, ioc->num_ports, ev->id);
|
||||
ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
|
||||
vdevice = sdev->hostdata;
|
||||
vdevice->vtarget->deleted = 1;
|
||||
mptsas_target_reset(ioc, vdevice->vtarget);
|
||||
|
@ -2723,7 +2697,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
hd->timer.data = (unsigned long) hd;
|
||||
hd->timer.function = mptscsih_timer_expired;
|
||||
|
||||
hd->mpt_pq_filter = mpt_pq_filter;
|
||||
ioc->sas_data.ptClear = mpt_pt_clear;
|
||||
|
||||
if (ioc->sas_data.ptClear==1) {
|
||||
|
@ -2731,12 +2704,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
|
||||
}
|
||||
|
||||
ddvprintk((MYIOC_s_INFO_FMT
|
||||
"mpt_pq_filter %x mpt_pq_filter %x\n",
|
||||
ioc->name,
|
||||
mpt_pq_filter,
|
||||
mpt_pq_filter));
|
||||
|
||||
init_waitqueue_head(&hd->scandv_waitq);
|
||||
hd->scandv_wait_done = 0;
|
||||
hd->last_queue_full = 0;
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
|
||||
#include "mptbase.h"
|
||||
#include "mptscsih.h"
|
||||
#include "lsi/mpi_log_sas.h"
|
||||
|
||||
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
||||
#define my_NAME "Fusion MPT SCSI Host driver"
|
||||
|
@ -127,7 +128,7 @@ static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
|
|||
static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
|
||||
static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
|
||||
static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
|
||||
static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
|
||||
static int SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
|
||||
|
||||
static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
|
||||
|
||||
|
@ -497,6 +498,34 @@ mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
|
|||
return SUCCESS;
|
||||
} /* mptscsih_AddSGE() */
|
||||
|
||||
static void
|
||||
mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget,
|
||||
U32 SlotStatus)
|
||||
{
|
||||
MPT_FRAME_HDR *mf;
|
||||
SEPRequest_t *SEPMsg;
|
||||
|
||||
if (ioc->bus_type == FC)
|
||||
return;
|
||||
|
||||
if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
|
||||
dfailprintk((MYIOC_s_WARN_FMT "%s: no msg frames!!\n",
|
||||
ioc->name,__FUNCTION__));
|
||||
return;
|
||||
}
|
||||
|
||||
SEPMsg = (SEPRequest_t *)mf;
|
||||
SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
|
||||
SEPMsg->Bus = vtarget->bus_id;
|
||||
SEPMsg->TargetID = vtarget->target_id;
|
||||
SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS;
|
||||
SEPMsg->SlotStatus = SlotStatus;
|
||||
devtverboseprintk((MYIOC_s_WARN_FMT
|
||||
"Sending SEP cmd=%x id=%d bus=%d\n",
|
||||
ioc->name, SlotStatus, SEPMsg->TargetID, SEPMsg->Bus));
|
||||
mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
|
||||
}
|
||||
|
||||
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
||||
/*
|
||||
* mptscsih_io_done - Main SCSI IO callback routine registered to
|
||||
|
@ -520,6 +549,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
|
|||
SCSIIORequest_t *pScsiReq;
|
||||
SCSIIOReply_t *pScsiReply;
|
||||
u16 req_idx, req_idx_MR;
|
||||
VirtDevice *vdev;
|
||||
VirtTarget *vtarget;
|
||||
|
||||
hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
|
||||
|
||||
|
@ -538,6 +569,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
|
|||
}
|
||||
|
||||
sc = hd->ScsiLookup[req_idx];
|
||||
hd->ScsiLookup[req_idx] = NULL;
|
||||
if (sc == NULL) {
|
||||
MPIHeader_t *hdr = (MPIHeader_t *)mf;
|
||||
|
||||
|
@ -553,6 +585,12 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if ((unsigned char *)mf != sc->host_scribble) {
|
||||
mptscsih_freeChainBuffers(ioc, req_idx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
sc->host_scribble = NULL;
|
||||
sc->result = DID_OK << 16; /* Set default reply as OK */
|
||||
pScsiReq = (SCSIIORequest_t *) mf;
|
||||
pScsiReply = (SCSIIOReply_t *) mr;
|
||||
|
@ -640,10 +678,36 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
|
|||
|
||||
if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
|
||||
hd->sel_timeout[pScsiReq->TargetID]++;
|
||||
|
||||
vdev = sc->device->hostdata;
|
||||
if (!vdev)
|
||||
break;
|
||||
vtarget = vdev->vtarget;
|
||||
if (vtarget->tflags & MPT_TARGET_FLAGS_LED_ON) {
|
||||
mptscsih_issue_sep_command(ioc, vtarget,
|
||||
MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED);
|
||||
vtarget->tflags &= ~MPT_TARGET_FLAGS_LED_ON;
|
||||
}
|
||||
break;
|
||||
|
||||
case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
|
||||
case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
|
||||
if ( ioc->bus_type == SAS ) {
|
||||
u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus);
|
||||
if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
|
||||
u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
|
||||
log_info &=SAS_LOGINFO_MASK;
|
||||
if (log_info == SAS_LOGINFO_NEXUS_LOSS) {
|
||||
sc->result = (DID_BUS_BUSY << 16);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Allow non-SAS & non-NEXUS_LOSS to drop into below code
|
||||
*/
|
||||
|
||||
case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
|
||||
case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
|
||||
/* Linux handles an unsolicited DID_RESET better
|
||||
* than an unsolicited DID_ABORT.
|
||||
|
@ -658,7 +722,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
|
|||
sc->result=DID_SOFT_ERROR << 16;
|
||||
else /* Sufficient data transfer occurred */
|
||||
sc->result = (DID_OK << 16) | scsi_status;
|
||||
dreplyprintk((KERN_NOTICE
|
||||
dreplyprintk((KERN_NOTICE
|
||||
"RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id));
|
||||
break;
|
||||
|
||||
|
@ -784,8 +848,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
|
|||
sc->request_bufflen, sc->sc_data_direction);
|
||||
}
|
||||
|
||||
hd->ScsiLookup[req_idx] = NULL;
|
||||
|
||||
sc->scsi_done(sc); /* Issue the command callback */
|
||||
|
||||
/* Free Chain buffers */
|
||||
|
@ -827,9 +889,17 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
|
|||
dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
|
||||
mf, SCpnt));
|
||||
|
||||
/* Free Chain buffers */
|
||||
mptscsih_freeChainBuffers(ioc, ii);
|
||||
|
||||
/* Free Message frames */
|
||||
mpt_free_msg_frame(ioc, mf);
|
||||
|
||||
if ((unsigned char *)mf != SCpnt->host_scribble)
|
||||
continue;
|
||||
|
||||
/* Set status, free OS resources (SG DMA buffers)
|
||||
* Do OS callback
|
||||
* Free driver resources (chain, msg buffers)
|
||||
*/
|
||||
if (SCpnt->use_sg) {
|
||||
pci_unmap_sg(ioc->pcidev,
|
||||
|
@ -845,12 +915,6 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
|
|||
SCpnt->result = DID_RESET << 16;
|
||||
SCpnt->host_scribble = NULL;
|
||||
|
||||
/* Free Chain buffers */
|
||||
mptscsih_freeChainBuffers(ioc, ii);
|
||||
|
||||
/* Free Message frames */
|
||||
mpt_free_msg_frame(ioc, mf);
|
||||
|
||||
SCpnt->scsi_done(SCpnt); /* Issue the command callback */
|
||||
}
|
||||
}
|
||||
|
@ -887,10 +951,10 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
|
|||
if ((sc = hd->ScsiLookup[ii]) != NULL) {
|
||||
|
||||
mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
|
||||
|
||||
if (mf == NULL)
|
||||
continue;
|
||||
dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
|
||||
hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
|
||||
|
||||
if ((mf->TargetID != ((u8)vdevice->vtarget->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun)))
|
||||
continue;
|
||||
|
||||
|
@ -899,6 +963,8 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
|
|||
hd->ScsiLookup[ii] = NULL;
|
||||
mptscsih_freeChainBuffers(hd->ioc, ii);
|
||||
mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
|
||||
if ((unsigned char *)mf != sc->host_scribble)
|
||||
continue;
|
||||
if (sc->use_sg) {
|
||||
pci_unmap_sg(hd->ioc->pcidev,
|
||||
(struct scatterlist *) sc->request_buffer,
|
||||
|
@ -1341,8 +1407,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
|
|||
goto fail;
|
||||
}
|
||||
|
||||
SCpnt->host_scribble = (unsigned char *)mf;
|
||||
hd->ScsiLookup[my_idx] = SCpnt;
|
||||
SCpnt->host_scribble = NULL;
|
||||
|
||||
mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
|
||||
dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
|
||||
|
@ -1529,6 +1595,12 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
|
|||
rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check IOCStatus from TM reply message
|
||||
*/
|
||||
if (hd->tm_iocstatus != MPI_IOCSTATUS_SUCCESS)
|
||||
rc = FAILED;
|
||||
|
||||
dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
|
||||
|
||||
return rc;
|
||||
|
@ -1654,6 +1726,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
|
|||
int scpnt_idx;
|
||||
int retval;
|
||||
VirtDevice *vdev;
|
||||
ulong sn = SCpnt->serial_number;
|
||||
|
||||
/* If we can't locate our host adapter structure, return FAILED status.
|
||||
*/
|
||||
|
@ -1707,6 +1780,11 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
|
|||
vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun,
|
||||
ctx2abort, mptscsih_get_tm_timeout(hd->ioc));
|
||||
|
||||
if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
|
||||
SCpnt->serial_number == sn) {
|
||||
retval = FAILED;
|
||||
}
|
||||
|
||||
printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
|
||||
hd->ioc->name,
|
||||
((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
|
||||
|
@ -2023,6 +2101,7 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
|
|||
DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
|
||||
|
||||
iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
|
||||
hd->tm_iocstatus = iocstatus;
|
||||
dtmprintk((MYIOC_s_WARN_FMT " SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",
|
||||
ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo)));
|
||||
/* Error? (anything non-zero?) */
|
||||
|
@ -2401,6 +2480,13 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR
|
|||
ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
|
||||
|
||||
ioc->eventContext++;
|
||||
if (hd->ioc->pcidev->vendor ==
|
||||
PCI_VENDOR_ID_IBM) {
|
||||
mptscsih_issue_sep_command(hd->ioc,
|
||||
vdev->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
|
||||
vdev->vtarget->tflags |=
|
||||
MPT_TARGET_FLAGS_LED_ON;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -2409,7 +2495,7 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR
|
|||
}
|
||||
}
|
||||
|
||||
static u32
|
||||
static int
|
||||
SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
|
||||
{
|
||||
MPT_SCSI_HOST *hd;
|
||||
|
|
|
@ -83,10 +83,6 @@ static int mpt_saf_te = MPTSCSIH_SAF_TE;
|
|||
module_param(mpt_saf_te, int, 0);
|
||||
MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1 (default=MPTSCSIH_SAF_TE=0)");
|
||||
|
||||
static int mpt_pq_filter = 0;
|
||||
module_param(mpt_pq_filter, int, 0);
|
||||
MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)");
|
||||
|
||||
static void mptspi_write_offset(struct scsi_target *, int);
|
||||
static void mptspi_write_width(struct scsi_target *, int);
|
||||
static int mptspi_write_spi_device_pg1(struct scsi_target *,
|
||||
|
@ -1047,14 +1043,12 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
hd->timer.function = mptscsih_timer_expired;
|
||||
|
||||
ioc->spi_data.Saf_Te = mpt_saf_te;
|
||||
hd->mpt_pq_filter = mpt_pq_filter;
|
||||
|
||||
hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
|
||||
ddvprintk((MYIOC_s_INFO_FMT
|
||||
"saf_te %x mpt_pq_filter %x\n",
|
||||
"saf_te %x\n",
|
||||
ioc->name,
|
||||
mpt_saf_te,
|
||||
mpt_pq_filter));
|
||||
mpt_saf_te));
|
||||
ioc->spi_data.noQas = 0;
|
||||
|
||||
init_waitqueue_head(&hd->scandv_waitq);
|
||||
|
|
|
@ -3451,12 +3451,12 @@ create_cmd (Scsi_Cmnd *cmd) {
|
|||
for (i = 0; cmd->use_sg ? (i < cmd->use_sg) : !i; cmd_datain += 4,
|
||||
cmd_dataout += 4, ++i) {
|
||||
u32 vbuf = cmd->use_sg
|
||||
? (u32)page_address(((struct scatterlist *)cmd->buffer)[i].page)+
|
||||
((struct scatterlist *)cmd->buffer)[i].offset
|
||||
? (u32)page_address(((struct scatterlist *)cmd->request_buffer)[i].page)+
|
||||
((struct scatterlist *)cmd->request_buffer)[i].offset
|
||||
: (u32)(cmd->request_buffer);
|
||||
u32 bbuf = virt_to_bus((void *)vbuf);
|
||||
u32 count = cmd->use_sg ?
|
||||
((struct scatterlist *)cmd->buffer)[i].length :
|
||||
((struct scatterlist *)cmd->request_buffer)[i].length :
|
||||
cmd->request_bufflen;
|
||||
|
||||
/*
|
||||
|
@ -5417,7 +5417,7 @@ insn_to_offset (Scsi_Cmnd *cmd, u32 *insn) {
|
|||
|
||||
if ((buffers = cmd->use_sg)) {
|
||||
for (offset = 0,
|
||||
segment = (struct scatterlist *) cmd->buffer;
|
||||
segment = (struct scatterlist *) cmd->request_buffer;
|
||||
buffers && !((found = ((ptr >= (char *)page_address(segment->page)+segment->offset) &&
|
||||
(ptr < ((char *)page_address(segment->page)+segment->offset+segment->length)))));
|
||||
--buffers, offset += segment->length, ++segment)
|
||||
|
|
|
@ -911,7 +911,7 @@ static void esp_get_dmabufs(struct NCR_ESP *esp, Scsi_Cmnd *sp)
|
|||
sp->SCp.ptr =
|
||||
(char *) virt_to_phys(sp->request_buffer);
|
||||
} else {
|
||||
sp->SCp.buffer = (struct scatterlist *) sp->buffer;
|
||||
sp->SCp.buffer = (struct scatterlist *) sp->request_buffer;
|
||||
sp->SCp.buffers_residual = sp->use_sg - 1;
|
||||
sp->SCp.this_residual = sp->SCp.buffer->length;
|
||||
if (esp->dma_mmu_get_scsi_sgl)
|
||||
|
|
|
@ -114,7 +114,7 @@ MODULE_DESCRIPTION("NCR Dual700 SCSI Driver");
|
|||
MODULE_LICENSE("GPL");
|
||||
module_param(NCR_D700, charp, 0);
|
||||
|
||||
static __u8 __initdata id_array[2*(MCA_MAX_SLOT_NR + 1)] =
|
||||
static __u8 __devinitdata id_array[2*(MCA_MAX_SLOT_NR + 1)] =
|
||||
{ [0 ... 2*(MCA_MAX_SLOT_NR + 1)-1] = 7 };
|
||||
|
||||
#ifdef MODULE
|
||||
|
@ -173,7 +173,7 @@ struct NCR_D700_private {
|
|||
char pad;
|
||||
};
|
||||
|
||||
static int
|
||||
static int __devinit
|
||||
NCR_D700_probe_one(struct NCR_D700_private *p, int siop, int irq,
|
||||
int slot, u32 region, int differential)
|
||||
{
|
||||
|
@ -243,7 +243,7 @@ NCR_D700_intr(int irq, void *data, struct pt_regs *regs)
|
|||
* essentially connectecd to the MCA bus independently, it is easier
|
||||
* to set them up as two separate host adapters, rather than one
|
||||
* adapter with two channels */
|
||||
static int
|
||||
static int __devinit
|
||||
NCR_D700_probe(struct device *dev)
|
||||
{
|
||||
struct NCR_D700_private *p;
|
||||
|
@ -329,7 +329,7 @@ NCR_D700_probe(struct device *dev)
|
|||
for (i = 0; i < 2; i++) {
|
||||
int err;
|
||||
|
||||
if ((err = NCR_D700_probe_one(p, i, slot, irq,
|
||||
if ((err = NCR_D700_probe_one(p, i, irq, slot,
|
||||
offset_addr + (0x80 * i),
|
||||
differential)) != 0)
|
||||
printk("D700: SIOP%d: probe failed, error = %d\n",
|
||||
|
@ -349,7 +349,7 @@ NCR_D700_probe(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
static void __devexit
|
||||
NCR_D700_remove_one(struct Scsi_Host *host)
|
||||
{
|
||||
scsi_remove_host(host);
|
||||
|
@ -359,7 +359,7 @@ NCR_D700_remove_one(struct Scsi_Host *host)
|
|||
release_region(host->base, 64);
|
||||
}
|
||||
|
||||
static int
|
||||
static int __devexit
|
||||
NCR_D700_remove(struct device *dev)
|
||||
{
|
||||
struct NCR_D700_private *p = dev_get_drvdata(dev);
|
||||
|
@ -380,7 +380,7 @@ static struct mca_driver NCR_D700_driver = {
|
|||
.name = "NCR_D700",
|
||||
.bus = &mca_bus_type,
|
||||
.probe = NCR_D700_probe,
|
||||
.remove = NCR_D700_remove,
|
||||
.remove = __devexit_p(NCR_D700_remove),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -551,6 +551,11 @@ struct aha152x_hostdata {
|
|||
struct aha152x_scdata {
|
||||
Scsi_Cmnd *next; /* next sc in queue */
|
||||
struct semaphore *sem; /* semaphore to block on */
|
||||
unsigned char cmd_len;
|
||||
unsigned char cmnd[MAX_COMMAND_SIZE];
|
||||
unsigned short use_sg;
|
||||
unsigned request_bufflen;
|
||||
void *request_buffer;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1006,11 +1011,20 @@ static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct semaphore *sem, int p
|
|||
return FAILED;
|
||||
}
|
||||
} else {
|
||||
struct aha152x_scdata *sc;
|
||||
|
||||
SCpnt->host_scribble = kmalloc(sizeof(struct aha152x_scdata), GFP_ATOMIC);
|
||||
if(SCpnt->host_scribble==0) {
|
||||
printk(ERR_LEAD "allocation failed\n", CMDINFO(SCpnt));
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
sc = SCDATA(SCpnt);
|
||||
memcpy(sc->cmnd, SCpnt->cmnd, sizeof(sc->cmnd));
|
||||
sc->request_buffer = SCpnt->request_buffer;
|
||||
sc->request_bufflen = SCpnt->request_bufflen;
|
||||
sc->use_sg = SCpnt->use_sg;
|
||||
sc->cmd_len = SCpnt->cmd_len;
|
||||
}
|
||||
|
||||
SCNEXT(SCpnt) = NULL;
|
||||
|
@ -1165,6 +1179,10 @@ static int aha152x_device_reset(Scsi_Cmnd * SCpnt)
|
|||
DECLARE_MUTEX_LOCKED(sem);
|
||||
struct timer_list timer;
|
||||
int ret, issued, disconnected;
|
||||
unsigned char old_cmd_len = SCpnt->cmd_len;
|
||||
unsigned short old_use_sg = SCpnt->use_sg;
|
||||
void *old_buffer = SCpnt->request_buffer;
|
||||
unsigned old_bufflen = SCpnt->request_bufflen;
|
||||
unsigned long flags;
|
||||
|
||||
#if defined(AHA152X_DEBUG)
|
||||
|
@ -1198,11 +1216,11 @@ static int aha152x_device_reset(Scsi_Cmnd * SCpnt)
|
|||
add_timer(&timer);
|
||||
down(&sem);
|
||||
del_timer(&timer);
|
||||
|
||||
SCpnt->cmd_len = SCpnt->old_cmd_len;
|
||||
SCpnt->use_sg = SCpnt->old_use_sg;
|
||||
SCpnt->request_buffer = SCpnt->buffer;
|
||||
SCpnt->request_bufflen = SCpnt->bufflen;
|
||||
|
||||
SCpnt->cmd_len = old_cmd_len;
|
||||
SCpnt->use_sg = old_use_sg;
|
||||
SCpnt->request_buffer = old_buffer;
|
||||
SCpnt->request_bufflen = old_bufflen;
|
||||
|
||||
DO_LOCK(flags);
|
||||
|
||||
|
@ -1565,6 +1583,9 @@ static void busfree_run(struct Scsi_Host *shpnt)
|
|||
#endif
|
||||
|
||||
if(DONE_SC->SCp.phase & check_condition) {
|
||||
struct scsi_cmnd *cmd = HOSTDATA(shpnt)->done_SC;
|
||||
struct aha152x_scdata *sc = SCDATA(cmd);
|
||||
|
||||
#if 0
|
||||
if(HOSTDATA(shpnt)->debug & debug_eh) {
|
||||
printk(ERR_LEAD "received sense: ", CMDINFO(DONE_SC));
|
||||
|
@ -1573,13 +1594,13 @@ static void busfree_run(struct Scsi_Host *shpnt)
|
|||
#endif
|
||||
|
||||
/* restore old command */
|
||||
memcpy((void *) DONE_SC->cmnd, (void *) DONE_SC->data_cmnd, sizeof(DONE_SC->data_cmnd));
|
||||
DONE_SC->request_buffer = DONE_SC->buffer;
|
||||
DONE_SC->request_bufflen = DONE_SC->bufflen;
|
||||
DONE_SC->use_sg = DONE_SC->old_use_sg;
|
||||
DONE_SC->cmd_len = DONE_SC->old_cmd_len;
|
||||
memcpy(cmd->cmnd, sc->cmnd, sizeof(sc->cmnd));
|
||||
cmd->request_buffer = sc->request_buffer;
|
||||
cmd->request_bufflen = sc->request_bufflen;
|
||||
cmd->use_sg = sc->use_sg;
|
||||
cmd->cmd_len = sc->cmd_len;
|
||||
|
||||
DONE_SC->SCp.Status = 0x02;
|
||||
cmd->SCp.Status = 0x02;
|
||||
|
||||
HOSTDATA(shpnt)->commands--;
|
||||
if (!HOSTDATA(shpnt)->commands)
|
||||
|
|
|
@ -7289,7 +7289,7 @@ ahd_reset_cmds_pending(struct ahd_softc *ahd)
|
|||
ahd->flags &= ~AHD_UPDATE_PEND_CMDS;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
ahd_done_with_status(struct ahd_softc *ahd, struct scb *scb, uint32_t status)
|
||||
{
|
||||
cam_status ostat;
|
||||
|
|
|
@ -242,25 +242,6 @@ ahd_print_path(struct ahd_softc *ahd, struct scb *scb)
|
|||
*/
|
||||
static uint32_t aic79xx_no_reset;
|
||||
|
||||
/*
|
||||
* Certain PCI motherboards will scan PCI devices from highest to lowest,
|
||||
* others scan from lowest to highest, and they tend to do all kinds of
|
||||
* strange things when they come into contact with PCI bridge chips. The
|
||||
* net result of all this is that the PCI card that is actually used to boot
|
||||
* the machine is very hard to detect. Most motherboards go from lowest
|
||||
* PCI slot number to highest, and the first SCSI controller found is the
|
||||
* one you boot from. The only exceptions to this are when a controller
|
||||
* has its BIOS disabled. So, we by default sort all of our SCSI controllers
|
||||
* from lowest PCI slot number to highest PCI slot number. We also force
|
||||
* all controllers with their BIOS disabled to the end of the list. This
|
||||
* works on *almost* all computers. Where it doesn't work, we have this
|
||||
* option. Setting this option to non-0 will reverse the order of the sort
|
||||
* to highest first, then lowest, but will still leave cards with their BIOS
|
||||
* disabled at the very end. That should fix everyone up unless there are
|
||||
* really strange cirumstances.
|
||||
*/
|
||||
static uint32_t aic79xx_reverse_scan;
|
||||
|
||||
/*
|
||||
* Should we force EXTENDED translation on a controller.
|
||||
* 0 == Use whatever is in the SEEPROM or default to off
|
||||
|
@ -350,7 +331,6 @@ MODULE_PARM_DESC(aic79xx,
|
|||
" periodically to prevent tag starvation.\n"
|
||||
" This may be required by some older disk\n"
|
||||
" or drives/RAID arrays.\n"
|
||||
" reverse_scan Sort PCI devices highest Bus/Slot to lowest\n"
|
||||
" tag_info:<tag_str> Set per-target tag depth\n"
|
||||
" global_tag_depth:<int> Global tag depth for all targets on all buses\n"
|
||||
" slewrate:<slewrate_list>Set the signal slew rate (0-15).\n"
|
||||
|
@ -1031,7 +1011,6 @@ aic79xx_setup(char *s)
|
|||
#ifdef AHD_DEBUG
|
||||
{ "debug", &ahd_debug },
|
||||
#endif
|
||||
{ "reverse_scan", &aic79xx_reverse_scan },
|
||||
{ "periodic_otag", &aic79xx_periodic_otag },
|
||||
{ "pci_parity", &aic79xx_pci_parity },
|
||||
{ "seltime", &aic79xx_seltime },
|
||||
|
|
|
@ -353,7 +353,6 @@ MODULE_PARM_DESC(aic7xxx,
|
|||
" periodically to prevent tag starvation.\n"
|
||||
" This may be required by some older disk\n"
|
||||
" drives or RAID arrays.\n"
|
||||
" reverse_scan Sort PCI devices highest Bus/Slot to lowest\n"
|
||||
" tag_info:<tag_str> Set per-target tag depth\n"
|
||||
" global_tag_depth:<int> Global tag depth for every target\n"
|
||||
" on every bus\n"
|
||||
|
|
|
@ -507,7 +507,7 @@ static __inline__ void initialize_SCp(Scsi_Cmnd *cmd)
|
|||
*/
|
||||
|
||||
if (cmd->use_sg) {
|
||||
cmd->SCp.buffer = (struct scatterlist *) cmd->buffer;
|
||||
cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer;
|
||||
cmd->SCp.buffers_residual = cmd->use_sg - 1;
|
||||
cmd->SCp.ptr = (char *)page_address(cmd->SCp.buffer->page)+
|
||||
cmd->SCp.buffer->offset;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* Additions for SCSI 3+ (SPC-3 T10/1416-D Rev 07 3 May 2002)
|
||||
* by D. Gilbert and aeb (20020609)
|
||||
* Additions for SPC-3 T10/1416-D Rev 21 22 Sept 2004, D. Gilbert 20041025
|
||||
* Update to SPC-4 T10/1713-D Rev 5a, 14 June 2006, D. Gilbert 20060702
|
||||
*/
|
||||
|
||||
#include <linux/blkdev.h>
|
||||
|
@ -36,55 +37,56 @@ static const char * cdb_byte0_names[] = {
|
|||
/* 00-03 */ "Test Unit Ready", "Rezero Unit/Rewind", NULL, "Request Sense",
|
||||
/* 04-07 */ "Format Unit/Medium", "Read Block Limits", NULL,
|
||||
"Reasssign Blocks",
|
||||
/* 08-0d */ "Read (6)", NULL, "Write (6)", "Seek (6)", NULL, NULL,
|
||||
/* 08-0d */ "Read(6)", NULL, "Write(6)", "Seek(6)", NULL, NULL,
|
||||
/* 0e-12 */ NULL, "Read Reverse", "Write Filemarks", "Space", "Inquiry",
|
||||
/* 13-16 */ "Verify (6)", "Recover Buffered Data", "Mode Select (6)",
|
||||
"Reserve (6)",
|
||||
/* 17-1a */ "Release (6)", "Copy", "Erase", "Mode Sense (6)",
|
||||
/* 13-16 */ "Verify(6)", "Recover Buffered Data", "Mode Select(6)",
|
||||
"Reserve(6)",
|
||||
/* 17-1a */ "Release(6)", "Copy", "Erase", "Mode Sense(6)",
|
||||
/* 1b-1d */ "Start/Stop Unit", "Receive Diagnostic", "Send Diagnostic",
|
||||
/* 1e-1f */ "Prevent/Allow Medium Removal", NULL,
|
||||
/* 20-22 */ NULL, NULL, NULL,
|
||||
/* 23-28 */ "Read Format Capacities", "Set Window",
|
||||
"Read Capacity (10)", NULL, NULL, "Read (10)",
|
||||
/* 29-2d */ "Read Generation", "Write (10)", "Seek (10)", "Erase (10)",
|
||||
"Read updated block",
|
||||
/* 2e-31 */ "Write Verify (10)", "Verify (10)", "Search High", "Search Equal",
|
||||
"Read Capacity(10)", NULL, NULL, "Read(10)",
|
||||
/* 29-2d */ "Read Generation", "Write(10)", "Seek(10)", "Erase(10)",
|
||||
"Read updated block",
|
||||
/* 2e-31 */ "Write Verify(10)", "Verify(10)", "Search High", "Search Equal",
|
||||
/* 32-34 */ "Search Low", "Set Limits", "Prefetch/Read Position",
|
||||
/* 35-37 */ "Synchronize Cache (10)", "Lock/Unlock Cache (10)",
|
||||
/* 35-37 */ "Synchronize Cache(10)", "Lock/Unlock Cache(10)",
|
||||
"Read Defect Data(10)",
|
||||
/* 38-3c */ "Medium Scan", "Compare", "Copy Verify", "Write Buffer",
|
||||
"Read Buffer",
|
||||
/* 3d-3f */ "Update Block", "Read Long (10)", "Write Long (10)",
|
||||
/* 40-41 */ "Change Definition", "Write Same (10)",
|
||||
/* 3d-3f */ "Update Block", "Read Long(10)", "Write Long(10)",
|
||||
/* 40-41 */ "Change Definition", "Write Same(10)",
|
||||
/* 42-48 */ "Read sub-channel", "Read TOC/PMA/ATIP", "Read density support",
|
||||
"Play audio (10)", "Get configuration", "Play audio msf",
|
||||
"Play audio(10)", "Get configuration", "Play audio msf",
|
||||
"Play audio track/index",
|
||||
/* 49-4f */ "Play track relative (10)", "Get event status notification",
|
||||
/* 49-4f */ "Play track relative(10)", "Get event status notification",
|
||||
"Pause/resume", "Log Select", "Log Sense", "Stop play/scan",
|
||||
NULL,
|
||||
/* 50-55 */ "Xdwrite", "Xpwrite, Read disk info", "Xdread, Read track info",
|
||||
"Reserve track", "Send OPC info", "Mode Select (10)",
|
||||
/* 56-5b */ "Reserve (10)", "Release (10)", "Repair track", "Read master cue",
|
||||
"Mode Sense (10)", "Close track/session",
|
||||
"Reserve track", "Send OPC info", "Mode Select(10)",
|
||||
/* 56-5b */ "Reserve(10)", "Release(10)", "Repair track", "Read master cue",
|
||||
"Mode Sense(10)", "Close track/session",
|
||||
/* 5c-5f */ "Read buffer capacity", "Send cue sheet", "Persistent reserve in",
|
||||
"Persistent reserve out",
|
||||
/* 60-67 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/* 68-6f */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/* 70-77 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/* 78-7f */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, "Variable length",
|
||||
/* 80-84 */ "Xdwrite (16)", "Rebuild (16)", "Regenerate (16)", "Extended copy",
|
||||
/* 80-84 */ "Xdwrite(16)", "Rebuild(16)", "Regenerate(16)", "Extended copy",
|
||||
"Receive copy results",
|
||||
/* 85-89 */ "Memory Export In (16)", "Access control in", "Access control out",
|
||||
"Read (16)", "Memory Export Out (16)",
|
||||
/* 8a-8f */ "Write (16)", NULL, "Read attributes", "Write attributes",
|
||||
"Write and verify (16)", "Verify (16)",
|
||||
/* 90-94 */ "Pre-fetch (16)", "Synchronize cache (16)",
|
||||
"Lock/unlock cache (16)", "Write same (16)", NULL,
|
||||
/* 85-89 */ "ATA command pass through(16)", "Access control in",
|
||||
"Access control out", "Read(16)", "Memory Export Out(16)",
|
||||
/* 8a-8f */ "Write(16)", NULL, "Read attributes", "Write attributes",
|
||||
"Write and verify(16)", "Verify(16)",
|
||||
/* 90-94 */ "Pre-fetch(16)", "Synchronize cache(16)",
|
||||
"Lock/unlock cache(16)", "Write same(16)", NULL,
|
||||
/* 95-99 */ NULL, NULL, NULL, NULL, NULL,
|
||||
/* 9a-9f */ NULL, NULL, NULL, NULL, "Service action in (16)",
|
||||
"Service action out (16)",
|
||||
/* a0-a5 */ "Report luns", "Blank", "Send event", "Maintenance in",
|
||||
"Maintenance out", "Move medium/play audio(12)",
|
||||
/* 9a-9f */ NULL, NULL, NULL, NULL, "Service action in(16)",
|
||||
"Service action out(16)",
|
||||
/* a0-a5 */ "Report luns", "ATA command pass through(12)/Blank",
|
||||
"Security protocol in", "Maintenance in", "Maintenance out",
|
||||
"Move medium/play audio(12)",
|
||||
/* a6-a9 */ "Exchange medium", "Move medium attached", "Read(12)",
|
||||
"Play track relative(12)",
|
||||
/* aa-ae */ "Write(12)", NULL, "Erase(12), Get Performance",
|
||||
|
@ -92,12 +94,12 @@ static const char * cdb_byte0_names[] = {
|
|||
/* af-b1 */ "Verify(12)", "Search data high(12)", "Search data equal(12)",
|
||||
/* b2-b4 */ "Search data low(12)", "Set limits(12)",
|
||||
"Read element status attached",
|
||||
/* b5-b6 */ "Request volume element address", "Send volume tag, set streaming",
|
||||
/* b5-b6 */ "Security protocol out", "Send volume tag, set streaming",
|
||||
/* b7-b9 */ "Read defect data(12)", "Read element status", "Read CD msf",
|
||||
/* ba-bc */ "Redundancy group (in), Scan",
|
||||
"Redundancy group (out), Set cd-rom speed", "Spare in, Play cd",
|
||||
/* bd-bf */ "Spare out, Mechanism status", "Volume set in, Read cd",
|
||||
"Volume set out, Send DVD structure",
|
||||
"Redundancy group (out), Set cd-rom speed", "Spare (in), Play cd",
|
||||
/* bd-bf */ "Spare (out), Mechanism status", "Volume set (in), Read cd",
|
||||
"Volume set (out), Send DVD structure",
|
||||
};
|
||||
|
||||
struct value_name_pair {
|
||||
|
@ -112,6 +114,7 @@ static const struct value_name_pair maint_in_arr[] = {
|
|||
{0xc, "Report supported operation codes"},
|
||||
{0xd, "Report supported task management functions"},
|
||||
{0xe, "Report priority"},
|
||||
{0xf, "Report timestamp"},
|
||||
};
|
||||
#define MAINT_IN_SZ ARRAY_SIZE(maint_in_arr)
|
||||
|
||||
|
@ -120,6 +123,7 @@ static const struct value_name_pair maint_out_arr[] = {
|
|||
{0xa, "Set target port groups"},
|
||||
{0xb, "Change aliases"},
|
||||
{0xe, "Set priority"},
|
||||
{0xe, "Set timestamp"},
|
||||
};
|
||||
#define MAINT_OUT_SZ ARRAY_SIZE(maint_out_arr)
|
||||
|
||||
|
@ -427,6 +431,7 @@ static struct error_info additional[] =
|
|||
{0x001A, "Rewind operation in progress"},
|
||||
{0x001B, "Set capacity operation in progress"},
|
||||
{0x001C, "Verify operation in progress"},
|
||||
{0x001D, "ATA pass through information available"},
|
||||
|
||||
{0x0100, "No index/sector signal"},
|
||||
|
||||
|
@ -438,7 +443,7 @@ static struct error_info additional[] =
|
|||
|
||||
{0x0400, "Logical unit not ready, cause not reportable"},
|
||||
{0x0401, "Logical unit is in process of becoming ready"},
|
||||
{0x0402, "Logical unit not ready, initializing cmd. required"},
|
||||
{0x0402, "Logical unit not ready, initializing command required"},
|
||||
{0x0403, "Logical unit not ready, manual intervention required"},
|
||||
{0x0404, "Logical unit not ready, format in progress"},
|
||||
{0x0405, "Logical unit not ready, rebuild in progress"},
|
||||
|
@ -478,6 +483,9 @@ static struct error_info additional[] =
|
|||
{0x0B00, "Warning"},
|
||||
{0x0B01, "Warning - specified temperature exceeded"},
|
||||
{0x0B02, "Warning - enclosure degraded"},
|
||||
{0x0B03, "Warning - background self-test failed"},
|
||||
{0x0B04, "Warning - background pre-scan detected medium error"},
|
||||
{0x0B05, "Warning - background medium scan detected medium error"},
|
||||
|
||||
{0x0C00, "Write error"},
|
||||
{0x0C01, "Write error - recovered with auto reallocation"},
|
||||
|
@ -493,6 +501,7 @@ static struct error_info additional[] =
|
|||
{0x0C0B, "Auxiliary memory write error"},
|
||||
{0x0C0C, "Write error - unexpected unsolicited data"},
|
||||
{0x0C0D, "Write error - not enough unsolicited data"},
|
||||
{0x0C0F, "Defects in error window"},
|
||||
|
||||
{0x0D00, "Error detected by third party temporary initiator"},
|
||||
{0x0D01, "Third party device failure"},
|
||||
|
@ -504,11 +513,12 @@ static struct error_info additional[] =
|
|||
{0x0E00, "Invalid information unit"},
|
||||
{0x0E01, "Information unit too short"},
|
||||
{0x0E02, "Information unit too long"},
|
||||
{0x0E03, "Invalid field in command information unit"},
|
||||
|
||||
{0x1000, "Id CRC or ECC error"},
|
||||
{0x1001, "Data block guard check failed"},
|
||||
{0x1002, "Data block application tag check failed"},
|
||||
{0x1003, "Data block reference tag check failed"},
|
||||
{0x1001, "Logical block guard check failed"},
|
||||
{0x1002, "Logical block application tag check failed"},
|
||||
{0x1003, "Logical block reference tag check failed"},
|
||||
|
||||
{0x1100, "Unrecovered read error"},
|
||||
{0x1101, "Read retries exhausted"},
|
||||
|
@ -530,6 +540,7 @@ static struct error_info additional[] =
|
|||
{0x1111, "Read error - loss of streaming"},
|
||||
{0x1112, "Auxiliary memory read error"},
|
||||
{0x1113, "Read error - failed retransmission request"},
|
||||
{0x1114, "Read error - lba marked bad by application client"},
|
||||
|
||||
{0x1200, "Address mark not found for id field"},
|
||||
|
||||
|
@ -610,11 +621,14 @@ static struct error_info additional[] =
|
|||
{0x2100, "Logical block address out of range"},
|
||||
{0x2101, "Invalid element address"},
|
||||
{0x2102, "Invalid address for write"},
|
||||
{0x2103, "Invalid write crossing layer jump"},
|
||||
|
||||
{0x2200, "Illegal function (use 20 00, 24 00, or 26 00)"},
|
||||
|
||||
{0x2400, "Invalid field in cdb"},
|
||||
{0x2401, "CDB decryption error"},
|
||||
{0x2402, "Obsolete"},
|
||||
{0x2403, "Obsolete"},
|
||||
{0x2404, "Security audit value frozen"},
|
||||
{0x2405, "Security working key frozen"},
|
||||
{0x2406, "Nonce not unique"},
|
||||
|
@ -637,7 +651,10 @@ static struct error_info additional[] =
|
|||
{0x260C, "Invalid operation for copy source or destination"},
|
||||
{0x260D, "Copy segment granularity violation"},
|
||||
{0x260E, "Invalid parameter while port is enabled"},
|
||||
{0x260F, "Invalid data-out buffer integrity"},
|
||||
{0x260F, "Invalid data-out buffer integrity check value"},
|
||||
{0x2610, "Data decryption key fail limit reached"},
|
||||
{0x2611, "Incomplete key-associated data set"},
|
||||
{0x2612, "Vendor specific key reference not found"},
|
||||
|
||||
{0x2700, "Write protected"},
|
||||
{0x2701, "Hardware write protected"},
|
||||
|
@ -649,6 +666,7 @@ static struct error_info additional[] =
|
|||
|
||||
{0x2800, "Not ready to ready change, medium may have changed"},
|
||||
{0x2801, "Import or export element accessed"},
|
||||
{0x2802, "Format-layer may have changed"},
|
||||
|
||||
{0x2900, "Power on, reset, or bus device reset occurred"},
|
||||
{0x2901, "Power on occurred"},
|
||||
|
@ -669,6 +687,11 @@ static struct error_info additional[] =
|
|||
{0x2A07, "Implicit asymmetric access state transition failed"},
|
||||
{0x2A08, "Priority changed"},
|
||||
{0x2A09, "Capacity data has changed"},
|
||||
{0x2A10, "Timestamp changed"},
|
||||
{0x2A11, "Data encryption parameters changed by another i_t nexus"},
|
||||
{0x2A12, "Data encryption parameters changed by vendor specific "
|
||||
"event"},
|
||||
{0x2A13, "Data encryption key instance counter has changed"},
|
||||
|
||||
{0x2B00, "Copy cannot execute since host cannot disconnect"},
|
||||
|
||||
|
@ -690,6 +713,7 @@ static struct error_info additional[] =
|
|||
{0x2E00, "Insufficient time for operation"},
|
||||
|
||||
{0x2F00, "Commands cleared by another initiator"},
|
||||
{0x2F01, "Commands cleared by power loss notification"},
|
||||
|
||||
{0x3000, "Incompatible medium installed"},
|
||||
{0x3001, "Cannot read medium - unknown format"},
|
||||
|
@ -702,7 +726,8 @@ static struct error_info additional[] =
|
|||
{0x3008, "Cannot write - application code mismatch"},
|
||||
{0x3009, "Current session not fixated for append"},
|
||||
{0x300A, "Cleaning request rejected"},
|
||||
{0x300C, "WORM medium, overwrite attempted"},
|
||||
{0x300C, "WORM medium - overwrite attempted"},
|
||||
{0x300D, "WORM medium - integrity check"},
|
||||
{0x3010, "Medium not formatted"},
|
||||
|
||||
{0x3100, "Medium format corrupted"},
|
||||
|
@ -790,6 +815,9 @@ static struct error_info additional[] =
|
|||
{0x3F0F, "Echo buffer overwritten"},
|
||||
{0x3F10, "Medium loadable"},
|
||||
{0x3F11, "Medium auxiliary memory accessible"},
|
||||
{0x3F12, "iSCSI IP address added"},
|
||||
{0x3F13, "iSCSI IP address removed"},
|
||||
{0x3F14, "iSCSI IP address changed"},
|
||||
/*
|
||||
* {0x40NN, "Ram failure"},
|
||||
* {0x40NN, "Diagnostic failure on component nn"},
|
||||
|
@ -799,6 +827,7 @@ static struct error_info additional[] =
|
|||
{0x4300, "Message error"},
|
||||
|
||||
{0x4400, "Internal target failure"},
|
||||
{0x4471, "ATA device failed set features"},
|
||||
|
||||
{0x4500, "Select or reselect failure"},
|
||||
|
||||
|
@ -807,9 +836,10 @@ static struct error_info additional[] =
|
|||
{0x4700, "Scsi parity error"},
|
||||
{0x4701, "Data phase CRC error detected"},
|
||||
{0x4702, "Scsi parity error detected during st data phase"},
|
||||
{0x4703, "Information unit CRC error detected"},
|
||||
{0x4703, "Information unit iuCRC error detected"},
|
||||
{0x4704, "Asynchronous information protection error detected"},
|
||||
{0x4705, "Protocol service CRC error"},
|
||||
{0x4706, "Phy test function in progress"},
|
||||
{0x477f, "Some commands cleared by iSCSI Protocol event"},
|
||||
|
||||
{0x4800, "Initiator detected error message received"},
|
||||
|
@ -844,6 +874,8 @@ static struct error_info additional[] =
|
|||
{0x5300, "Media load or eject failed"},
|
||||
{0x5301, "Unload tape failure"},
|
||||
{0x5302, "Medium removal prevented"},
|
||||
{0x5303, "Medium removal prevented by data transfer element"},
|
||||
{0x5304, "Medium thread or unthread failure"},
|
||||
|
||||
{0x5400, "Scsi to host system interface failure"},
|
||||
|
||||
|
@ -855,6 +887,7 @@ static struct error_info additional[] =
|
|||
{0x5505, "Insufficient access control resources"},
|
||||
{0x5506, "Auxiliary memory out of space"},
|
||||
{0x5507, "Quota error"},
|
||||
{0x5508, "Maximum number of supplemental decryption keys exceeded"},
|
||||
|
||||
{0x5700, "Unable to recover table-of-contents"},
|
||||
|
||||
|
@ -1004,6 +1037,7 @@ static struct error_info additional[] =
|
|||
{0x6708, "Assign failure occurred"},
|
||||
{0x6709, "Multiply assigned logical unit"},
|
||||
{0x670A, "Set target port groups command failed"},
|
||||
{0x670B, "ATA device feature not enabled"},
|
||||
|
||||
{0x6800, "Logical unit not configured"},
|
||||
|
||||
|
@ -1030,6 +1064,8 @@ static struct error_info additional[] =
|
|||
{0x6F03, "Read of scrambled sector without authentication"},
|
||||
{0x6F04, "Media region code is mismatched to logical unit region"},
|
||||
{0x6F05, "Drive region must be permanent/region reset count error"},
|
||||
{0x6F06, "Insufficient block count for binding nonce recording"},
|
||||
{0x6F07, "Conflict in binding nonce recording"},
|
||||
/*
|
||||
* {0x70NN, "Decompression exception short algorithm id of nn"},
|
||||
*/
|
||||
|
@ -1041,6 +1077,8 @@ static struct error_info additional[] =
|
|||
{0x7203, "Session fixation error - incomplete track in session"},
|
||||
{0x7204, "Empty or partially written reserved track"},
|
||||
{0x7205, "No more track reservations allowed"},
|
||||
{0x7206, "RMZ extension is not allowed"},
|
||||
{0x7207, "No more test zone extensions are allowed"},
|
||||
|
||||
{0x7300, "Cd control error"},
|
||||
{0x7301, "Power calibration area almost full"},
|
||||
|
@ -1049,6 +1087,18 @@ static struct error_info additional[] =
|
|||
{0x7304, "Program memory area update failure"},
|
||||
{0x7305, "Program memory area is full"},
|
||||
{0x7306, "RMA/PMA is almost full"},
|
||||
{0x7310, "Current power calibration area almost full"},
|
||||
{0x7311, "Current power calibration area is full"},
|
||||
{0x7317, "RDZ is full"},
|
||||
|
||||
{0x7400, "Security error"},
|
||||
{0x7401, "Unable to decrypt data"},
|
||||
{0x7402, "Unencrypted data encountered while decrypting"},
|
||||
{0x7403, "Incorrect data encryption key"},
|
||||
{0x7404, "Cryptographic integrity validation failed"},
|
||||
{0x7405, "Error decrypting data"},
|
||||
{0x7471, "Logical unit access not authorized"},
|
||||
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
|
|
|
@ -1397,7 +1397,7 @@ static void esp_get_dmabufs(struct esp *esp, struct scsi_cmnd *sp)
|
|||
sp->SCp.ptr = NULL;
|
||||
}
|
||||
} else {
|
||||
sp->SCp.buffer = (struct scatterlist *) sp->buffer;
|
||||
sp->SCp.buffer = (struct scatterlist *) sp->request_buffer;
|
||||
sp->SCp.buffers_residual = sbus_map_sg(esp->sdev,
|
||||
sp->SCp.buffer,
|
||||
sp->use_sg,
|
||||
|
@ -1410,7 +1410,7 @@ static void esp_get_dmabufs(struct esp *esp, struct scsi_cmnd *sp)
|
|||
static void esp_release_dmabufs(struct esp *esp, struct scsi_cmnd *sp)
|
||||
{
|
||||
if (sp->use_sg) {
|
||||
sbus_unmap_sg(esp->sdev, sp->buffer, sp->use_sg,
|
||||
sbus_unmap_sg(esp->sdev, sp->request_buffer, sp->use_sg,
|
||||
sp->sc_data_direction);
|
||||
} else if (sp->request_bufflen) {
|
||||
sbus_unmap_single(esp->sdev,
|
||||
|
|
|
@ -81,7 +81,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
|
|||
int rc;
|
||||
|
||||
single_host_data = hostdata;
|
||||
rc = viopath_open(viopath_hostLp, viomajorsubtype_scsi, 0);
|
||||
rc = viopath_open(viopath_hostLp, viomajorsubtype_scsi, max_requests);
|
||||
if (rc < 0) {
|
||||
printk("viopath_open failed with rc %d in open_event_path\n",
|
||||
rc);
|
||||
|
|
|
@ -238,6 +238,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue,
|
|||
if (rc == 2) {
|
||||
/* Adapter is good, but other end is not ready */
|
||||
printk(KERN_WARNING "ibmvscsi: Partner adapter not ready\n");
|
||||
retrc = 0;
|
||||
} else if (rc != 0) {
|
||||
printk(KERN_WARNING "ibmvscsi: Error %d opening adapter\n", rc);
|
||||
goto reg_crq_failed;
|
||||
|
|
|
@ -257,7 +257,7 @@ static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, struct scsi_cmnd *sp)
|
|||
static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, struct scsi_cmnd *sp)
|
||||
{
|
||||
int sz = sp->use_sg - 1;
|
||||
struct scatterlist *sg = (struct scatterlist *)sp->buffer;
|
||||
struct scatterlist *sg = (struct scatterlist *)sp->request_buffer;
|
||||
|
||||
while(sz >= 0) {
|
||||
vdma_free(sg[sz].dma_address);
|
||||
|
|
|
@ -21,10 +21,12 @@
|
|||
|
||||
struct lpfc_sli2_slim;
|
||||
|
||||
#define LPFC_MAX_TARGET 256 /* max targets supported */
|
||||
#define LPFC_MAX_DISC_THREADS 64 /* max outstanding discovery els req */
|
||||
#define LPFC_MAX_NS_RETRY 3 /* max NameServer retries */
|
||||
|
||||
#define LPFC_MAX_TARGET 256 /* max number of targets supported */
|
||||
#define LPFC_MAX_DISC_THREADS 64 /* max outstanding discovery els
|
||||
requests */
|
||||
#define LPFC_MAX_NS_RETRY 3 /* Number of retry attempts to contact
|
||||
the NameServer before giving up. */
|
||||
#define LPFC_DFT_HBA_Q_DEPTH 2048 /* max cmds per hba */
|
||||
#define LPFC_LC_HBA_Q_DEPTH 1024 /* max cmds per low cost hba */
|
||||
#define LPFC_LP101_HBA_Q_DEPTH 128 /* max cmds per low cost hba */
|
||||
|
@ -41,7 +43,6 @@ struct lpfc_sli2_slim;
|
|||
(( (u64)(high)<<16 ) << 16)|( (u64)(low))))
|
||||
/* Provide maximum configuration definitions. */
|
||||
#define LPFC_DRVR_TIMEOUT 16 /* driver iocb timeout value in sec */
|
||||
#define MAX_FCP_TARGET 256 /* max num of FCP targets supported */
|
||||
#define FC_MAX_ADPTMSG 64
|
||||
|
||||
#define MAX_HBAEVT 32
|
||||
|
|
|
@ -219,9 +219,19 @@ lpfc_issue_lip(struct Scsi_Host *host)
|
|||
return -ENOMEM;
|
||||
|
||||
memset((void *)pmboxq, 0, sizeof (LPFC_MBOXQ_t));
|
||||
lpfc_init_link(phba, pmboxq, phba->cfg_topology, phba->cfg_link_speed);
|
||||
pmboxq->mb.mbxCommand = MBX_DOWN_LINK;
|
||||
pmboxq->mb.mbxOwner = OWN_HOST;
|
||||
|
||||
mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
|
||||
|
||||
if ((mbxstatus == MBX_SUCCESS) && (pmboxq->mb.mbxStatus == 0)) {
|
||||
memset((void *)pmboxq, 0, sizeof (LPFC_MBOXQ_t));
|
||||
lpfc_init_link(phba, pmboxq, phba->cfg_topology,
|
||||
phba->cfg_link_speed);
|
||||
mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq,
|
||||
phba->fc_ratov * 2);
|
||||
}
|
||||
|
||||
if (mbxstatus == MBX_TIMEOUT)
|
||||
pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
|
||||
else
|
||||
|
@ -233,6 +243,47 @@ lpfc_issue_lip(struct Scsi_Host *host)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
lpfc_selective_reset(struct lpfc_hba *phba)
|
||||
{
|
||||
struct completion online_compl;
|
||||
int status = 0;
|
||||
|
||||
init_completion(&online_compl);
|
||||
lpfc_workq_post_event(phba, &status, &online_compl,
|
||||
LPFC_EVT_OFFLINE);
|
||||
wait_for_completion(&online_compl);
|
||||
|
||||
if (status != 0)
|
||||
return -EIO;
|
||||
|
||||
init_completion(&online_compl);
|
||||
lpfc_workq_post_event(phba, &status, &online_compl,
|
||||
LPFC_EVT_ONLINE);
|
||||
wait_for_completion(&online_compl);
|
||||
|
||||
if (status != 0)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
lpfc_issue_reset(struct class_device *cdev, const char *buf, size_t count)
|
||||
{
|
||||
struct Scsi_Host *host = class_to_shost(cdev);
|
||||
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
|
||||
int status = -EINVAL;
|
||||
|
||||
if (strncmp(buf, "selective", sizeof("selective") - 1) == 0)
|
||||
status = lpfc_selective_reset(phba);
|
||||
|
||||
if (status == 0)
|
||||
return strlen(buf);
|
||||
else
|
||||
return status;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
lpfc_nport_evt_cnt_show(struct class_device *cdev, char *buf)
|
||||
{
|
||||
|
@ -241,45 +292,6 @@ lpfc_nport_evt_cnt_show(struct class_device *cdev, char *buf)
|
|||
return snprintf(buf, PAGE_SIZE, "%d\n", phba->nport_event_cnt);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
lpfc_board_online_show(struct class_device *cdev, char *buf)
|
||||
{
|
||||
struct Scsi_Host *host = class_to_shost(cdev);
|
||||
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
|
||||
|
||||
if (phba->fc_flag & FC_OFFLINE_MODE)
|
||||
return snprintf(buf, PAGE_SIZE, "0\n");
|
||||
else
|
||||
return snprintf(buf, PAGE_SIZE, "1\n");
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
lpfc_board_online_store(struct class_device *cdev, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct Scsi_Host *host = class_to_shost(cdev);
|
||||
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
|
||||
struct completion online_compl;
|
||||
int val=0, status=0;
|
||||
|
||||
if (sscanf(buf, "%d", &val) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
init_completion(&online_compl);
|
||||
|
||||
if (val)
|
||||
lpfc_workq_post_event(phba, &status, &online_compl,
|
||||
LPFC_EVT_ONLINE);
|
||||
else
|
||||
lpfc_workq_post_event(phba, &status, &online_compl,
|
||||
LPFC_EVT_OFFLINE);
|
||||
wait_for_completion(&online_compl);
|
||||
if (!status)
|
||||
return strlen(buf);
|
||||
else
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
lpfc_board_mode_show(struct class_device *cdev, char *buf)
|
||||
{
|
||||
|
@ -532,10 +544,9 @@ static CLASS_DEVICE_ATTR(lpfc_drvr_version, S_IRUGO, lpfc_drvr_version_show,
|
|||
NULL);
|
||||
static CLASS_DEVICE_ATTR(management_version, S_IRUGO, management_version_show,
|
||||
NULL);
|
||||
static CLASS_DEVICE_ATTR(board_online, S_IRUGO | S_IWUSR,
|
||||
lpfc_board_online_show, lpfc_board_online_store);
|
||||
static CLASS_DEVICE_ATTR(board_mode, S_IRUGO | S_IWUSR,
|
||||
lpfc_board_mode_show, lpfc_board_mode_store);
|
||||
static CLASS_DEVICE_ATTR(issue_reset, S_IWUSR, NULL, lpfc_issue_reset);
|
||||
|
||||
static int lpfc_poll = 0;
|
||||
module_param(lpfc_poll, int, 0);
|
||||
|
@ -695,12 +706,12 @@ LPFC_ATTR(discovery_threads, 32, 1, 64, "Maximum number of ELS commands "
|
|||
"during discovery");
|
||||
|
||||
/*
|
||||
# lpfc_max_luns: maximum number of LUNs per target driver will support
|
||||
# Value range is [1,32768]. Default value is 256.
|
||||
# NOTE: The SCSI layer will scan each target for this many luns
|
||||
# lpfc_max_luns: maximum allowed LUN.
|
||||
# Value range is [0,65535]. Default value is 255.
|
||||
# NOTE: The SCSI layer might probe all allowed LUN on some old targets.
|
||||
*/
|
||||
LPFC_ATTR_R(max_luns, 256, 1, 32768,
|
||||
"Maximum number of LUNs per target driver will support");
|
||||
LPFC_ATTR_R(max_luns, 255, 0, 65535,
|
||||
"Maximum allowed LUN");
|
||||
|
||||
/*
|
||||
# lpfc_poll_tmo: .Milliseconds driver will wait between polling FCP ring.
|
||||
|
@ -739,8 +750,8 @@ struct class_device_attribute *lpfc_host_attrs[] = {
|
|||
&class_device_attr_lpfc_max_luns,
|
||||
&class_device_attr_nport_evt_cnt,
|
||||
&class_device_attr_management_version,
|
||||
&class_device_attr_board_online,
|
||||
&class_device_attr_board_mode,
|
||||
&class_device_attr_issue_reset,
|
||||
&class_device_attr_lpfc_poll,
|
||||
&class_device_attr_lpfc_poll_tmo,
|
||||
NULL,
|
||||
|
|
|
@ -147,6 +147,7 @@ int lpfc_sli_hba_setup(struct lpfc_hba *);
|
|||
int lpfc_sli_hba_down(struct lpfc_hba *);
|
||||
int lpfc_sli_issue_mbox(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);
|
||||
int lpfc_sli_handle_mb_event(struct lpfc_hba *);
|
||||
int lpfc_sli_flush_mbox_queue(struct lpfc_hba *);
|
||||
int lpfc_sli_handle_slow_ring_event(struct lpfc_hba *,
|
||||
struct lpfc_sli_ring *, uint32_t);
|
||||
void lpfc_sli_def_mbox_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
|
|
|
@ -648,33 +648,32 @@ lpfc_more_plogi(struct lpfc_hba * phba)
|
|||
}
|
||||
|
||||
static struct lpfc_nodelist *
|
||||
lpfc_plogi_confirm_nport(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
|
||||
lpfc_plogi_confirm_nport(struct lpfc_hba * phba, struct lpfc_dmabuf *prsp,
|
||||
struct lpfc_nodelist *ndlp)
|
||||
{
|
||||
struct lpfc_nodelist *new_ndlp;
|
||||
struct lpfc_dmabuf *pcmd, *prsp;
|
||||
uint32_t *lp;
|
||||
struct serv_parm *sp;
|
||||
uint8_t name[sizeof (struct lpfc_name)];
|
||||
uint32_t rc;
|
||||
|
||||
pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
|
||||
prsp = (struct lpfc_dmabuf *) pcmd->list.next;
|
||||
lp = (uint32_t *) prsp->virt;
|
||||
sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
|
||||
memset(name, 0, sizeof (struct lpfc_name));
|
||||
|
||||
/* Now we to find out if the NPort we are logging into, matches the WWPN
|
||||
* we have for that ndlp. If not, we have some work to do.
|
||||
*/
|
||||
new_ndlp = lpfc_findnode_wwpn(phba, NLP_SEARCH_ALL, &sp->portName);
|
||||
|
||||
memset(name, 0, sizeof (struct lpfc_name));
|
||||
rc = memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name));
|
||||
if (!rc || (new_ndlp == ndlp)) {
|
||||
if (new_ndlp == ndlp)
|
||||
return ndlp;
|
||||
}
|
||||
|
||||
if (!new_ndlp) {
|
||||
rc =
|
||||
memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name));
|
||||
if (!rc)
|
||||
return ndlp;
|
||||
new_ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC);
|
||||
if (!new_ndlp)
|
||||
return ndlp;
|
||||
|
@ -683,17 +682,21 @@ lpfc_plogi_confirm_nport(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
|
|||
}
|
||||
|
||||
lpfc_unreg_rpi(phba, new_ndlp);
|
||||
new_ndlp->nlp_prev_state = ndlp->nlp_state;
|
||||
new_ndlp->nlp_DID = ndlp->nlp_DID;
|
||||
new_ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
|
||||
lpfc_nlp_list(phba, new_ndlp, NLP_PLOGI_LIST);
|
||||
new_ndlp->nlp_prev_state = ndlp->nlp_prev_state;
|
||||
new_ndlp->nlp_state = ndlp->nlp_state;
|
||||
lpfc_nlp_list(phba, new_ndlp, ndlp->nlp_flag & NLP_LIST_MASK);
|
||||
|
||||
/* Move this back to NPR list */
|
||||
lpfc_unreg_rpi(phba, ndlp);
|
||||
ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */
|
||||
ndlp->nlp_state = NLP_STE_NPR_NODE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
|
||||
|
||||
if (memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)) == 0) {
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
}
|
||||
else {
|
||||
lpfc_unreg_rpi(phba, ndlp);
|
||||
ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */
|
||||
ndlp->nlp_state = NLP_STE_NPR_NODE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
|
||||
}
|
||||
return new_ndlp;
|
||||
}
|
||||
|
||||
|
@ -703,6 +706,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
|
|||
{
|
||||
IOCB_t *irsp;
|
||||
struct lpfc_nodelist *ndlp;
|
||||
struct lpfc_dmabuf *prsp;
|
||||
int disc, rc, did, type;
|
||||
|
||||
|
||||
|
@ -769,7 +773,10 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
|
|||
}
|
||||
} else {
|
||||
/* Good status, call state machine */
|
||||
ndlp = lpfc_plogi_confirm_nport(phba, cmdiocb, ndlp);
|
||||
prsp = list_entry(((struct lpfc_dmabuf *)
|
||||
cmdiocb->context2)->list.next,
|
||||
struct lpfc_dmabuf, list);
|
||||
ndlp = lpfc_plogi_confirm_nport(phba, prsp, ndlp);
|
||||
rc = lpfc_disc_state_machine(phba, ndlp, cmdiocb,
|
||||
NLP_EVT_CMPL_PLOGI);
|
||||
}
|
||||
|
@ -3282,10 +3289,9 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba)
|
|||
} else
|
||||
lpfc_sli_release_iocbq(phba, piocb);
|
||||
}
|
||||
if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt) {
|
||||
phba->els_tmofunc.expires = jiffies + HZ * timeout;
|
||||
add_timer(&phba->els_tmofunc);
|
||||
}
|
||||
if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt)
|
||||
mod_timer(&phba->els_tmofunc, jiffies + HZ * timeout);
|
||||
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
}
|
||||
|
||||
|
@ -3442,6 +3448,8 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
|
|||
if ((did & Fabric_DID_MASK) == Fabric_DID_MASK) {
|
||||
ndlp->nlp_type |= NLP_FABRIC;
|
||||
}
|
||||
ndlp->nlp_state = NLP_STE_UNUSED_NODE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST);
|
||||
}
|
||||
|
||||
phba->fc_stat.elsRcvFrame++;
|
||||
|
@ -3463,13 +3471,14 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
|
|||
rjt_err = 1;
|
||||
break;
|
||||
}
|
||||
ndlp = lpfc_plogi_confirm_nport(phba, mp, ndlp);
|
||||
lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PLOGI);
|
||||
break;
|
||||
case ELS_CMD_FLOGI:
|
||||
phba->fc_stat.elsRcvFLOGI++;
|
||||
lpfc_els_rcv_flogi(phba, elsiocb, ndlp, newnode);
|
||||
if (newnode) {
|
||||
mempool_free( ndlp, phba->nlp_mem_pool);
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
}
|
||||
break;
|
||||
case ELS_CMD_LOGO:
|
||||
|
@ -3492,7 +3501,7 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
|
|||
phba->fc_stat.elsRcvRSCN++;
|
||||
lpfc_els_rcv_rscn(phba, elsiocb, ndlp, newnode);
|
||||
if (newnode) {
|
||||
mempool_free( ndlp, phba->nlp_mem_pool);
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
}
|
||||
break;
|
||||
case ELS_CMD_ADISC:
|
||||
|
@ -3535,28 +3544,28 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
|
|||
phba->fc_stat.elsRcvLIRR++;
|
||||
lpfc_els_rcv_lirr(phba, elsiocb, ndlp);
|
||||
if (newnode) {
|
||||
mempool_free( ndlp, phba->nlp_mem_pool);
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
}
|
||||
break;
|
||||
case ELS_CMD_RPS:
|
||||
phba->fc_stat.elsRcvRPS++;
|
||||
lpfc_els_rcv_rps(phba, elsiocb, ndlp);
|
||||
if (newnode) {
|
||||
mempool_free( ndlp, phba->nlp_mem_pool);
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
}
|
||||
break;
|
||||
case ELS_CMD_RPL:
|
||||
phba->fc_stat.elsRcvRPL++;
|
||||
lpfc_els_rcv_rpl(phba, elsiocb, ndlp);
|
||||
if (newnode) {
|
||||
mempool_free( ndlp, phba->nlp_mem_pool);
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
}
|
||||
break;
|
||||
case ELS_CMD_RNID:
|
||||
phba->fc_stat.elsRcvRNID++;
|
||||
lpfc_els_rcv_rnid(phba, elsiocb, ndlp);
|
||||
if (newnode) {
|
||||
mempool_free( ndlp, phba->nlp_mem_pool);
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -3568,7 +3577,7 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
|
|||
"%d:0115 Unknown ELS command x%x received from "
|
||||
"NPORT x%x\n", phba->brd_no, cmd, did);
|
||||
if (newnode) {
|
||||
mempool_free( ndlp, phba->nlp_mem_pool);
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1084,7 +1084,7 @@ lpfc_register_remote_port(struct lpfc_hba * phba,
|
|||
fc_remote_port_rolechg(rport, rport_ids.roles);
|
||||
|
||||
if ((rport->scsi_target_id != -1) &&
|
||||
(rport->scsi_target_id < MAX_FCP_TARGET)) {
|
||||
(rport->scsi_target_id < LPFC_MAX_TARGET)) {
|
||||
ndlp->nlp_sid = rport->scsi_target_id;
|
||||
}
|
||||
|
||||
|
@ -1313,7 +1313,7 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
|
|||
if ((rport_add == mapped) &&
|
||||
((!nlp->rport) ||
|
||||
(nlp->rport->scsi_target_id == -1) ||
|
||||
(nlp->rport->scsi_target_id >= MAX_FCP_TARGET))) {
|
||||
(nlp->rport->scsi_target_id >= LPFC_MAX_TARGET))) {
|
||||
nlp->nlp_state = NLP_STE_UNMAPPED_NODE;
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
nlp->nlp_flag |= NLP_TGT_NO_SCSIID;
|
||||
|
|
|
@ -71,6 +71,7 @@ lpfc_config_port_prep(struct lpfc_hba * phba)
|
|||
uint16_t offset = 0;
|
||||
static char licensed[56] =
|
||||
"key unlock for use with gnu public licensed code only\0";
|
||||
static int init_key = 1;
|
||||
|
||||
pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
|
||||
if (!pmb) {
|
||||
|
@ -82,10 +83,13 @@ lpfc_config_port_prep(struct lpfc_hba * phba)
|
|||
phba->hba_state = LPFC_INIT_MBX_CMDS;
|
||||
|
||||
if (lpfc_is_LC_HBA(phba->pcidev->device)) {
|
||||
uint32_t *ptext = (uint32_t *) licensed;
|
||||
if (init_key) {
|
||||
uint32_t *ptext = (uint32_t *) licensed;
|
||||
|
||||
for (i = 0; i < 56; i += sizeof (uint32_t), ptext++)
|
||||
*ptext = cpu_to_be32(*ptext);
|
||||
for (i = 0; i < 56; i += sizeof (uint32_t), ptext++)
|
||||
*ptext = cpu_to_be32(*ptext);
|
||||
init_key = 0;
|
||||
}
|
||||
|
||||
lpfc_read_nv(phba, pmb);
|
||||
memset((char*)mb->un.varRDnvp.rsvd3, 0,
|
||||
|
@ -405,19 +409,26 @@ lpfc_config_port_post(struct lpfc_hba * phba)
|
|||
}
|
||||
/* MBOX buffer will be freed in mbox compl */
|
||||
|
||||
i = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
lpfc_discovery_wait(struct lpfc_hba *phba)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while ((phba->hba_state != LPFC_HBA_READY) ||
|
||||
(phba->num_disc_nodes) || (phba->fc_prli_sent) ||
|
||||
((phba->fc_map_cnt == 0) && (i<2)) ||
|
||||
(psli->sli_flag & LPFC_SLI_MBOX_ACTIVE)) {
|
||||
(phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE)) {
|
||||
/* Check every second for 30 retries. */
|
||||
i++;
|
||||
if (i > 30) {
|
||||
break;
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
if ((i >= 15) && (phba->hba_state <= LPFC_LINK_DOWN)) {
|
||||
/* The link is down. Set linkdown timeout */
|
||||
break;
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/* Delay for 1 second to give discovery time to complete. */
|
||||
|
@ -425,12 +436,7 @@ lpfc_config_port_post(struct lpfc_hba * phba)
|
|||
|
||||
}
|
||||
|
||||
/* Since num_disc_nodes keys off of PLOGI, delay a bit to let
|
||||
* any potential PRLIs to flush thru the SLI sub-system.
|
||||
*/
|
||||
msleep(50);
|
||||
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
@ -1339,7 +1345,8 @@ lpfc_offline(struct lpfc_hba * phba)
|
|||
struct lpfc_sli_ring *pring;
|
||||
struct lpfc_sli *psli;
|
||||
unsigned long iflag;
|
||||
int i = 0;
|
||||
int i;
|
||||
int cnt = 0;
|
||||
|
||||
if (!phba)
|
||||
return 0;
|
||||
|
@ -1348,17 +1355,27 @@ lpfc_offline(struct lpfc_hba * phba)
|
|||
return 0;
|
||||
|
||||
psli = &phba->sli;
|
||||
pring = &psli->ring[psli->fcp_ring];
|
||||
|
||||
lpfc_linkdown(phba);
|
||||
lpfc_sli_flush_mbox_queue(phba);
|
||||
|
||||
/* The linkdown event takes 30 seconds to timeout. */
|
||||
while (pring->txcmplq_cnt) {
|
||||
mdelay(10);
|
||||
if (i++ > 3000)
|
||||
break;
|
||||
for (i = 0; i < psli->num_rings; i++) {
|
||||
pring = &psli->ring[i];
|
||||
/* The linkdown event takes 30 seconds to timeout. */
|
||||
while (pring->txcmplq_cnt) {
|
||||
mdelay(10);
|
||||
if (cnt++ > 3000) {
|
||||
lpfc_printf_log(phba,
|
||||
KERN_WARNING, LOG_INIT,
|
||||
"%d:0466 Outstanding IO when "
|
||||
"bringing Adapter offline\n",
|
||||
phba->brd_no);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* stop all timers associated with this hba */
|
||||
lpfc_stop_timer(phba);
|
||||
phba->work_hba_events = 0;
|
||||
|
@ -1639,6 +1656,8 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
|
|||
goto out_free_irq;
|
||||
}
|
||||
|
||||
lpfc_discovery_wait(phba);
|
||||
|
||||
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
lpfc_poll_start_timer(phba);
|
||||
|
|
|
@ -133,6 +133,11 @@ lpfc_mem_free(struct lpfc_hba * phba)
|
|||
|
||||
pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool);
|
||||
pci_pool_destroy(phba->lpfc_mbuf_pool);
|
||||
|
||||
/* Free the iocb lookup array */
|
||||
kfree(psli->iocbq_lookup);
|
||||
psli->iocbq_lookup = NULL;
|
||||
|
||||
}
|
||||
|
||||
void *
|
||||
|
|
|
@ -1110,6 +1110,17 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_hba * phba,
|
|||
phba->brd_no,
|
||||
did, mb->mbxStatus, phba->hba_state);
|
||||
|
||||
/*
|
||||
* If RegLogin failed due to lack of HBA resources do not
|
||||
* retry discovery.
|
||||
*/
|
||||
if (mb->mbxStatus == MBXERR_RPI_FULL) {
|
||||
ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE;
|
||||
ndlp->nlp_state = NLP_STE_UNUSED_NODE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST);
|
||||
return ndlp->nlp_state;
|
||||
}
|
||||
|
||||
/* Put ndlp in npr list set plogi timer for 1 sec */
|
||||
mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
|
|
|
@ -153,22 +153,6 @@ static void
|
|||
lpfc_release_scsi_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb)
|
||||
{
|
||||
unsigned long iflag = 0;
|
||||
/*
|
||||
* There are only two special cases to consider. (1) the scsi command
|
||||
* requested scatter-gather usage or (2) the scsi command allocated
|
||||
* a request buffer, but did not request use_sg. There is a third
|
||||
* case, but it does not require resource deallocation.
|
||||
*/
|
||||
if ((psb->seg_cnt > 0) && (psb->pCmd->use_sg)) {
|
||||
dma_unmap_sg(&phba->pcidev->dev, psb->pCmd->request_buffer,
|
||||
psb->seg_cnt, psb->pCmd->sc_data_direction);
|
||||
} else {
|
||||
if ((psb->nonsg_phys) && (psb->pCmd->request_bufflen)) {
|
||||
dma_unmap_single(&phba->pcidev->dev, psb->nonsg_phys,
|
||||
psb->pCmd->request_bufflen,
|
||||
psb->pCmd->sc_data_direction);
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
|
||||
psb->pCmd = NULL;
|
||||
|
@ -281,6 +265,27 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
lpfc_scsi_unprep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb)
|
||||
{
|
||||
/*
|
||||
* There are only two special cases to consider. (1) the scsi command
|
||||
* requested scatter-gather usage or (2) the scsi command allocated
|
||||
* a request buffer, but did not request use_sg. There is a third
|
||||
* case, but it does not require resource deallocation.
|
||||
*/
|
||||
if ((psb->seg_cnt > 0) && (psb->pCmd->use_sg)) {
|
||||
dma_unmap_sg(&phba->pcidev->dev, psb->pCmd->request_buffer,
|
||||
psb->seg_cnt, psb->pCmd->sc_data_direction);
|
||||
} else {
|
||||
if ((psb->nonsg_phys) && (psb->pCmd->request_bufflen)) {
|
||||
dma_unmap_single(&phba->pcidev->dev, psb->nonsg_phys,
|
||||
psb->pCmd->request_bufflen,
|
||||
psb->pCmd->sc_data_direction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd)
|
||||
{
|
||||
|
@ -454,6 +459,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
|
|||
cmd->scsi_done(cmd);
|
||||
|
||||
if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
|
||||
lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
|
||||
lpfc_release_scsi_buf(phba, lpfc_cmd);
|
||||
return;
|
||||
}
|
||||
|
@ -511,6 +517,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
|
|||
}
|
||||
}
|
||||
|
||||
lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
|
||||
lpfc_release_scsi_buf(phba, lpfc_cmd);
|
||||
}
|
||||
|
||||
|
@ -609,6 +616,7 @@ lpfc_scsi_prep_cmnd(struct lpfc_hba * phba, struct lpfc_scsi_buf * lpfc_cmd,
|
|||
static int
|
||||
lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
|
||||
struct lpfc_scsi_buf *lpfc_cmd,
|
||||
unsigned int lun,
|
||||
uint8_t task_mgmt_cmd)
|
||||
{
|
||||
struct lpfc_sli *psli;
|
||||
|
@ -627,8 +635,7 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
|
|||
piocb = &piocbq->iocb;
|
||||
|
||||
fcp_cmnd = lpfc_cmd->fcp_cmnd;
|
||||
int_to_scsilun(lpfc_cmd->pCmd->device->lun,
|
||||
&lpfc_cmd->fcp_cmnd->fcp_lun);
|
||||
int_to_scsilun(lun, &lpfc_cmd->fcp_cmnd->fcp_lun);
|
||||
fcp_cmnd->fcpCntl2 = task_mgmt_cmd;
|
||||
|
||||
piocb->ulpCommand = CMD_FCP_ICMND64_CR;
|
||||
|
@ -655,14 +662,16 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
|
|||
|
||||
static int
|
||||
lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba,
|
||||
unsigned tgt_id, struct lpfc_rport_data *rdata)
|
||||
unsigned tgt_id, unsigned int lun,
|
||||
struct lpfc_rport_data *rdata)
|
||||
{
|
||||
struct lpfc_iocbq *iocbq;
|
||||
struct lpfc_iocbq *iocbqrsp;
|
||||
int ret;
|
||||
|
||||
lpfc_cmd->rdata = rdata;
|
||||
ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, FCP_TARGET_RESET);
|
||||
ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, lun,
|
||||
FCP_TARGET_RESET);
|
||||
if (!ret)
|
||||
return FAILED;
|
||||
|
||||
|
@ -822,6 +831,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
|
|||
return 0;
|
||||
|
||||
out_host_busy_free_buf:
|
||||
lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
|
||||
lpfc_release_scsi_buf(phba, lpfc_cmd);
|
||||
out_host_busy:
|
||||
return SCSI_MLQUEUE_HOST_BUSY;
|
||||
|
@ -969,12 +979,12 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
|
|||
if (lpfc_cmd == NULL)
|
||||
goto out;
|
||||
|
||||
lpfc_cmd->pCmd = cmnd;
|
||||
lpfc_cmd->timeout = 60;
|
||||
lpfc_cmd->scsi_hba = phba;
|
||||
lpfc_cmd->rdata = rdata;
|
||||
|
||||
ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, FCP_LUN_RESET);
|
||||
ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, cmnd->device->lun,
|
||||
FCP_LUN_RESET);
|
||||
if (!ret)
|
||||
goto out_free_scsi_buf;
|
||||
|
||||
|
@ -1001,7 +1011,6 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
|
|||
cmd_status = iocbqrsp->iocb.ulpStatus;
|
||||
|
||||
lpfc_sli_release_iocbq(phba, iocbqrsp);
|
||||
lpfc_release_scsi_buf(phba, lpfc_cmd);
|
||||
|
||||
/*
|
||||
* All outstanding txcmplq I/Os should have been aborted by the device.
|
||||
|
@ -1040,6 +1049,8 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
|
|||
}
|
||||
|
||||
out_free_scsi_buf:
|
||||
lpfc_release_scsi_buf(phba, lpfc_cmd);
|
||||
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
|
||||
"%d:0713 SCSI layer issued LUN reset (%d, %d) "
|
||||
"Data: x%x x%x x%x\n",
|
||||
|
@ -1070,7 +1081,6 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
|
|||
|
||||
/* The lpfc_cmd storage is reused. Set all loop invariants. */
|
||||
lpfc_cmd->timeout = 60;
|
||||
lpfc_cmd->pCmd = cmnd;
|
||||
lpfc_cmd->scsi_hba = phba;
|
||||
|
||||
/*
|
||||
|
@ -1078,7 +1088,7 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
|
|||
* targets known to the driver. Should any target reset
|
||||
* fail, this routine returns failure to the midlayer.
|
||||
*/
|
||||
for (i = 0; i < MAX_FCP_TARGET; i++) {
|
||||
for (i = 0; i < LPFC_MAX_TARGET; i++) {
|
||||
/* Search the mapped list for this target ID */
|
||||
match = 0;
|
||||
list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) {
|
||||
|
@ -1090,8 +1100,8 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
|
|||
if (!match)
|
||||
continue;
|
||||
|
||||
ret = lpfc_scsi_tgt_reset(lpfc_cmd, phba,
|
||||
i, ndlp->rport->dd_data);
|
||||
ret = lpfc_scsi_tgt_reset(lpfc_cmd, phba, i, cmnd->device->lun,
|
||||
ndlp->rport->dd_data);
|
||||
if (ret != SUCCESS) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
|
||||
"%d:0713 Bus Reset on target %d failed\n",
|
||||
|
|
|
@ -191,35 +191,12 @@ static int
|
|||
lpfc_sli_ringtxcmpl_put(struct lpfc_hba * phba,
|
||||
struct lpfc_sli_ring * pring, struct lpfc_iocbq * piocb)
|
||||
{
|
||||
uint16_t iotag;
|
||||
|
||||
list_add_tail(&piocb->list, &pring->txcmplq);
|
||||
pring->txcmplq_cnt++;
|
||||
if (unlikely(pring->ringno == LPFC_ELS_RING))
|
||||
mod_timer(&phba->els_tmofunc,
|
||||
jiffies + HZ * (phba->fc_ratov << 1));
|
||||
|
||||
if (pring->fast_lookup) {
|
||||
/* Setup fast lookup based on iotag for completion */
|
||||
iotag = piocb->iocb.ulpIoTag;
|
||||
if (iotag && (iotag < pring->fast_iotag))
|
||||
*(pring->fast_lookup + iotag) = piocb;
|
||||
else {
|
||||
|
||||
/* Cmd ring <ringno> put: iotag <iotag> greater then
|
||||
configured max <fast_iotag> wd0 <icmd> */
|
||||
lpfc_printf_log(phba,
|
||||
KERN_ERR,
|
||||
LOG_SLI,
|
||||
"%d:0316 Cmd ring %d put: iotag x%x "
|
||||
"greater then configured max x%x "
|
||||
"wd0 x%x\n",
|
||||
phba->brd_no,
|
||||
pring->ringno, iotag,
|
||||
pring->fast_iotag,
|
||||
*(((uint32_t *)(&piocb->iocb)) + 7));
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -601,7 +578,7 @@ lpfc_sli_handle_mb_event(struct lpfc_hba * phba)
|
|||
/* Stray Mailbox Interrupt, mbxCommand <cmd> mbxStatus
|
||||
<status> */
|
||||
lpfc_printf_log(phba,
|
||||
KERN_ERR,
|
||||
KERN_WARNING,
|
||||
LOG_MBOX | LOG_SLI,
|
||||
"%d:0304 Stray Mailbox Interrupt "
|
||||
"mbxCommand x%x mbxStatus x%x\n",
|
||||
|
@ -1570,8 +1547,8 @@ lpfc_sli_brdready(struct lpfc_hba * phba, uint32_t mask)
|
|||
|
||||
void lpfc_reset_barrier(struct lpfc_hba * phba)
|
||||
{
|
||||
uint32_t * resp_buf;
|
||||
uint32_t * mbox_buf;
|
||||
uint32_t __iomem *resp_buf;
|
||||
uint32_t __iomem *mbox_buf;
|
||||
volatile uint32_t mbox;
|
||||
uint32_t hc_copy;
|
||||
int i;
|
||||
|
@ -1587,7 +1564,7 @@ void lpfc_reset_barrier(struct lpfc_hba * phba)
|
|||
* Tell the other part of the chip to suspend temporarily all
|
||||
* its DMA activity.
|
||||
*/
|
||||
resp_buf = (uint32_t *)phba->MBslimaddr;
|
||||
resp_buf = phba->MBslimaddr;
|
||||
|
||||
/* Disable the error attention */
|
||||
hc_copy = readl(phba->HCregaddr);
|
||||
|
@ -1605,7 +1582,7 @@ void lpfc_reset_barrier(struct lpfc_hba * phba)
|
|||
((MAILBOX_t *)&mbox)->mbxOwner = OWN_CHIP;
|
||||
|
||||
writel(BARRIER_TEST_PATTERN, (resp_buf + 1));
|
||||
mbox_buf = (uint32_t *)phba->MBslimaddr;
|
||||
mbox_buf = phba->MBslimaddr;
|
||||
writel(mbox, mbox_buf);
|
||||
|
||||
for (i = 0;
|
||||
|
@ -1805,7 +1782,7 @@ lpfc_sli_brdrestart(struct lpfc_hba * phba)
|
|||
skip_post = 0;
|
||||
word0 = 0; /* This is really setting up word1 */
|
||||
}
|
||||
to_slim = (uint8_t *) phba->MBslimaddr + sizeof (uint32_t);
|
||||
to_slim = phba->MBslimaddr + sizeof (uint32_t);
|
||||
writel(*(uint32_t *) mb, to_slim);
|
||||
readl(to_slim); /* flush */
|
||||
|
||||
|
@ -2659,8 +2636,6 @@ lpfc_sli_hba_down(struct lpfc_hba * phba)
|
|||
|
||||
INIT_LIST_HEAD(&(pring->txq));
|
||||
|
||||
kfree(pring->fast_lookup);
|
||||
pring->fast_lookup = NULL;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(phba->host->host_lock, flags);
|
||||
|
@ -3110,6 +3085,24 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq,
|
|||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
lpfc_sli_flush_mbox_queue(struct lpfc_hba * phba)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE && !phba->stopped) {
|
||||
if (i++ > LPFC_MBOX_TMO * 1000)
|
||||
return 1;
|
||||
|
||||
if (lpfc_sli_handle_mb_event(phba) == 0)
|
||||
i = 0;
|
||||
|
||||
msleep(1);
|
||||
}
|
||||
|
||||
return (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE) ? 1 : 0;
|
||||
}
|
||||
|
||||
irqreturn_t
|
||||
lpfc_intr_handler(int irq, void *dev_id, struct pt_regs * regs)
|
||||
{
|
||||
|
|
|
@ -135,8 +135,6 @@ struct lpfc_sli_ring {
|
|||
uint32_t fast_iotag; /* max fastlookup based iotag */
|
||||
uint32_t iotag_ctr; /* keeps track of the next iotag to use */
|
||||
uint32_t iotag_max; /* max iotag value to use */
|
||||
struct lpfc_iocbq ** fast_lookup; /* array of IOCB ptrs indexed by
|
||||
iotag */
|
||||
struct list_head txq;
|
||||
uint16_t txq_cnt; /* current length of queue */
|
||||
uint16_t txq_max; /* max length */
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* included with this package. *
|
||||
*******************************************************************/
|
||||
|
||||
#define LPFC_DRIVER_VERSION "8.1.6"
|
||||
#define LPFC_DRIVER_VERSION "8.1.7"
|
||||
|
||||
#define LPFC_DRIVER_NAME "lpfc"
|
||||
|
||||
|
|
|
@ -378,7 +378,7 @@ static void set_dma_cmds(struct fsc_state *state, struct scsi_cmnd *cmd)
|
|||
int nseg;
|
||||
|
||||
total = 0;
|
||||
scl = (struct scatterlist *) cmd->buffer;
|
||||
scl = (struct scatterlist *) cmd->request_buffer;
|
||||
nseg = pci_map_sg(state->pdev, scl, cmd->use_sg,
|
||||
cmd->sc_data_direction);
|
||||
for (i = 0; i < nseg; ++i) {
|
||||
|
|
|
@ -1268,7 +1268,7 @@ static void set_dma_cmds(struct mesh_state *ms, struct scsi_cmnd *cmd)
|
|||
if (cmd->use_sg > 0) {
|
||||
int nseg;
|
||||
total = 0;
|
||||
scl = (struct scatterlist *) cmd->buffer;
|
||||
scl = (struct scatterlist *) cmd->request_buffer;
|
||||
off = ms->data_ptr;
|
||||
nseg = pci_map_sg(ms->pdev, scl, cmd->use_sg,
|
||||
cmd->sc_data_direction);
|
||||
|
|
|
@ -169,8 +169,6 @@ int __init pluto_detect(struct scsi_host_template *tpnt)
|
|||
SCpnt->request->rq_status = RQ_SCSI_BUSY;
|
||||
|
||||
SCpnt->done = pluto_detect_done;
|
||||
SCpnt->bufflen = 256;
|
||||
SCpnt->buffer = fcs[i].inquiry;
|
||||
SCpnt->request_bufflen = 256;
|
||||
SCpnt->request_buffer = fcs[i].inquiry;
|
||||
PLD(("set up %d %08lx\n", i, (long)SCpnt))
|
||||
|
|
|
@ -874,7 +874,7 @@ static inline int load_cmd(struct scsi_cmnd *Cmnd, struct Command_Entry *cmd,
|
|||
if (Cmnd->use_sg) {
|
||||
int sg_count;
|
||||
|
||||
sg = (struct scatterlist *) Cmnd->buffer;
|
||||
sg = (struct scatterlist *) Cmnd->request_buffer;
|
||||
sg_count = sbus_map_sg(qpti->sdev, sg, Cmnd->use_sg, Cmnd->sc_data_direction);
|
||||
|
||||
ds = cmd->dataseg;
|
||||
|
@ -1278,7 +1278,7 @@ static struct scsi_cmnd *qlogicpti_intr_handler(struct qlogicpti *qpti)
|
|||
|
||||
if (Cmnd->use_sg) {
|
||||
sbus_unmap_sg(qpti->sdev,
|
||||
(struct scatterlist *)Cmnd->buffer,
|
||||
(struct scatterlist *)Cmnd->request_buffer,
|
||||
Cmnd->use_sg,
|
||||
Cmnd->sc_data_direction);
|
||||
} else {
|
||||
|
|
|
@ -346,7 +346,7 @@ void scsi_log_send(struct scsi_cmnd *cmd)
|
|||
if (level > 3) {
|
||||
printk(KERN_INFO "buffer = 0x%p, bufflen = %d,"
|
||||
" done = 0x%p, queuecommand 0x%p\n",
|
||||
cmd->buffer, cmd->bufflen,
|
||||
cmd->request_buffer, cmd->request_bufflen,
|
||||
cmd->done,
|
||||
sdev->host->hostt->queuecommand);
|
||||
|
||||
|
@ -661,11 +661,6 @@ void __scsi_done(struct scsi_cmnd *cmd)
|
|||
*/
|
||||
int scsi_retry_command(struct scsi_cmnd *cmd)
|
||||
{
|
||||
/*
|
||||
* Restore the SCSI command state.
|
||||
*/
|
||||
scsi_setup_cmd_retry(cmd);
|
||||
|
||||
/*
|
||||
* Zero the sense information from the last time we tried
|
||||
* this command.
|
||||
|
@ -711,10 +706,6 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
|
|||
"Notifying upper driver of completion "
|
||||
"(result %x)\n", cmd->result));
|
||||
|
||||
/*
|
||||
* We can get here with use_sg=0, causing a panic in the upper level
|
||||
*/
|
||||
cmd->use_sg = cmd->old_use_sg;
|
||||
cmd->done(cmd);
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_finish_command);
|
||||
|
|
|
@ -286,7 +286,7 @@ static int inquiry_evpd_83(unsigned char * arr, int target_dev_id,
|
|||
int dev_id_num, const char * dev_id_str,
|
||||
int dev_id_str_len);
|
||||
static int inquiry_evpd_88(unsigned char * arr, int target_dev_id);
|
||||
static void do_create_driverfs_files(void);
|
||||
static int do_create_driverfs_files(void);
|
||||
static void do_remove_driverfs_files(void);
|
||||
|
||||
static int sdebug_add_adapter(void);
|
||||
|
@ -2487,19 +2487,22 @@ static ssize_t sdebug_add_host_store(struct device_driver * ddp,
|
|||
DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, sdebug_add_host_show,
|
||||
sdebug_add_host_store);
|
||||
|
||||
static void do_create_driverfs_files(void)
|
||||
static int do_create_driverfs_files(void)
|
||||
{
|
||||
driver_create_file(&sdebug_driverfs_driver, &driver_attr_add_host);
|
||||
driver_create_file(&sdebug_driverfs_driver, &driver_attr_delay);
|
||||
driver_create_file(&sdebug_driverfs_driver, &driver_attr_dev_size_mb);
|
||||
driver_create_file(&sdebug_driverfs_driver, &driver_attr_dsense);
|
||||
driver_create_file(&sdebug_driverfs_driver, &driver_attr_every_nth);
|
||||
driver_create_file(&sdebug_driverfs_driver, &driver_attr_max_luns);
|
||||
driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_tgts);
|
||||
driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_parts);
|
||||
driver_create_file(&sdebug_driverfs_driver, &driver_attr_ptype);
|
||||
driver_create_file(&sdebug_driverfs_driver, &driver_attr_opts);
|
||||
driver_create_file(&sdebug_driverfs_driver, &driver_attr_scsi_level);
|
||||
int ret;
|
||||
|
||||
ret = driver_create_file(&sdebug_driverfs_driver, &driver_attr_add_host);
|
||||
ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_delay);
|
||||
ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_dev_size_mb);
|
||||
ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_dsense);
|
||||
ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_every_nth);
|
||||
ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_max_luns);
|
||||
ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_tgts);
|
||||
ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_num_parts);
|
||||
ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_ptype);
|
||||
ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_opts);
|
||||
ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_scsi_level);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void do_remove_driverfs_files(void)
|
||||
|
@ -2522,6 +2525,7 @@ static int __init scsi_debug_init(void)
|
|||
unsigned int sz;
|
||||
int host_to_add;
|
||||
int k;
|
||||
int ret;
|
||||
|
||||
if (scsi_debug_dev_size_mb < 1)
|
||||
scsi_debug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */
|
||||
|
@ -2560,12 +2564,32 @@ static int __init scsi_debug_init(void)
|
|||
if (scsi_debug_num_parts > 0)
|
||||
sdebug_build_parts(fake_storep);
|
||||
|
||||
init_all_queued();
|
||||
ret = device_register(&pseudo_primary);
|
||||
if (ret < 0) {
|
||||
printk(KERN_WARNING "scsi_debug: device_register error: %d\n",
|
||||
ret);
|
||||
goto free_vm;
|
||||
}
|
||||
ret = bus_register(&pseudo_lld_bus);
|
||||
if (ret < 0) {
|
||||
printk(KERN_WARNING "scsi_debug: bus_register error: %d\n",
|
||||
ret);
|
||||
goto dev_unreg;
|
||||
}
|
||||
ret = driver_register(&sdebug_driverfs_driver);
|
||||
if (ret < 0) {
|
||||
printk(KERN_WARNING "scsi_debug: driver_register error: %d\n",
|
||||
ret);
|
||||
goto bus_unreg;
|
||||
}
|
||||
ret = do_create_driverfs_files();
|
||||
if (ret < 0) {
|
||||
printk(KERN_WARNING "scsi_debug: driver_create_file error: %d\n",
|
||||
ret);
|
||||
goto del_files;
|
||||
}
|
||||
|
||||
device_register(&pseudo_primary);
|
||||
bus_register(&pseudo_lld_bus);
|
||||
driver_register(&sdebug_driverfs_driver);
|
||||
do_create_driverfs_files();
|
||||
init_all_queued();
|
||||
|
||||
sdebug_driver_template.proc_name = (char *)sdebug_proc_name;
|
||||
|
||||
|
@ -2585,6 +2609,18 @@ static int __init scsi_debug_init(void)
|
|||
scsi_debug_add_host);
|
||||
}
|
||||
return 0;
|
||||
|
||||
del_files:
|
||||
do_remove_driverfs_files();
|
||||
driver_unregister(&sdebug_driverfs_driver);
|
||||
bus_unreg:
|
||||
bus_unregister(&pseudo_lld_bus);
|
||||
dev_unreg:
|
||||
device_unregister(&pseudo_primary);
|
||||
free_vm:
|
||||
vfree(fake_storep);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit scsi_debug_exit(void)
|
||||
|
|
|
@ -460,19 +460,67 @@ static void scsi_eh_done(struct scsi_cmnd *scmd)
|
|||
* Return value:
|
||||
* SUCCESS or FAILED or NEEDS_RETRY
|
||||
**/
|
||||
static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout)
|
||||
static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout, int copy_sense)
|
||||
{
|
||||
struct scsi_device *sdev = scmd->device;
|
||||
struct Scsi_Host *shost = sdev->host;
|
||||
int old_result = scmd->result;
|
||||
DECLARE_COMPLETION(done);
|
||||
unsigned long timeleft;
|
||||
unsigned long flags;
|
||||
unsigned char old_cmnd[MAX_COMMAND_SIZE];
|
||||
enum dma_data_direction old_data_direction;
|
||||
unsigned short old_use_sg;
|
||||
unsigned char old_cmd_len;
|
||||
unsigned old_bufflen;
|
||||
void *old_buffer;
|
||||
int rtn;
|
||||
|
||||
/*
|
||||
* We need saved copies of a number of fields - this is because
|
||||
* error handling may need to overwrite these with different values
|
||||
* to run different commands, and once error handling is complete,
|
||||
* we will need to restore these values prior to running the actual
|
||||
* command.
|
||||
*/
|
||||
old_buffer = scmd->request_buffer;
|
||||
old_bufflen = scmd->request_bufflen;
|
||||
memcpy(old_cmnd, scmd->cmnd, sizeof(scmd->cmnd));
|
||||
old_data_direction = scmd->sc_data_direction;
|
||||
old_cmd_len = scmd->cmd_len;
|
||||
old_use_sg = scmd->use_sg;
|
||||
|
||||
if (copy_sense) {
|
||||
int gfp_mask = GFP_ATOMIC;
|
||||
|
||||
if (shost->hostt->unchecked_isa_dma)
|
||||
gfp_mask |= __GFP_DMA;
|
||||
|
||||
scmd->sc_data_direction = DMA_FROM_DEVICE;
|
||||
scmd->request_bufflen = 252;
|
||||
scmd->request_buffer = kzalloc(scmd->request_bufflen, gfp_mask);
|
||||
if (!scmd->request_buffer)
|
||||
return FAILED;
|
||||
} else {
|
||||
scmd->request_buffer = NULL;
|
||||
scmd->request_bufflen = 0;
|
||||
scmd->sc_data_direction = DMA_NONE;
|
||||
}
|
||||
|
||||
scmd->underflow = 0;
|
||||
scmd->use_sg = 0;
|
||||
scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
|
||||
|
||||
if (sdev->scsi_level <= SCSI_2)
|
||||
scmd->cmnd[1] = (scmd->cmnd[1] & 0x1f) |
|
||||
(sdev->lun << 5 & 0xe0);
|
||||
|
||||
/*
|
||||
* Zero the sense buffer. The scsi spec mandates that any
|
||||
* untransferred sense data should be interpreted as being zero.
|
||||
*/
|
||||
memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer));
|
||||
|
||||
shost->eh_action = &done;
|
||||
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
|
@ -522,6 +570,29 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout)
|
|||
rtn = FAILED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Last chance to have valid sense data.
|
||||
*/
|
||||
if (copy_sense) {
|
||||
if (!SCSI_SENSE_VALID(scmd)) {
|
||||
memcpy(scmd->sense_buffer, scmd->request_buffer,
|
||||
sizeof(scmd->sense_buffer));
|
||||
}
|
||||
kfree(scmd->request_buffer);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Restore original data
|
||||
*/
|
||||
scmd->request_buffer = old_buffer;
|
||||
scmd->request_bufflen = old_bufflen;
|
||||
memcpy(scmd->cmnd, old_cmnd, sizeof(scmd->cmnd));
|
||||
scmd->sc_data_direction = old_data_direction;
|
||||
scmd->cmd_len = old_cmd_len;
|
||||
scmd->use_sg = old_use_sg;
|
||||
scmd->result = old_result;
|
||||
return rtn;
|
||||
}
|
||||
|
||||
|
@ -537,56 +608,10 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout)
|
|||
static int scsi_request_sense(struct scsi_cmnd *scmd)
|
||||
{
|
||||
static unsigned char generic_sense[6] =
|
||||
{REQUEST_SENSE, 0, 0, 0, 252, 0};
|
||||
unsigned char *scsi_result;
|
||||
int saved_result;
|
||||
int rtn;
|
||||
{REQUEST_SENSE, 0, 0, 0, 252, 0};
|
||||
|
||||
memcpy(scmd->cmnd, generic_sense, sizeof(generic_sense));
|
||||
|
||||
scsi_result = kmalloc(252, GFP_ATOMIC | ((scmd->device->host->hostt->unchecked_isa_dma) ? __GFP_DMA : 0));
|
||||
|
||||
|
||||
if (unlikely(!scsi_result)) {
|
||||
printk(KERN_ERR "%s: cannot allocate scsi_result.\n",
|
||||
__FUNCTION__);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
/*
|
||||
* zero the sense buffer. some host adapters automatically always
|
||||
* request sense, so it is not a good idea that
|
||||
* scmd->request_buffer and scmd->sense_buffer point to the same
|
||||
* address (db). 0 is not a valid sense code.
|
||||
*/
|
||||
memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer));
|
||||
memset(scsi_result, 0, 252);
|
||||
|
||||
saved_result = scmd->result;
|
||||
scmd->request_buffer = scsi_result;
|
||||
scmd->request_bufflen = 252;
|
||||
scmd->use_sg = 0;
|
||||
scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
|
||||
scmd->sc_data_direction = DMA_FROM_DEVICE;
|
||||
scmd->underflow = 0;
|
||||
|
||||
rtn = scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT);
|
||||
|
||||
/* last chance to have valid sense data */
|
||||
if(!SCSI_SENSE_VALID(scmd)) {
|
||||
memcpy(scmd->sense_buffer, scmd->request_buffer,
|
||||
sizeof(scmd->sense_buffer));
|
||||
}
|
||||
|
||||
kfree(scsi_result);
|
||||
|
||||
/*
|
||||
* when we eventually call scsi_finish, we really wish to complete
|
||||
* the original request, so let's restore the original data. (db)
|
||||
*/
|
||||
scsi_setup_cmd_retry(scmd);
|
||||
scmd->result = saved_result;
|
||||
return rtn;
|
||||
return scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -605,12 +630,6 @@ void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, struct list_head *done_q)
|
|||
{
|
||||
scmd->device->host->host_failed--;
|
||||
scmd->eh_eflags = 0;
|
||||
|
||||
/*
|
||||
* set this back so that the upper level can correctly free up
|
||||
* things.
|
||||
*/
|
||||
scsi_setup_cmd_retry(scmd);
|
||||
list_move_tail(&scmd->eh_entry, done_q);
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_eh_finish_cmd);
|
||||
|
@ -715,47 +734,26 @@ static int scsi_eh_tur(struct scsi_cmnd *scmd)
|
|||
{
|
||||
static unsigned char tur_command[6] = {TEST_UNIT_READY, 0, 0, 0, 0, 0};
|
||||
int retry_cnt = 1, rtn;
|
||||
int saved_result;
|
||||
|
||||
retry_tur:
|
||||
memcpy(scmd->cmnd, tur_command, sizeof(tur_command));
|
||||
|
||||
/*
|
||||
* zero the sense buffer. the scsi spec mandates that any
|
||||
* untransferred sense data should be interpreted as being zero.
|
||||
*/
|
||||
memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer));
|
||||
|
||||
saved_result = scmd->result;
|
||||
scmd->request_buffer = NULL;
|
||||
scmd->request_bufflen = 0;
|
||||
scmd->use_sg = 0;
|
||||
scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
|
||||
scmd->underflow = 0;
|
||||
scmd->sc_data_direction = DMA_NONE;
|
||||
rtn = scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT, 0);
|
||||
|
||||
rtn = scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT);
|
||||
|
||||
/*
|
||||
* when we eventually call scsi_finish, we really wish to complete
|
||||
* the original request, so let's restore the original data. (db)
|
||||
*/
|
||||
scsi_setup_cmd_retry(scmd);
|
||||
scmd->result = saved_result;
|
||||
|
||||
/*
|
||||
* hey, we are done. let's look to see what happened.
|
||||
*/
|
||||
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd %p rtn %x\n",
|
||||
__FUNCTION__, scmd, rtn));
|
||||
if (rtn == SUCCESS)
|
||||
return 0;
|
||||
else if (rtn == NEEDS_RETRY) {
|
||||
|
||||
switch (rtn) {
|
||||
case NEEDS_RETRY:
|
||||
if (retry_cnt--)
|
||||
goto retry_tur;
|
||||
/*FALLTHRU*/
|
||||
case SUCCESS:
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -837,44 +835,16 @@ static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd)
|
|||
static int scsi_eh_try_stu(struct scsi_cmnd *scmd)
|
||||
{
|
||||
static unsigned char stu_command[6] = {START_STOP, 0, 0, 0, 1, 0};
|
||||
int rtn;
|
||||
int saved_result;
|
||||
|
||||
if (!scmd->device->allow_restart)
|
||||
return 1;
|
||||
if (scmd->device->allow_restart) {
|
||||
int rtn;
|
||||
|
||||
memcpy(scmd->cmnd, stu_command, sizeof(stu_command));
|
||||
memcpy(scmd->cmnd, stu_command, sizeof(stu_command));
|
||||
rtn = scsi_send_eh_cmnd(scmd, START_UNIT_TIMEOUT, 0);
|
||||
if (rtn == SUCCESS)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* zero the sense buffer. the scsi spec mandates that any
|
||||
* untransferred sense data should be interpreted as being zero.
|
||||
*/
|
||||
memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer));
|
||||
|
||||
saved_result = scmd->result;
|
||||
scmd->request_buffer = NULL;
|
||||
scmd->request_bufflen = 0;
|
||||
scmd->use_sg = 0;
|
||||
scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
|
||||
scmd->underflow = 0;
|
||||
scmd->sc_data_direction = DMA_NONE;
|
||||
|
||||
rtn = scsi_send_eh_cmnd(scmd, START_UNIT_TIMEOUT);
|
||||
|
||||
/*
|
||||
* when we eventually call scsi_finish, we really wish to complete
|
||||
* the original request, so let's restore the original data. (db)
|
||||
*/
|
||||
scsi_setup_cmd_retry(scmd);
|
||||
scmd->result = saved_result;
|
||||
|
||||
/*
|
||||
* hey, we are done. let's look to see what happened.
|
||||
*/
|
||||
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd %p rtn %x\n",
|
||||
__FUNCTION__, scmd, rtn));
|
||||
if (rtn == SUCCESS)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1684,8 +1654,6 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
|
|||
|
||||
scmd->scsi_done = scsi_reset_provider_done_command;
|
||||
scmd->done = NULL;
|
||||
scmd->buffer = NULL;
|
||||
scmd->bufflen = 0;
|
||||
scmd->request_buffer = NULL;
|
||||
scmd->request_bufflen = 0;
|
||||
|
||||
|
|
|
@ -436,60 +436,16 @@ EXPORT_SYMBOL_GPL(scsi_execute_async);
|
|||
*
|
||||
* Arguments: cmd - command that is ready to be queued.
|
||||
*
|
||||
* Returns: Nothing
|
||||
*
|
||||
* Notes: This function has the job of initializing a number of
|
||||
* fields related to error handling. Typically this will
|
||||
* be called once for each command, as required.
|
||||
*/
|
||||
static int scsi_init_cmd_errh(struct scsi_cmnd *cmd)
|
||||
static void scsi_init_cmd_errh(struct scsi_cmnd *cmd)
|
||||
{
|
||||
cmd->serial_number = 0;
|
||||
|
||||
memset(cmd->sense_buffer, 0, sizeof cmd->sense_buffer);
|
||||
|
||||
if (cmd->cmd_len == 0)
|
||||
cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
|
||||
|
||||
/*
|
||||
* We need saved copies of a number of fields - this is because
|
||||
* error handling may need to overwrite these with different values
|
||||
* to run different commands, and once error handling is complete,
|
||||
* we will need to restore these values prior to running the actual
|
||||
* command.
|
||||
*/
|
||||
cmd->old_use_sg = cmd->use_sg;
|
||||
cmd->old_cmd_len = cmd->cmd_len;
|
||||
cmd->sc_old_data_direction = cmd->sc_data_direction;
|
||||
cmd->old_underflow = cmd->underflow;
|
||||
memcpy(cmd->data_cmnd, cmd->cmnd, sizeof(cmd->cmnd));
|
||||
cmd->buffer = cmd->request_buffer;
|
||||
cmd->bufflen = cmd->request_bufflen;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function: scsi_setup_cmd_retry()
|
||||
*
|
||||
* Purpose: Restore the command state for a retry
|
||||
*
|
||||
* Arguments: cmd - command to be restored
|
||||
*
|
||||
* Returns: Nothing
|
||||
*
|
||||
* Notes: Immediately prior to retrying a command, we need
|
||||
* to restore certain fields that we saved above.
|
||||
*/
|
||||
void scsi_setup_cmd_retry(struct scsi_cmnd *cmd)
|
||||
{
|
||||
memcpy(cmd->cmnd, cmd->data_cmnd, sizeof(cmd->data_cmnd));
|
||||
cmd->request_buffer = cmd->buffer;
|
||||
cmd->request_bufflen = cmd->bufflen;
|
||||
cmd->use_sg = cmd->old_use_sg;
|
||||
cmd->cmd_len = cmd->old_cmd_len;
|
||||
cmd->sc_data_direction = cmd->sc_old_data_direction;
|
||||
cmd->underflow = cmd->old_underflow;
|
||||
}
|
||||
|
||||
void scsi_device_unbusy(struct scsi_device *sdev)
|
||||
|
@ -807,22 +763,13 @@ static void scsi_free_sgtable(struct scatterlist *sgl, int index)
|
|||
*/
|
||||
static void scsi_release_buffers(struct scsi_cmnd *cmd)
|
||||
{
|
||||
struct request *req = cmd->request;
|
||||
|
||||
/*
|
||||
* Free up any indirection buffers we allocated for DMA purposes.
|
||||
*/
|
||||
if (cmd->use_sg)
|
||||
scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len);
|
||||
else if (cmd->request_buffer != req->buffer)
|
||||
kfree(cmd->request_buffer);
|
||||
|
||||
/*
|
||||
* Zero these out. They now point to freed memory, and it is
|
||||
* dangerous to hang onto the pointers.
|
||||
*/
|
||||
cmd->buffer = NULL;
|
||||
cmd->bufflen = 0;
|
||||
cmd->request_buffer = NULL;
|
||||
cmd->request_bufflen = 0;
|
||||
}
|
||||
|
@ -858,7 +805,7 @@ static void scsi_release_buffers(struct scsi_cmnd *cmd)
|
|||
void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
|
||||
{
|
||||
int result = cmd->result;
|
||||
int this_count = cmd->bufflen;
|
||||
int this_count = cmd->request_bufflen;
|
||||
request_queue_t *q = cmd->device->request_queue;
|
||||
struct request *req = cmd->request;
|
||||
int clear_errors = 1;
|
||||
|
@ -866,28 +813,14 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
|
|||
int sense_valid = 0;
|
||||
int sense_deferred = 0;
|
||||
|
||||
/*
|
||||
* Free up any indirection buffers we allocated for DMA purposes.
|
||||
* For the case of a READ, we need to copy the data out of the
|
||||
* bounce buffer and into the real buffer.
|
||||
*/
|
||||
if (cmd->use_sg)
|
||||
scsi_free_sgtable(cmd->buffer, cmd->sglist_len);
|
||||
else if (cmd->buffer != req->buffer) {
|
||||
if (rq_data_dir(req) == READ) {
|
||||
unsigned long flags;
|
||||
char *to = bio_kmap_irq(req->bio, &flags);
|
||||
memcpy(to, cmd->buffer, cmd->bufflen);
|
||||
bio_kunmap_irq(to, &flags);
|
||||
}
|
||||
kfree(cmd->buffer);
|
||||
}
|
||||
scsi_release_buffers(cmd);
|
||||
|
||||
if (result) {
|
||||
sense_valid = scsi_command_normalize_sense(cmd, &sshdr);
|
||||
if (sense_valid)
|
||||
sense_deferred = scsi_sense_is_deferred(&sshdr);
|
||||
}
|
||||
|
||||
if (blk_pc_request(req)) { /* SG_IO ioctl from block level */
|
||||
req->errors = result;
|
||||
if (result) {
|
||||
|
@ -907,15 +840,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
|
|||
req->data_len = cmd->resid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Zero these out. They now point to freed memory, and it is
|
||||
* dangerous to hang onto the pointers.
|
||||
*/
|
||||
cmd->buffer = NULL;
|
||||
cmd->bufflen = 0;
|
||||
cmd->request_buffer = NULL;
|
||||
cmd->request_bufflen = 0;
|
||||
|
||||
/*
|
||||
* Next deal with any sectors which we were able to correctly
|
||||
* handle.
|
||||
|
@ -1012,7 +936,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
|
|||
if (!(req->flags & REQ_QUIET)) {
|
||||
scmd_printk(KERN_INFO, cmd,
|
||||
"Volume overflow, CDB: ");
|
||||
__scsi_print_command(cmd->data_cmnd);
|
||||
__scsi_print_command(cmd->cmnd);
|
||||
scsi_print_sense("", cmd);
|
||||
}
|
||||
/* See SSC3rXX or current. */
|
||||
|
@ -1143,7 +1067,7 @@ static void scsi_blk_pc_done(struct scsi_cmnd *cmd)
|
|||
* successfully. Since this is a REQ_BLOCK_PC command the
|
||||
* caller should check the request's errors value
|
||||
*/
|
||||
scsi_io_completion(cmd, cmd->bufflen);
|
||||
scsi_io_completion(cmd, cmd->request_bufflen);
|
||||
}
|
||||
|
||||
static void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd)
|
||||
|
|
|
@ -57,7 +57,6 @@ extern int scsi_eh_scmd_add(struct scsi_cmnd *, int);
|
|||
|
||||
/* scsi_lib.c */
|
||||
extern int scsi_maybe_unblock_host(struct scsi_device *sdev);
|
||||
extern void scsi_setup_cmd_retry(struct scsi_cmnd *cmd);
|
||||
extern void scsi_device_unbusy(struct scsi_device *sdev);
|
||||
extern int scsi_queue_insert(struct scsi_cmnd *cmd, int reason);
|
||||
extern void scsi_next_command(struct scsi_cmnd *cmd);
|
||||
|
|
|
@ -41,6 +41,7 @@ struct sas_host_attrs {
|
|||
struct mutex lock;
|
||||
u32 next_target_id;
|
||||
u32 next_expander_id;
|
||||
int next_port_id;
|
||||
};
|
||||
#define to_sas_host_attrs(host) ((struct sas_host_attrs *)(host)->shost_data)
|
||||
|
||||
|
@ -146,6 +147,7 @@ static int sas_host_setup(struct transport_container *tc, struct device *dev,
|
|||
mutex_init(&sas_host->lock);
|
||||
sas_host->next_target_id = 0;
|
||||
sas_host->next_expander_id = 0;
|
||||
sas_host->next_port_id = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -327,7 +329,7 @@ sas_phy_protocol_attr(identify.target_port_protocols,
|
|||
sas_phy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n",
|
||||
unsigned long long);
|
||||
sas_phy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8);
|
||||
//sas_phy_simple_attr(port_identifier, port_identifier, "%d\n", u8);
|
||||
//sas_phy_simple_attr(port_identifier, port_identifier, "%d\n", int);
|
||||
sas_phy_linkspeed_attr(negotiated_linkrate);
|
||||
sas_phy_linkspeed_attr(minimum_linkrate_hw);
|
||||
sas_phy_linkspeed_attr(minimum_linkrate);
|
||||
|
@ -590,6 +592,38 @@ struct sas_port *sas_port_alloc(struct device *parent, int port_id)
|
|||
}
|
||||
EXPORT_SYMBOL(sas_port_alloc);
|
||||
|
||||
/** sas_port_alloc_num - allocate and initialize a SAS port structure
|
||||
*
|
||||
* @parent: parent device
|
||||
*
|
||||
* Allocates a SAS port structure and a number to go with it. This
|
||||
* interface is really for adapters where the port number has no
|
||||
* meansing, so the sas class should manage them. It will be added to
|
||||
* the device tree below the device specified by @parent which must be
|
||||
* either a Scsi_Host or a sas_expander_device.
|
||||
*
|
||||
* Returns %NULL on error
|
||||
*/
|
||||
struct sas_port *sas_port_alloc_num(struct device *parent)
|
||||
{
|
||||
int index;
|
||||
struct Scsi_Host *shost = dev_to_shost(parent);
|
||||
struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
|
||||
|
||||
/* FIXME: use idr for this eventually */
|
||||
mutex_lock(&sas_host->lock);
|
||||
if (scsi_is_sas_expander_device(parent)) {
|
||||
struct sas_rphy *rphy = dev_to_rphy(parent);
|
||||
struct sas_expander_device *exp = rphy_to_expander_device(rphy);
|
||||
|
||||
index = exp->next_port_id++;
|
||||
} else
|
||||
index = sas_host->next_port_id++;
|
||||
mutex_unlock(&sas_host->lock);
|
||||
return sas_port_alloc(parent, index);
|
||||
}
|
||||
EXPORT_SYMBOL(sas_port_alloc_num);
|
||||
|
||||
/**
|
||||
* sas_port_add - add a SAS port to the device hierarchy
|
||||
*
|
||||
|
@ -658,6 +692,13 @@ void sas_port_delete(struct sas_port *port)
|
|||
}
|
||||
mutex_unlock(&port->phy_list_mutex);
|
||||
|
||||
if (port->is_backlink) {
|
||||
struct device *parent = port->dev.parent;
|
||||
|
||||
sysfs_remove_link(&port->dev.kobj, parent->bus_id);
|
||||
port->is_backlink = 0;
|
||||
}
|
||||
|
||||
transport_remove_device(dev);
|
||||
device_del(dev);
|
||||
transport_destroy_device(dev);
|
||||
|
@ -733,6 +774,19 @@ void sas_port_delete_phy(struct sas_port *port, struct sas_phy *phy)
|
|||
}
|
||||
EXPORT_SYMBOL(sas_port_delete_phy);
|
||||
|
||||
void sas_port_mark_backlink(struct sas_port *port)
|
||||
{
|
||||
struct device *parent = port->dev.parent->parent->parent;
|
||||
|
||||
if (port->is_backlink)
|
||||
return;
|
||||
port->is_backlink = 1;
|
||||
sysfs_create_link(&port->dev.kobj, &parent->kobj,
|
||||
parent->bus_id);
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(sas_port_mark_backlink);
|
||||
|
||||
/*
|
||||
* SAS remote PHY attributes.
|
||||
*/
|
||||
|
@ -1140,7 +1194,7 @@ int sas_rphy_add(struct sas_rphy *rphy)
|
|||
|
||||
if (identify->device_type == SAS_END_DEVICE &&
|
||||
rphy->scsi_target_id != -1) {
|
||||
scsi_scan_target(&rphy->dev, parent->port_identifier,
|
||||
scsi_scan_target(&rphy->dev, 0,
|
||||
rphy->scsi_target_id, ~0, 0);
|
||||
}
|
||||
|
||||
|
@ -1242,15 +1296,13 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel,
|
|||
|
||||
mutex_lock(&sas_host->lock);
|
||||
list_for_each_entry(rphy, &sas_host->rphy_list, list) {
|
||||
struct sas_port *parent = dev_to_sas_port(rphy->dev.parent);
|
||||
|
||||
if (rphy->identify.device_type != SAS_END_DEVICE ||
|
||||
rphy->scsi_target_id == -1)
|
||||
continue;
|
||||
|
||||
if ((channel == SCAN_WILD_CARD || channel == parent->port_identifier) &&
|
||||
if ((channel == SCAN_WILD_CARD || channel == 0) &&
|
||||
(id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) {
|
||||
scsi_scan_target(&rphy->dev, parent->port_identifier,
|
||||
scsi_scan_target(&rphy->dev, 0,
|
||||
rphy->scsi_target_id, lun, 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -502,8 +502,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
|
|||
SCpnt->cmnd[4] = (unsigned char) this_count;
|
||||
SCpnt->cmnd[5] = 0;
|
||||
}
|
||||
SCpnt->request_bufflen = SCpnt->bufflen =
|
||||
this_count * sdp->sector_size;
|
||||
SCpnt->request_bufflen = this_count * sdp->sector_size;
|
||||
|
||||
/*
|
||||
* We shouldn't disconnect in the middle of a sector, so with a dumb
|
||||
|
|
|
@ -1002,7 +1002,7 @@ static int internal_command (unsigned char target, unsigned char lun,
|
|||
}
|
||||
#endif
|
||||
|
||||
buffer = (struct scatterlist *) SCint->buffer;
|
||||
buffer = (struct scatterlist *) SCint->request_buffer;
|
||||
len = buffer->length;
|
||||
data = page_address(buffer->page) + buffer->offset;
|
||||
} else {
|
||||
|
|
|
@ -360,7 +360,7 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
|
|||
"mismatch count %d, bytes %d\n",
|
||||
size, SCpnt->request_bufflen);
|
||||
if (SCpnt->request_bufflen > size)
|
||||
SCpnt->request_bufflen = SCpnt->bufflen = size;
|
||||
SCpnt->request_bufflen = size;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -387,8 +387,7 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
|
|||
|
||||
if (this_count > 0xffff) {
|
||||
this_count = 0xffff;
|
||||
SCpnt->request_bufflen = SCpnt->bufflen =
|
||||
this_count * s_size;
|
||||
SCpnt->request_bufflen = this_count * s_size;
|
||||
}
|
||||
|
||||
SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff;
|
||||
|
|
|
@ -368,7 +368,7 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt)
|
|||
SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
|
||||
SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
|
||||
if (cmdstatp->have_sense)
|
||||
__scsi_print_sense("st", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
|
||||
__scsi_print_sense(name, SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
|
||||
} ) /* end DEB */
|
||||
if (!debugging) { /* Abnormal conditions for tape */
|
||||
if (!cmdstatp->have_sense)
|
||||
|
@ -384,9 +384,8 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt)
|
|||
scode != VOLUME_OVERFLOW &&
|
||||
SRpnt->cmd[0] != MODE_SENSE &&
|
||||
SRpnt->cmd[0] != TEST_UNIT_READY) {
|
||||
printk(KERN_WARNING "%s: Error with sense data: ", name);
|
||||
__scsi_print_sense("st", SRpnt->sense,
|
||||
SCSI_SENSE_BUFFERSIZE);
|
||||
|
||||
__scsi_print_sense(name, SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -517,7 +517,7 @@ static __inline__ void initialize_SCp(Scsi_Cmnd *cmd)
|
|||
*/
|
||||
|
||||
if (cmd->use_sg) {
|
||||
cmd->SCp.buffer = (struct scatterlist *) cmd->buffer;
|
||||
cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer;
|
||||
cmd->SCp.buffers_residual = cmd->use_sg - 1;
|
||||
cmd->SCp.ptr = (char *) SGADDR(cmd->SCp.buffer);
|
||||
cmd->SCp.this_residual = cmd->SCp.buffer->length;
|
||||
|
|
|
@ -347,7 +347,7 @@ static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp)
|
|||
static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp)
|
||||
{
|
||||
int sz = sp->use_sg - 1;
|
||||
struct scatterlist *sg = (struct scatterlist *)sp->buffer;
|
||||
struct scatterlist *sg = (struct scatterlist *)sp->request_buffer;
|
||||
|
||||
while(sz >= 0) {
|
||||
dvma_unmap((char *)sg[sz].dma_address);
|
||||
|
|
|
@ -373,7 +373,7 @@ wd33c93_queuecommand(struct scsi_cmnd *cmd,
|
|||
*/
|
||||
|
||||
if (cmd->use_sg) {
|
||||
cmd->SCp.buffer = (struct scatterlist *) cmd->buffer;
|
||||
cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer;
|
||||
cmd->SCp.buffers_residual = cmd->use_sg - 1;
|
||||
cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) +
|
||||
cmd->SCp.buffer->offset;
|
||||
|
|
|
@ -58,9 +58,7 @@ struct scsi_cmnd {
|
|||
int timeout_per_command;
|
||||
|
||||
unsigned char cmd_len;
|
||||
unsigned char old_cmd_len;
|
||||
enum dma_data_direction sc_data_direction;
|
||||
enum dma_data_direction sc_old_data_direction;
|
||||
|
||||
/* These elements define the operation we are about to perform */
|
||||
#define MAX_COMMAND_SIZE 16
|
||||
|
@ -71,18 +69,11 @@ struct scsi_cmnd {
|
|||
void *request_buffer; /* Actual requested buffer */
|
||||
|
||||
/* These elements define the operation we ultimately want to perform */
|
||||
unsigned char data_cmnd[MAX_COMMAND_SIZE];
|
||||
unsigned short old_use_sg; /* We save use_sg here when requesting
|
||||
* sense info */
|
||||
unsigned short use_sg; /* Number of pieces of scatter-gather */
|
||||
unsigned short sglist_len; /* size of malloc'd scatter-gather list */
|
||||
unsigned bufflen; /* Size of data buffer */
|
||||
void *buffer; /* Data buffer */
|
||||
|
||||
unsigned underflow; /* Return error if less than
|
||||
this amount is transferred */
|
||||
unsigned old_underflow; /* save underflow here when reusing the
|
||||
* command for error handling */
|
||||
|
||||
unsigned transfersize; /* How much we are guaranteed to
|
||||
transfer with each SCSI transfer
|
||||
|
|
|
@ -106,6 +106,7 @@ struct sas_end_device {
|
|||
|
||||
struct sas_expander_device {
|
||||
int level;
|
||||
int next_port_id;
|
||||
|
||||
#define SAS_EXPANDER_VENDOR_ID_LEN 8
|
||||
char vendor_id[SAS_EXPANDER_VENDOR_ID_LEN+1];
|
||||
|
@ -127,8 +128,10 @@ struct sas_expander_device {
|
|||
struct sas_port {
|
||||
struct device dev;
|
||||
|
||||
u8 port_identifier;
|
||||
int port_identifier;
|
||||
int num_phys;
|
||||
/* port flags */
|
||||
unsigned int is_backlink:1;
|
||||
|
||||
/* the other end of the link */
|
||||
struct sas_rphy *rphy;
|
||||
|
@ -168,11 +171,13 @@ extern void sas_rphy_delete(struct sas_rphy *);
|
|||
extern int scsi_is_sas_rphy(const struct device *);
|
||||
|
||||
struct sas_port *sas_port_alloc(struct device *, int);
|
||||
struct sas_port *sas_port_alloc_num(struct device *);
|
||||
int sas_port_add(struct sas_port *);
|
||||
void sas_port_free(struct sas_port *);
|
||||
void sas_port_delete(struct sas_port *);
|
||||
void sas_port_add_phy(struct sas_port *, struct sas_phy *);
|
||||
void sas_port_delete_phy(struct sas_port *, struct sas_phy *);
|
||||
void sas_port_mark_backlink(struct sas_port *);
|
||||
int scsi_is_sas_port(const struct device *);
|
||||
|
||||
extern struct scsi_transport_template *
|
||||
|
|
Loading…
Reference in a new issue