Commit bd381b1f authored by Stephen Cameron's avatar Stephen Cameron Committed by Linus Torvalds

[PATCH] fix cpqfc passthrough ioctl for 2.5.30

This patch fixes the cpqfc passthrough ioctl for 2.5.30.

One question... Is it possible for a user app, by abusing
a upperlevel driver (e.g. the sg driver) to put a bogus
value into Scsi_Request->upper_level_private?

This patch kind of depends on this being impossible.

If it is possible, maybe it's better if I find another way
to identify passthrough commands on completion than what
this patch does.  e.g. keep a list of the passthru Scsi_Requests
that are outstanding, then search the list on each completion...(yuck.)

-- steve
parent 9c9e47a5
......@@ -7,6 +7,8 @@ Tested in single and dual HBA configuration, 32 and 64bit busses,
SEST size 512 Exchanges (simultaneous I/Os) limited by module kmalloc()
max of 128k bytes contiguous.
Ver 2.5.3 Aug 01, 2002
* fix the passthru ioctl to handle the Scsi_Cmnd->request being a pointer
Ver 2.5.1 Jul 30, 2002
* fix ioctl to pay attention to the specified LUN.
Ver 2.5.0 Nov 29, 2001
......
This diff is collapsed.
......@@ -33,7 +33,7 @@
// don't forget to also change MODULE_DESCRIPTION in cpqfcTSinit.c
#define VER_MAJOR 2
#define VER_MINOR 5
#define VER_SUBMINOR 2
#define VER_SUBMINOR 3
// Macros for kernel (esp. SMP) tracing using a PCI analyzer
// (e.g. x86).
......@@ -907,9 +907,17 @@ typedef struct
} FC_SCSI_QUE, *PFC_SCSI_QUE;
typedef struct {
/* This is tacked on to a Scsi_Request in upper_private_data
for pasthrough ioctls, as a place to hold data that can't
be stashed anywhere else in the Scsi_Request. We differentiate
this from _real_ upper_private_data by checking if the virt addr
is within our special pool. */
ushort bus;
ushort pdrive;
} cpqfc_passthru_private_t;
#define CPQFC_MAX_PASSTHRU_CMDS 100
#define DYNAMIC_ALLOCATIONS 4 // Tachyon aligned allocations: ERQ,IMQ,SFQ,SEST
......@@ -949,6 +957,8 @@ typedef struct
PFC_LINK_QUE fcLQ; // the WorkerThread operates on this
spinlock_t hba_spinlock; // held/released by WorkerThread
cpqfc_passthru_private_t *private_data_pool;
unsigned long *private_data_bits;
} CPQFCHBA;
......@@ -1405,6 +1415,7 @@ struct ext_sg_entry_t {
__u32 lba; /* lower bus address bits 0-31 */
};
// J. McCarty's LINK.H
//
// LS_RJT Reason Codes
......
......@@ -2887,15 +2887,22 @@ static void ScsiReportLunsDone(Scsi_Cmnd *Cmnd)
Done:
}
extern int is_private_data_of_cpqfc(CPQFCHBA *hba, void * pointer);
extern void cpqfc_free_private_data(CPQFCHBA *hba, cpqfc_passthru_private_t *data);
static void
call_scsi_done(Scsi_Cmnd *Cmnd)
{
// We have to reinitialize sent_command here, so the scsi-mid
// layer won't re-use the scsi command leaving it set incorrectly.
// (incorrectly for our purposes...it's normally unused.)
if (Cmnd->SCp.sent_command != 0) { // was it a passthru?
Cmnd->SCp.sent_command = 0;
CPQFCHBA *hba;
hba = (CPQFCHBA *) Cmnd->host->hostdata;
// Was this command a cpqfc passthru ioctl ?
if (Cmnd->sc_request != NULL && Cmnd->host != NULL &&
Cmnd->host->hostdata != NULL &&
is_private_data_of_cpqfc((CPQFCHBA *) Cmnd->host->hostdata,
Cmnd->sc_request->upper_private_data)) {
cpqfc_free_private_data(hba,
Cmnd->sc_request->upper_private_data);
Cmnd->sc_request->upper_private_data = NULL;
Cmnd->result &= 0xff00ffff;
Cmnd->result |= (DID_PASSTHROUGH << 16); // prevents retry
}
......@@ -3293,6 +3300,7 @@ static int GetLoopID( ULONG al_pa )
}
#endif
extern cpqfc_passthru_private_t *cpqfc_private(Scsi_Request *sr);
// Search the singly (forward) linked list "fcPorts" looking for
// either the SCSI target (if != -1), port_id (if not NULL),
......@@ -3366,8 +3374,18 @@ PFC_LOGGEDIN_PORT fcFindLoggedInPort(
{
// For "passthru" modes, the IOCTL caller is responsible
// for setting the FCP-LUN addressing
if( !Cmnd->SCp.sent_command ) // NOT passthru?
{
if (Cmnd->sc_request != NULL && Cmnd->host != NULL &&
Cmnd->host->hostdata != NULL &&
is_private_data_of_cpqfc((CPQFCHBA *) Cmnd->host->hostdata,
Cmnd->sc_request->upper_private_data)) {
/* This is a passthru... */
cpqfc_passthru_private_t *pd;
pd = Cmnd->sc_request->upper_private_data;
Cmnd->SCp.phase = pd->bus;
// Cmnd->SCp.have_data_in = pd->pdrive;
Cmnd->SCp.have_data_in = Cmnd->lun;
} else {
/* This is not a passthru... */
// set the FCP-LUN addressing type
Cmnd->SCp.phase = pLoggedInPort->ScsiNexus.VolumeSetAddressing;
......@@ -3506,7 +3524,6 @@ static void UnblockScsiDevice( struct Scsi_Host *HostAdapter,
{
printk("LinkDnCmnd scsi_done ptr null, port_id %Xh\n",
pLoggedInPort->port_id);
Cmnd->SCp.sent_command = 0;
}
else
call_scsi_done(Cmnd);
......@@ -5234,7 +5251,6 @@ static ULONG build_SEST_sgList(
sgl = (struct scatterlist*)Cmnd->request_buffer;
sg_count = pci_map_sg(pcidev, sgl, Cmnd->use_sg,
scsi_to_pci_dma_dir(Cmnd->sc_data_direction));
// printk("sgl = %p, sg_count = %d\n", (void *) sgl, sg_count);
if( sg_count <= 3 ) {
// we need to be careful here that no individual mapping
......@@ -5263,7 +5279,6 @@ static ULONG build_SEST_sgList(
// printk("totalsgs = %d, sgcount=%d\n",totalsgs,sg_count);
}
// printk("totalsgs = %d, sgcount=%d\n", totalsgs, sg_count);
if( totalsgs <= 3 ) // can (must) use "local" SEST list
{
while( bytes_to_go)
......@@ -6166,13 +6181,11 @@ void cpqfcTSCompleteExchange(
}
else
{
Exchanges->fcExchange[ x_ID ].Cmnd->SCp.sent_command = 0;
// printk(" not calling scsi_done on x_ID %Xh, Cmnd %p\n",
// x_ID, Exchanges->fcExchange[ x_ID ].Cmnd);
}
}
else{
Exchanges->fcExchange[ x_ID ].Cmnd->SCp.sent_command = 0;
printk(" x_ID %Xh, type %Xh, Cdb0 %Xh\n", x_ID,
Exchanges->fcExchange[ x_ID ].type,
Exchanges->fcExchange[ x_ID ].Cmnd->cmnd[0]);
......@@ -6465,10 +6478,10 @@ static int build_FCP_payload( Scsi_Cmnd *Cmnd,
for( i=0; (i < Cmnd->cmd_len) && i < MAX_COMMAND_SIZE; i++)
*payload++ = Cmnd->cmnd[i];
if( Cmnd->cmd_len == 16 )
{
memcpy( payload, &Cmnd->SCp.buffers_residual, 4);
}
// if( Cmnd->cmd_len == 16 )
// {
// memcpy( payload, &Cmnd->SCp.buffers_residual, 4);
// }
payload+= (16 - i);
// FCP_DL is largest number of expected data bytes
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment