Commit 130fbeeb authored by James Bottomley's avatar James Bottomley

Merge ssh://linux-scsi@linux-scsi.bkbits.net/scsi-for-linus-2.5

into mulgrave.(none):/home/jejb/BK/scsi-for-linus-2.5
parents d572f1a5 8403fb48
...@@ -7,11 +7,18 @@ Tested in single and dual HBA configuration, 32 and 64bit busses, ...@@ -7,11 +7,18 @@ Tested in single and dual HBA configuration, 32 and 64bit busses,
SEST size 512 Exchanges (simultaneous I/Os) limited by module kmalloc() SEST size 512 Exchanges (simultaneous I/Os) limited by module kmalloc()
max of 128k bytes contiguous. 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 Ver 2.5.0 Nov 29, 2001
* eliminated io_request_lock. This change makes the driver specific * eliminated io_request_lock. This change makes the driver specific
to the 2.5.x kernels. to the 2.5.x kernels.
* silenced excessively noisy printks. * silenced excessively noisy printks.
Ver 2.1.2 July 23, 2002
* initialize DumCmnd->lun in cpqfcTS_ioctl (used in fcFindLoggedInPorts as LUN index)
Ver 2.1.1 Oct 18, 2001 Ver 2.1.1 Oct 18, 2001
* reinitialize Cmnd->SCp.sent_command (used to identify commands as * reinitialize Cmnd->SCp.sent_command (used to identify commands as
passthrus) on calling scsi_done, since the scsi mid layer does not passthrus) on calling scsi_done, since the scsi mid layer does not
......
This diff is collapsed.
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
// don't forget to also change MODULE_DESCRIPTION in cpqfcTSinit.c // don't forget to also change MODULE_DESCRIPTION in cpqfcTSinit.c
#define VER_MAJOR 2 #define VER_MAJOR 2
#define VER_MINOR 5 #define VER_MINOR 5
#define VER_SUBMINOR 0 #define VER_SUBMINOR 3
// Macros for kernel (esp. SMP) tracing using a PCI analyzer // Macros for kernel (esp. SMP) tracing using a PCI analyzer
// (e.g. x86). // (e.g. x86).
...@@ -907,9 +907,17 @@ typedef struct ...@@ -907,9 +907,17 @@ typedef struct
} FC_SCSI_QUE, *PFC_SCSI_QUE; } 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 #define DYNAMIC_ALLOCATIONS 4 // Tachyon aligned allocations: ERQ,IMQ,SFQ,SEST
...@@ -949,6 +957,8 @@ typedef struct ...@@ -949,6 +957,8 @@ typedef struct
PFC_LINK_QUE fcLQ; // the WorkerThread operates on this PFC_LINK_QUE fcLQ; // the WorkerThread operates on this
spinlock_t hba_spinlock; // held/released by WorkerThread spinlock_t hba_spinlock; // held/released by WorkerThread
cpqfc_passthru_private_t *private_data_pool;
unsigned long *private_data_bits;
} CPQFCHBA; } CPQFCHBA;
...@@ -1405,6 +1415,7 @@ struct ext_sg_entry_t { ...@@ -1405,6 +1415,7 @@ struct ext_sg_entry_t {
__u32 lba; /* lower bus address bits 0-31 */ __u32 lba; /* lower bus address bits 0-31 */
}; };
// J. McCarty's LINK.H // J. McCarty's LINK.H
// //
// LS_RJT Reason Codes // LS_RJT Reason Codes
......
...@@ -2887,15 +2887,22 @@ static void ScsiReportLunsDone(Scsi_Cmnd *Cmnd) ...@@ -2887,15 +2887,22 @@ static void ScsiReportLunsDone(Scsi_Cmnd *Cmnd)
Done: 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 static void
call_scsi_done(Scsi_Cmnd *Cmnd) call_scsi_done(Scsi_Cmnd *Cmnd)
{ {
// We have to reinitialize sent_command here, so the scsi-mid CPQFCHBA *hba;
// layer won't re-use the scsi command leaving it set incorrectly. hba = (CPQFCHBA *) Cmnd->host->hostdata;
// (incorrectly for our purposes...it's normally unused.) // Was this command a cpqfc passthru ioctl ?
if (Cmnd->sc_request != NULL && Cmnd->host != NULL &&
if (Cmnd->SCp.sent_command != 0) { // was it a passthru? Cmnd->host->hostdata != NULL &&
Cmnd->SCp.sent_command = 0; 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 &= 0xff00ffff;
Cmnd->result |= (DID_PASSTHROUGH << 16); // prevents retry Cmnd->result |= (DID_PASSTHROUGH << 16); // prevents retry
} }
...@@ -3293,6 +3300,7 @@ static int GetLoopID( ULONG al_pa ) ...@@ -3293,6 +3300,7 @@ static int GetLoopID( ULONG al_pa )
} }
#endif #endif
extern cpqfc_passthru_private_t *cpqfc_private(Scsi_Request *sr);
// Search the singly (forward) linked list "fcPorts" looking for // Search the singly (forward) linked list "fcPorts" looking for
// either the SCSI target (if != -1), port_id (if not NULL), // either the SCSI target (if != -1), port_id (if not NULL),
...@@ -3366,8 +3374,18 @@ PFC_LOGGEDIN_PORT fcFindLoggedInPort( ...@@ -3366,8 +3374,18 @@ PFC_LOGGEDIN_PORT fcFindLoggedInPort(
{ {
// For "passthru" modes, the IOCTL caller is responsible // For "passthru" modes, the IOCTL caller is responsible
// for setting the FCP-LUN addressing // 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 // set the FCP-LUN addressing type
Cmnd->SCp.phase = pLoggedInPort->ScsiNexus.VolumeSetAddressing; Cmnd->SCp.phase = pLoggedInPort->ScsiNexus.VolumeSetAddressing;
...@@ -3380,6 +3398,8 @@ PFC_LOGGEDIN_PORT fcFindLoggedInPort( ...@@ -3380,6 +3398,8 @@ PFC_LOGGEDIN_PORT fcFindLoggedInPort(
// Report Luns command // Report Luns command
if( pLoggedInPort->ScsiNexus.LunMasking == 1) if( pLoggedInPort->ScsiNexus.LunMasking == 1)
{ {
if (Cmnd->lun > sizeof(pLoggedInPort->ScsiNexus.lun))
return NULL;
// we KNOW all the valid LUNs... 0xFF is invalid! // we KNOW all the valid LUNs... 0xFF is invalid!
Cmnd->SCp.have_data_in = pLoggedInPort->ScsiNexus.lun[Cmnd->lun]; Cmnd->SCp.have_data_in = pLoggedInPort->ScsiNexus.lun[Cmnd->lun];
if (pLoggedInPort->ScsiNexus.lun[Cmnd->lun] == 0xFF) if (pLoggedInPort->ScsiNexus.lun[Cmnd->lun] == 0xFF)
...@@ -3504,7 +3524,6 @@ static void UnblockScsiDevice( struct Scsi_Host *HostAdapter, ...@@ -3504,7 +3524,6 @@ static void UnblockScsiDevice( struct Scsi_Host *HostAdapter,
{ {
printk("LinkDnCmnd scsi_done ptr null, port_id %Xh\n", printk("LinkDnCmnd scsi_done ptr null, port_id %Xh\n",
pLoggedInPort->port_id); pLoggedInPort->port_id);
Cmnd->SCp.sent_command = 0;
} }
else else
call_scsi_done(Cmnd); call_scsi_done(Cmnd);
...@@ -5232,7 +5251,6 @@ static ULONG build_SEST_sgList( ...@@ -5232,7 +5251,6 @@ static ULONG build_SEST_sgList(
sgl = (struct scatterlist*)Cmnd->request_buffer; sgl = (struct scatterlist*)Cmnd->request_buffer;
sg_count = pci_map_sg(pcidev, sgl, Cmnd->use_sg, sg_count = pci_map_sg(pcidev, sgl, Cmnd->use_sg,
scsi_to_pci_dma_dir(Cmnd->sc_data_direction)); scsi_to_pci_dma_dir(Cmnd->sc_data_direction));
// printk("sgl = %p, sg_count = %d\n", (void *) sgl, sg_count);
if( sg_count <= 3 ) { if( sg_count <= 3 ) {
// we need to be careful here that no individual mapping // we need to be careful here that no individual mapping
...@@ -5261,7 +5279,6 @@ static ULONG build_SEST_sgList( ...@@ -5261,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);
} }
// printk("totalsgs = %d, sgcount=%d\n", totalsgs, sg_count);
if( totalsgs <= 3 ) // can (must) use "local" SEST list if( totalsgs <= 3 ) // can (must) use "local" SEST list
{ {
while( bytes_to_go) while( bytes_to_go)
...@@ -6164,13 +6181,11 @@ void cpqfcTSCompleteExchange( ...@@ -6164,13 +6181,11 @@ void cpqfcTSCompleteExchange(
} }
else else
{ {
Exchanges->fcExchange[ x_ID ].Cmnd->SCp.sent_command = 0;
// printk(" not calling scsi_done on x_ID %Xh, Cmnd %p\n", // printk(" not calling scsi_done on x_ID %Xh, Cmnd %p\n",
// x_ID, Exchanges->fcExchange[ x_ID ].Cmnd); // x_ID, Exchanges->fcExchange[ x_ID ].Cmnd);
} }
} }
else{ else{
Exchanges->fcExchange[ x_ID ].Cmnd->SCp.sent_command = 0;
printk(" x_ID %Xh, type %Xh, Cdb0 %Xh\n", x_ID, printk(" x_ID %Xh, type %Xh, Cdb0 %Xh\n", x_ID,
Exchanges->fcExchange[ x_ID ].type, Exchanges->fcExchange[ x_ID ].type,
Exchanges->fcExchange[ x_ID ].Cmnd->cmnd[0]); Exchanges->fcExchange[ x_ID ].Cmnd->cmnd[0]);
...@@ -6463,10 +6478,10 @@ static int build_FCP_payload( Scsi_Cmnd *Cmnd, ...@@ -6463,10 +6478,10 @@ static int build_FCP_payload( Scsi_Cmnd *Cmnd,
for( i=0; (i < Cmnd->cmd_len) && i < MAX_COMMAND_SIZE; i++) for( i=0; (i < Cmnd->cmd_len) && i < MAX_COMMAND_SIZE; i++)
*payload++ = Cmnd->cmnd[i]; *payload++ = Cmnd->cmnd[i];
if( Cmnd->cmd_len == 16 ) // if( Cmnd->cmd_len == 16 )
{ // {
memcpy( payload, &Cmnd->SCp.buffers_residual, 4); // memcpy( payload, &Cmnd->SCp.buffers_residual, 4);
} // }
payload+= (16 - i); payload+= (16 - i);
// FCP_DL is largest number of expected data bytes // FCP_DL is largest number of expected data bytes
......
This diff is collapsed.
#ifndef _SCSI_DEBUG_H #ifndef _SCSI_DEBUG_H
#include <linux/types.h> #include <linux/types.h>
#include <linux/kdev_t.h>
static int scsi_debug_detect(Scsi_Host_Template *); static int scsi_debug_detect(Scsi_Host_Template *);
static int scsi_debug_release(struct Scsi_Host *);
/* static int scsi_debug_command(Scsi_Cmnd *); */ /* static int scsi_debug_command(Scsi_Cmnd *); */
static int scsi_debug_queuecommand(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); static int scsi_debug_queuecommand(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
static int scsi_debug_abort(Scsi_Cmnd *); static int scsi_debug_ioctl(Scsi_Device *, int, void *);
static int scsi_debug_biosparam(Disk *, struct block_device *, int[]); static int scsi_debug_biosparam(Disk *, struct block_device *, int[]);
static int scsi_debug_abort(Scsi_Cmnd *);
static int scsi_debug_bus_reset(Scsi_Cmnd *); static int scsi_debug_bus_reset(Scsi_Cmnd *);
static int scsi_debug_device_reset(Scsi_Cmnd *); static int scsi_debug_device_reset(Scsi_Cmnd *);
static int scsi_debug_host_reset(Scsi_Cmnd *); static int scsi_debug_host_reset(Scsi_Cmnd *);
...@@ -20,29 +23,29 @@ static const char * scsi_debug_info(struct Scsi_Host *); ...@@ -20,29 +23,29 @@ static const char * scsi_debug_info(struct Scsi_Host *);
/* /*
* This driver is written for the lk 2.5 series * This driver is written for the lk 2.5 series
*/ */
#define SCSI_DEBUG_CANQUEUE 255 #define SCSI_DEBUG_CANQUEUE 255 /* needs to be >= 1 */
#define SCSI_DEBUG_MAX_CMD_LEN 16 #define SCSI_DEBUG_MAX_CMD_LEN 16
#define SCSI_DEBUG_TEMPLATE \ static Scsi_Host_Template driver_template = {
{proc_info: scsi_debug_proc_info, \ .proc_info = scsi_debug_proc_info,
name: "SCSI DEBUG", \ .name = "SCSI DEBUG",
info: scsi_debug_info, \ .info = scsi_debug_info,
detect: scsi_debug_detect, \ .detect = scsi_debug_detect,
release: scsi_debug_release, \ .release = scsi_debug_release,
ioctl: scsi_debug_ioctl, \ .ioctl = scsi_debug_ioctl,
queuecommand: scsi_debug_queuecommand, \ .queuecommand = scsi_debug_queuecommand,
eh_abort_handler: scsi_debug_abort, \ .eh_abort_handler = scsi_debug_abort,
eh_bus_reset_handler: scsi_debug_bus_reset, \ .eh_bus_reset_handler = scsi_debug_bus_reset,
eh_device_reset_handler: scsi_debug_device_reset, \ .eh_device_reset_handler = scsi_debug_device_reset,
eh_host_reset_handler: scsi_debug_host_reset, \ .eh_host_reset_handler = scsi_debug_host_reset,
bios_param: scsi_debug_biosparam, \ .bios_param = scsi_debug_biosparam,
can_queue: SCSI_DEBUG_CANQUEUE, \ .can_queue = SCSI_DEBUG_CANQUEUE,
this_id: 7, \ .this_id = 7,
sg_tablesize: 64, \ .sg_tablesize = 64,
cmd_per_lun: 3, \ .cmd_per_lun = 3,
unchecked_isa_dma: 0, \ .unchecked_isa_dma = 0,
use_clustering: ENABLE_CLUSTERING, \ .use_clustering = ENABLE_CLUSTERING,
} }; /* the name 'driver_template' is used by scsi_module.c */
#endif #endif
...@@ -34,12 +34,15 @@ scsi_module.c is normally included at the end of a lower ...@@ -34,12 +34,15 @@ scsi_module.c is normally included at the end of a lower
level driver. For it to work a declaration like this is needed before level driver. For it to work a declaration like this is needed before
it is included: it is included:
static Scsi_Host_Template driver_template = DRIVER_TEMPLATE; static Scsi_Host_Template driver_template = DRIVER_TEMPLATE;
/* DRIVER_TEMPLATE should contain pointers to supported interface
functions. Scsi_Host_Template is defined in hosts.h */
#include "scsi_module.c" #include "scsi_module.c"
In this case "DRIVER_TEMPLATE" is defined to be a structure initializer
that is placed in the driver header file by convention. It contains
pointers to supported interface functions and other values.
Scsi_Host_Template is defined in hosts.h .
The scsi_module.c assumes the name "driver_template" is appropriately The scsi_module.c assumes the name "driver_template" is appropriately
defined. It contains 2 functions: defined. scsi_module.c contains 2 functions:
1) init_this_scsi_driver() called during builtin and module driver 1) init_this_scsi_driver() called during builtin and module driver
initialization: invokes mid level's scsi_register_host() initialization: invokes mid level's scsi_register_host()
2) exit_this_scsi_driver() called during closedown: invokes 2) exit_this_scsi_driver() called during closedown: invokes
...@@ -68,7 +71,7 @@ The interface functions are listed below in alphabetical order. ...@@ -68,7 +71,7 @@ The interface functions are listed below in alphabetical order.
/** /**
* bios_param - fetch head, sector, cylinder info for a disk * bios_param - fetch head, sector, cylinder info for a disk
* @sdkp: pointer to disk structure (defined in sd.h) * @sdkp: pointer to disk structure (defined in sd.h)
* @dev: corresponds to dev_t of device file name (e.g. /dev/sdb) * @bdev: pointer to block device context (defined in fs.h)
* @params: three element array to place output: * @params: three element array to place output:
* params[0] number of heads * params[0] number of heads
* params[1] number of sectors * params[1] number of sectors
...@@ -267,6 +270,8 @@ The interface functions are listed below in alphabetical order. ...@@ -267,6 +270,8 @@ The interface functions are listed below in alphabetical order.
* unsupported ioctl() 'cmd' numbers should return -ENOTTY. * unsupported ioctl() 'cmd' numbers should return -ENOTTY.
* However the mid level returns -EINVAL for unrecognized 'cmd' * However the mid level returns -EINVAL for unrecognized 'cmd'
* numbers when this function is not supplied by the driver. * numbers when this function is not supplied by the driver.
* Unfortunately some applications expect -EINVAL and react badly
* when -ENOTTY is returned; stick with -EINVAL.
**/ **/
int ioctl(Scsi_Device *sdp, int cmd, void *arg); int ioctl(Scsi_Device *sdp, int cmd, void *arg);
...@@ -304,7 +309,10 @@ int proc_info(char * buffer, char ** start, off_t offset, ...@@ -304,7 +309,10 @@ int proc_info(char * buffer, char ** start, off_t offset,
* @scp: pointer to scsi command object * @scp: pointer to scsi command object
* @done: function pointer to be invoked on completion * @done: function pointer to be invoked on completion
* *
* Returns 1 if the adapter is busy, else returns 0. * Returns 1 if the adapter (host) is busy, else returns 0. One
* reason for an adapter to be busy is that the number
* of outstanding queued commands is already equal to
* Scsi_Host::can_queue .
* *
* Required: if Scsi_Host::can_queue is ever non-zero * Required: if Scsi_Host::can_queue is ever non-zero
* then this function is required. * then this function is required.
...@@ -324,6 +332,9 @@ int proc_info(char * buffer, char ** start, off_t offset, ...@@ -324,6 +332,9 @@ int proc_info(char * buffer, char ** start, off_t offset,
* return value should be generated by this function. However, in * return value should be generated by this function. However, in
* this case, it should be placed in scp->result before this function * this case, it should be placed in scp->result before this function
* returns. * returns.
* If a status of CHECK CONDITION is placed in "result" when the
* 'done' callback is invoked, then the lower level driver should
* perform autosense and fill in the Scsi_Cmnd::sense_buffer array.
**/ **/
int queuecommand(Scsi_Cmnd * scp, void (*done)(Scsi_Cmnd *)); int queuecommand(Scsi_Cmnd * scp, void (*done)(Scsi_Cmnd *));
...@@ -505,6 +516,28 @@ lock of equal granularity (i.e. per host). Using finer grain locks ...@@ -505,6 +516,28 @@ lock of equal granularity (i.e. per host). Using finer grain locks
(e.g. per scsi device) may be possible by juggling locks in (e.g. per scsi device) may be possible by juggling locks in
queuecommand(). queuecommand().
Autosense
=========
Autosense (or auto-sense) is defined in the SAM-2 document as "the
automatic return of sense data to the application client coincident
with the completion of a SCSI command" when a status of CHECK CONDITION
occurs. Lower level drivers should perform autosense. This should be
done when the lower level driver detects a CHECK CONDITION status by either:
a) instructing the SCSI protocol (e.g. SCSI Parallel Interface (SPI))
to perform an extra data in phase on such responses
b) or, the lower level driver issuing a REQUEST SENSE command itself
Either way, the mid level decides whether the lower level driver has
performed autosense by checking Scsi_Cmnd::sense_buffer[0] . If this
byte has an upper nibble of 7 then autosense is assumed to have taken
place. If it has another value (and this byte is initialized to 0 before
each command) then the mid level will issue a REQUEST SENSE command.
In the presence of queued commands the "nexus" that maintains sense
buffer data from the command that failed until a following REQUEST SENSE
may get out of synchronization. This is why it is best for the lower
level driver to perform autosense.
Changes since lk 2.4 series Changes since lk 2.4 series
=========================== ===========================
...@@ -514,6 +547,7 @@ per scsi host. ...@@ -514,6 +547,7 @@ per scsi host.
The older error handling mechanism has been removed. This means the The older error handling mechanism has been removed. This means the
lower level interface functions abort() and reset() have been removed. lower level interface functions abort() and reset() have been removed.
The Scsi_Host_Template::use_new_eh_code flag has been removed.
In the 2.4 series the scsi subsystem configuration descriptions were In the 2.4 series the scsi subsystem configuration descriptions were
aggregated with the configuration descriptions from all other Linux aggregated with the configuration descriptions from all other Linux
...@@ -532,4 +566,4 @@ The following people have contributed to this document: ...@@ -532,4 +566,4 @@ The following people have contributed to this document:
Douglas Gilbert Douglas Gilbert
dgilbert@interlog.com dgilbert@interlog.com
27th April 2002 13th August 2002
This diff is collapsed.
This diff is collapsed.
...@@ -11,9 +11,13 @@ Original driver (sg.h): ...@@ -11,9 +11,13 @@ Original driver (sg.h):
Version 2 and 3 extensions to driver: Version 2 and 3 extensions to driver:
* Copyright (C) 1998 - 2002 Douglas Gilbert * Copyright (C) 1998 - 2002 Douglas Gilbert
Version: 3.5.26 (20020708) Version: 3.5.27 (20020812)
This version is for 2.5 series kernels. This version is for 2.5 series kernels.
Changes since 3.5.26 (20020708)
- re-add direct IO using Kai Makisara's work
- re-tab to 8, start using C99-isms
- simplify memory management
Changes since 3.5.25 (20020504) Changes since 3.5.25 (20020504)
- driverfs additions - driverfs additions
- copy_to/from_user() fixes [William Stinson] - copy_to/from_user() fixes [William Stinson]
......
...@@ -129,6 +129,7 @@ EXPORT_SYMBOL(highmem_start_page); ...@@ -129,6 +129,7 @@ EXPORT_SYMBOL(highmem_start_page);
EXPORT_SYMBOL(kmap_prot); EXPORT_SYMBOL(kmap_prot);
EXPORT_SYMBOL(kmap_pte); EXPORT_SYMBOL(kmap_pte);
#endif #endif
EXPORT_SYMBOL(get_user_pages);
/* filesystem internal functions */ /* filesystem internal functions */
EXPORT_SYMBOL(def_blk_fops); EXPORT_SYMBOL(def_blk_fops);
......
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