Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
3eff4c78
Commit
3eff4c78
authored
Dec 22, 2016
by
James Bottomley
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'misc' into for-linus
parents
d2a14525
ae2aae24
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
283 additions
and
165 deletions
+283
-165
Documentation/scsi/g_NCR5380.txt
Documentation/scsi/g_NCR5380.txt
+23
-23
drivers/scsi/NCR5380.c
drivers/scsi/NCR5380.c
+1
-76
drivers/scsi/NCR5380.h
drivers/scsi/NCR5380.h
+0
-11
drivers/scsi/aacraid/linit.c
drivers/scsi/aacraid/linit.c
+0
-2
drivers/scsi/g_NCR5380.c
drivers/scsi/g_NCR5380.c
+130
-23
drivers/scsi/g_NCR5380.h
drivers/scsi/g_NCR5380.h
+2
-0
drivers/scsi/ibmvscsi/ibmvscsi.c
drivers/scsi/ibmvscsi/ibmvscsi.c
+6
-1
drivers/scsi/ibmvscsi/ibmvscsi.h
drivers/scsi/ibmvscsi/ibmvscsi.h
+1
-0
drivers/scsi/ufs/ufs-qcom.c
drivers/scsi/ufs/ufs-qcom.c
+42
-2
drivers/scsi/ufs/ufs-qcom.h
drivers/scsi/ufs/ufs-qcom.h
+1
-0
drivers/scsi/ufs/ufs_quirks.h
drivers/scsi/ufs/ufs_quirks.h
+9
-21
drivers/scsi/ufs/ufshcd.c
drivers/scsi/ufs/ufshcd.c
+51
-4
drivers/scsi/ufs/ufshcd.h
drivers/scsi/ufs/ufshcd.h
+10
-2
drivers/scsi/ufs/ufshci.h
drivers/scsi/ufs/ufshci.h
+7
-0
No files found.
Documentation/scsi/g_NCR5380.txt
View file @
3eff4c78
...
...
@@ -6,17 +6,15 @@ NCR53c400 extensions (c) 1994,1995,1996 Kevin Lentin
This file documents the NCR53c400 extensions by Kevin Lentin and some
enhancements to the NCR5380 core.
This driver supports both NCR5380 and NCR53c400 cards in port or memory
mapped modes. Currently this driver can only support one of those mapping
modes at a time but it does support both of these chips at the same time.
The next release of this driver will support port & memory mapped cards at
the same time. It should be able to handle multiple different cards in the
same machine.
This driver supports NCR5380 and NCR53c400 and compatible cards in port or
memory mapped modes.
The drivers/scsi/Makefile has an override in it for the most common
NCR53c400 card, the Trantor T130B in its default configuration:
Port: 0x350
IRQ : 5
Use of an interrupt is recommended, if supported by the board, as this will
allow targets to disconnect and thereby improve SCSI bus utilization.
If the irq parameter is 254 or is omitted entirely, the driver will probe
for the correct IRQ line automatically. If the irq parameter is 0 or 255
then no IRQ will be used.
The NCR53c400 does not support DMA but it does have Pseudo-DMA which is
supported by the driver.
...
...
@@ -47,22 +45,24 @@ These old-style parameters can support only one card:
dtc_3181e=1 to set up for a Domex Technology Corp 3181E board
hp_c2502=1 to set up for a Hewlett Packard C2502 board
e.g.
OLD: modprobe g_NCR5380 ncr_irq=5 ncr_addr=0x350 ncr_5380=1
NEW: modprobe g_NCR5380 irq=5 base=0x350 card=0
for a port mapped NCR5380 board or
OLD: modprobe g_NCR5380 ncr_irq=255 ncr_addr=0xc8000 ncr_53c400=1
NEW: modprobe g_NCR5380 irq=255 base=0xc8000 card=1
for a memory mapped NCR53C400 board with interrupts disabled or
E.g. Trantor T130B in its default configuration:
modprobe g_NCR5380 irq=5 base=0x350 card=1
or alternatively, using the old syntax,
modprobe g_NCR5380 ncr_irq=5 ncr_addr=0x350 ncr_53c400=1
NEW: modprobe g_NCR5380 irq=0,7 base=0x240,0x300 card=3,4
for two cards: DTC3181 (in non-PnP mode) at 0x240 with no IRQ
and HP C2502 at 0x300 with IRQ 7
E.g. a port mapped NCR5380 board, driver to probe for IRQ:
modprobe g_NCR5380 base=0x350 card=0
or alternatively,
modprobe g_NCR5380 ncr_addr=0x350 ncr_5380=1
(255 should be specified for no or DMA interrupt, 254 to autoprobe for an
IRQ line if overridden on the command line.)
E.g. a memory mapped NCR53C400 board with no IRQ:
modprobe g_NCR5380 irq=255 base=0xc8000 card=1
or alternatively,
modprobe g_NCR5380 ncr_irq=255 ncr_addr=0xc8000 ncr_53c400=1
E.g. two cards, DTC3181 (in non-PnP mode) at 0x240 with no IRQ
and HP C2502 at 0x300 with IRQ 7:
modprobe g_NCR5380 irq=0,7 base=0x240,0x300 card=3,4
Kevin Lentin
K.Lentin@cs.monash.edu.au
drivers/scsi/NCR5380.c
View file @
3eff4c78
...
...
@@ -97,9 +97,6 @@
* and macros and include this file in your driver.
*
* These macros control options :
* AUTOPROBE_IRQ - if defined, the NCR5380_probe_irq() function will be
* defined.
*
* AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
* for commands that return with a CHECK CONDITION status.
*
...
...
@@ -127,9 +124,7 @@
* NCR5380_dma_residual - residual byte count
*
* The generic driver is initialized by calling NCR5380_init(instance),
* after setting the appropriate host specific fields and ID. If the
* driver wishes to autoprobe for an IRQ line, the NCR5380_probe_irq(instance,
* possible) function may be used.
* after setting the appropriate host specific fields and ID.
*/
#ifndef NCR5380_io_delay
...
...
@@ -351,76 +346,6 @@ static void NCR5380_print_phase(struct Scsi_Host *instance)
}
#endif
static
int
probe_irq
;
/**
* probe_intr - helper for IRQ autoprobe
* @irq: interrupt number
* @dev_id: unused
* @regs: unused
*
* Set a flag to indicate the IRQ in question was received. This is
* used by the IRQ probe code.
*/
static
irqreturn_t
probe_intr
(
int
irq
,
void
*
dev_id
)
{
probe_irq
=
irq
;
return
IRQ_HANDLED
;
}
/**
* NCR5380_probe_irq - find the IRQ of an NCR5380
* @instance: NCR5380 controller
* @possible: bitmask of ISA IRQ lines
*
* Autoprobe for the IRQ line used by the NCR5380 by triggering an IRQ
* and then looking to see what interrupt actually turned up.
*/
static
int
__maybe_unused
NCR5380_probe_irq
(
struct
Scsi_Host
*
instance
,
int
possible
)
{
struct
NCR5380_hostdata
*
hostdata
=
shost_priv
(
instance
);
unsigned
long
timeout
;
int
trying_irqs
,
i
,
mask
;
for
(
trying_irqs
=
0
,
i
=
1
,
mask
=
2
;
i
<
16
;
++
i
,
mask
<<=
1
)
if
((
mask
&
possible
)
&&
(
request_irq
(
i
,
&
probe_intr
,
0
,
"NCR-probe"
,
NULL
)
==
0
))
trying_irqs
|=
mask
;
timeout
=
jiffies
+
msecs_to_jiffies
(
250
);
probe_irq
=
NO_IRQ
;
/*
* A interrupt is triggered whenever BSY = false, SEL = true
* and a bit set in the SELECT_ENABLE_REG is asserted on the
* SCSI bus.
*
* Note that the bus is only driven when the phase control signals
* (I/O, C/D, and MSG) match those in the TCR, so we must reset that
* to zero.
*/
NCR5380_write
(
TARGET_COMMAND_REG
,
0
);
NCR5380_write
(
SELECT_ENABLE_REG
,
hostdata
->
id_mask
);
NCR5380_write
(
OUTPUT_DATA_REG
,
hostdata
->
id_mask
);
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
|
ICR_ASSERT_DATA
|
ICR_ASSERT_SEL
);
while
(
probe_irq
==
NO_IRQ
&&
time_before
(
jiffies
,
timeout
))
schedule_timeout_uninterruptible
(
1
);
NCR5380_write
(
SELECT_ENABLE_REG
,
0
);
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
);
for
(
i
=
1
,
mask
=
2
;
i
<
16
;
++
i
,
mask
<<=
1
)
if
(
trying_irqs
&
mask
)
free_irq
(
i
,
NULL
);
return
probe_irq
;
}
/**
* NCR58380_info - report driver and host information
* @instance: relevant scsi host instance
...
...
drivers/scsi/NCR5380.h
View file @
3eff4c78
...
...
@@ -199,16 +199,6 @@
#define PHASE_SR_TO_TCR(phase) ((phase) >> 2)
/*
* These are "special" values for the irq and dma_channel fields of the
* Scsi_Host structure
*/
#define DMA_NONE 255
#define IRQ_AUTO 254
#define DMA_AUTO 254
#define PORT_AUTO 0xffff
/* autoprobe io port for 53c400a */
#ifndef NO_IRQ
#define NO_IRQ 0
#endif
...
...
@@ -290,7 +280,6 @@ static void NCR5380_print(struct Scsi_Host *instance);
#define NCR5380_dprint_phase(flg, arg) do {} while (0)
#endif
static
int
NCR5380_probe_irq
(
struct
Scsi_Host
*
instance
,
int
possible
);
static
int
NCR5380_init
(
struct
Scsi_Host
*
instance
,
int
flags
);
static
int
NCR5380_maybe_reset_bus
(
struct
Scsi_Host
*
);
static
void
NCR5380_exit
(
struct
Scsi_Host
*
instance
);
...
...
drivers/scsi/aacraid/linit.c
View file @
3eff4c78
...
...
@@ -160,7 +160,6 @@ static const struct pci_device_id aac_pci_tbl[] = {
{
0x9005
,
0x028b
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
62
},
/* Adaptec PMC Series 6 (Tupelo) */
{
0x9005
,
0x028c
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
63
},
/* Adaptec PMC Series 7 (Denali) */
{
0x9005
,
0x028d
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
64
},
/* Adaptec PMC Series 8 */
{
0x9005
,
0x028f
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
65
},
/* Adaptec PMC Series 9 */
{
0
,}
};
MODULE_DEVICE_TABLE
(
pci
,
aac_pci_tbl
);
...
...
@@ -239,7 +238,6 @@ static struct aac_driver_ident aac_drivers[] = {
{
aac_src_init
,
"aacraid"
,
"ADAPTEC "
,
"RAID "
,
2
,
AAC_QUIRK_SRC
},
/* Adaptec PMC Series 6 (Tupelo) */
{
aac_srcv_init
,
"aacraid"
,
"ADAPTEC "
,
"RAID "
,
2
,
AAC_QUIRK_SRC
},
/* Adaptec PMC Series 7 (Denali) */
{
aac_srcv_init
,
"aacraid"
,
"ADAPTEC "
,
"RAID "
,
2
,
AAC_QUIRK_SRC
},
/* Adaptec PMC Series 8 */
{
aac_srcv_init
,
"aacraid"
,
"ADAPTEC "
,
"RAID "
,
2
,
AAC_QUIRK_SRC
}
/* Adaptec PMC Series 9 */
};
/**
...
...
drivers/scsi/g_NCR5380.c
View file @
3eff4c78
...
...
@@ -37,7 +37,7 @@
#define MAX_CARDS 8
/* old-style parameters for compatibility */
static
int
ncr_irq
;
static
int
ncr_irq
=
-
1
;
static
int
ncr_addr
;
static
int
ncr_5380
;
static
int
ncr_53c400
;
...
...
@@ -52,9 +52,9 @@ module_param(ncr_53c400a, int, 0);
module_param
(
dtc_3181e
,
int
,
0
);
module_param
(
hp_c2502
,
int
,
0
);
static
int
irq
[]
=
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
static
int
irq
[]
=
{
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
};
module_param_array
(
irq
,
int
,
NULL
,
0
);
MODULE_PARM_DESC
(
irq
,
"IRQ number(s)"
);
MODULE_PARM_DESC
(
irq
,
"IRQ number(s)
(0=none, 254=auto [default])
"
);
static
int
base
[]
=
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
module_param_array
(
base
,
int
,
NULL
,
0
);
...
...
@@ -67,6 +67,56 @@ MODULE_PARM_DESC(card, "card type (0=NCR5380, 1=NCR53C400, 2=NCR53C400A, 3=DTC31
MODULE_ALIAS
(
"g_NCR5380_mmio"
);
MODULE_LICENSE
(
"GPL"
);
static
void
g_NCR5380_trigger_irq
(
struct
Scsi_Host
*
instance
)
{
struct
NCR5380_hostdata
*
hostdata
=
shost_priv
(
instance
);
/*
* An interrupt is triggered whenever BSY = false, SEL = true
* and a bit set in the SELECT_ENABLE_REG is asserted on the
* SCSI bus.
*
* Note that the bus is only driven when the phase control signals
* (I/O, C/D, and MSG) match those in the TCR.
*/
NCR5380_write
(
TARGET_COMMAND_REG
,
PHASE_SR_TO_TCR
(
NCR5380_read
(
STATUS_REG
)
&
PHASE_MASK
));
NCR5380_write
(
SELECT_ENABLE_REG
,
hostdata
->
id_mask
);
NCR5380_write
(
OUTPUT_DATA_REG
,
hostdata
->
id_mask
);
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
|
ICR_ASSERT_DATA
|
ICR_ASSERT_SEL
);
msleep
(
1
);
NCR5380_write
(
INITIATOR_COMMAND_REG
,
ICR_BASE
);
NCR5380_write
(
SELECT_ENABLE_REG
,
0
);
NCR5380_write
(
TARGET_COMMAND_REG
,
0
);
}
/**
* g_NCR5380_probe_irq - find the IRQ of a NCR5380 or equivalent
* @instance: SCSI host instance
*
* Autoprobe for the IRQ line used by the card by triggering an IRQ
* and then looking to see what interrupt actually turned up.
*/
static
int
g_NCR5380_probe_irq
(
struct
Scsi_Host
*
instance
)
{
struct
NCR5380_hostdata
*
hostdata
=
shost_priv
(
instance
);
int
irq_mask
,
irq
;
NCR5380_read
(
RESET_PARITY_INTERRUPT_REG
);
irq_mask
=
probe_irq_on
();
g_NCR5380_trigger_irq
(
instance
);
irq
=
probe_irq_off
(
irq_mask
);
NCR5380_read
(
RESET_PARITY_INTERRUPT_REG
);
if
(
irq
<=
0
)
return
NO_IRQ
;
return
irq
;
}
/*
* Configure I/O address of 53C400A or DTC436 by writing magic numbers
* to ports 0x779 and 0x379.
...
...
@@ -81,14 +131,33 @@ static void magic_configure(int idx, u8 irq, u8 magic[])
outb
(
magic
[
3
],
0x379
);
outb
(
magic
[
4
],
0x379
);
/* allowed IRQs for HP C2502 */
if
(
irq
!=
2
&&
irq
!=
3
&&
irq
!=
4
&&
irq
!=
5
&&
irq
!=
7
)
irq
=
0
;
if
(
irq
==
9
)
irq
=
2
;
if
(
idx
>=
0
&&
idx
<=
7
)
cfg
=
0x80
|
idx
|
(
irq
<<
4
);
outb
(
cfg
,
0x379
);
}
static
irqreturn_t
legacy_empty_irq_handler
(
int
irq
,
void
*
dev_id
)
{
return
IRQ_HANDLED
;
}
static
int
legacy_find_free_irq
(
int
*
irq_table
)
{
while
(
*
irq_table
!=
-
1
)
{
if
(
!
request_irq
(
*
irq_table
,
legacy_empty_irq_handler
,
IRQF_PROBE_SHARED
,
"Test IRQ"
,
(
void
*
)
irq_table
))
{
free_irq
(
*
irq_table
,
(
void
*
)
irq_table
);
return
*
irq_table
;
}
irq_table
++
;
}
return
-
1
;
}
static
unsigned
int
ncr_53c400a_ports
[]
=
{
0x280
,
0x290
,
0x300
,
0x310
,
0x330
,
0x340
,
0x348
,
0x350
,
0
};
...
...
@@ -101,6 +170,9 @@ static u8 ncr_53c400a_magic[] = { /* 53C400A & DTC436 */
static
u8
hp_c2502_magic
[]
=
{
/* HP C2502 */
0x0f
,
0x22
,
0xf0
,
0x20
,
0x80
};
static
int
hp_c2502_irqs
[]
=
{
9
,
5
,
7
,
3
,
4
,
-
1
};
static
int
generic_NCR5380_init_one
(
struct
scsi_host_template
*
tpnt
,
struct
device
*
pdev
,
int
base
,
int
irq
,
int
board
)
...
...
@@ -248,6 +320,13 @@ static int generic_NCR5380_init_one(struct scsi_host_template *tpnt,
}
}
/* Check for vacant slot */
NCR5380_write
(
MODE_REG
,
0
);
if
(
NCR5380_read
(
MODE_REG
)
!=
0
)
{
ret
=
-
ENODEV
;
goto
out_unregister
;
}
ret
=
NCR5380_init
(
instance
,
flags
|
FLAG_LATE_DMA_SETUP
);
if
(
ret
)
goto
out_unregister
;
...
...
@@ -262,31 +341,59 @@ static int generic_NCR5380_init_one(struct scsi_host_template *tpnt,
NCR5380_maybe_reset_bus
(
instance
);
if
(
irq
!=
IRQ_AUTO
)
instance
->
irq
=
irq
;
else
instance
->
irq
=
NCR5380_probe_irq
(
instance
,
0xffff
);
/* Compatibility with documented NCR5380 kernel parameters */
if
(
instance
->
irq
==
255
)
instance
->
irq
=
NO_IRQ
;
if
(
irq
==
255
||
irq
==
0
)
irq
=
NO_IRQ
;
else
if
(
irq
==
-
1
)
irq
=
IRQ_AUTO
;
if
(
board
==
BOARD_HP_C2502
)
{
int
*
irq_table
=
hp_c2502_irqs
;
int
board_irq
=
-
1
;
switch
(
irq
)
{
case
NO_IRQ
:
board_irq
=
0
;
break
;
case
IRQ_AUTO
:
board_irq
=
legacy_find_free_irq
(
irq_table
);
break
;
default:
while
(
*
irq_table
!=
-
1
)
if
(
*
irq_table
++
==
irq
)
board_irq
=
irq
;
}
if
(
board_irq
<=
0
)
{
board_irq
=
0
;
irq
=
NO_IRQ
;
}
magic_configure
(
port_idx
,
board_irq
,
magic
);
}
if
(
irq
==
IRQ_AUTO
)
{
instance
->
irq
=
g_NCR5380_probe_irq
(
instance
);
if
(
instance
->
irq
==
NO_IRQ
)
shost_printk
(
KERN_INFO
,
instance
,
"no irq detected
\n
"
);
}
else
{
instance
->
irq
=
irq
;
if
(
instance
->
irq
==
NO_IRQ
)
shost_printk
(
KERN_INFO
,
instance
,
"no irq provided
\n
"
);
}
if
(
instance
->
irq
!=
NO_IRQ
)
{
/* set IRQ for HP C2502 */
if
(
board
==
BOARD_HP_C2502
)
magic_configure
(
port_idx
,
instance
->
irq
,
magic
);
if
(
request_irq
(
instance
->
irq
,
generic_NCR5380_intr
,
0
,
"NCR5380"
,
instance
))
{
printk
(
KERN_WARNING
"scsi%d : IRQ%d not free, interrupts disabled
\n
"
,
instance
->
host_no
,
instance
->
irq
);
instance
->
irq
=
NO_IRQ
;
shost_printk
(
KERN_INFO
,
instance
,
"irq %d denied
\n
"
,
instance
->
irq
);
}
else
{
shost_printk
(
KERN_INFO
,
instance
,
"irq %d acquired
\n
"
,
instance
->
irq
);
}
}
if
(
instance
->
irq
==
NO_IRQ
)
{
printk
(
KERN_INFO
"scsi%d : interrupts not enabled. for better interactive performance,
\n
"
,
instance
->
host_no
);
printk
(
KERN_INFO
"scsi%d : please jumper the board for a free IRQ.
\n
"
,
instance
->
host_no
);
}
ret
=
scsi_add_host
(
instance
,
pdev
);
if
(
ret
)
goto
out_free_irq
;
...
...
@@ -597,7 +704,7 @@ static int __init generic_NCR5380_init(void)
int
ret
=
0
;
/* compatibility with old-style parameters */
if
(
irq
[
0
]
==
0
&&
base
[
0
]
==
0
&&
card
[
0
]
==
-
1
)
{
if
(
irq
[
0
]
==
-
1
&&
base
[
0
]
==
0
&&
card
[
0
]
==
-
1
)
{
irq
[
0
]
=
ncr_irq
;
base
[
0
]
=
ncr_addr
;
if
(
ncr_5380
)
...
...
drivers/scsi/g_NCR5380.h
View file @
3eff4c78
...
...
@@ -51,4 +51,6 @@
#define BOARD_DTC3181E 3
#define BOARD_HP_C2502 4
#define IRQ_AUTO 254
#endif
/* GENERIC_NCR5380_H */
drivers/scsi/ibmvscsi/ibmvscsi.c
View file @
3eff4c78
...
...
@@ -95,6 +95,7 @@ static int fast_fail = 1;
static
int
client_reserve
=
1
;
static
char
partition_name
[
97
]
=
"UNKNOWN"
;
static
unsigned
int
partition_number
=
-
1
;
static
LIST_HEAD
(
ibmvscsi_head
);
static
struct
scsi_transport_template
*
ibmvscsi_transport_template
;
...
...
@@ -232,6 +233,7 @@ static void ibmvscsi_task(void *data)
while
((
crq
=
crq_queue_next_crq
(
&
hostdata
->
queue
))
!=
NULL
)
{
ibmvscsi_handle_crq
(
crq
,
hostdata
);
crq
->
valid
=
VIOSRP_CRQ_FREE
;
wmb
();
}
vio_enable_interrupts
(
vdev
);
...
...
@@ -240,6 +242,7 @@ static void ibmvscsi_task(void *data)
vio_disable_interrupts
(
vdev
);
ibmvscsi_handle_crq
(
crq
,
hostdata
);
crq
->
valid
=
VIOSRP_CRQ_FREE
;
wmb
();
}
else
{
done
=
1
;
}
...
...
@@ -992,7 +995,7 @@ static void handle_cmd_rsp(struct srp_event_struct *evt_struct)
if
(
unlikely
(
rsp
->
opcode
!=
SRP_RSP
))
{
if
(
printk_ratelimit
())
dev_warn
(
evt_struct
->
hostdata
->
dev
,
"bad SRP RSP type %
d
\n
"
,
rsp
->
opcode
);
"bad SRP RSP type %
#02x
\n
"
,
rsp
->
opcode
);
}
if
(
cmnd
)
{
...
...
@@ -2270,6 +2273,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
}
dev_set_drvdata
(
&
vdev
->
dev
,
hostdata
);
list_add_tail
(
&
hostdata
->
host_list
,
&
ibmvscsi_head
);
return
0
;
add_srp_port_failed:
...
...
@@ -2291,6 +2295,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
static
int
ibmvscsi_remove
(
struct
vio_dev
*
vdev
)
{
struct
ibmvscsi_host_data
*
hostdata
=
dev_get_drvdata
(
&
vdev
->
dev
);
list_del
(
&
hostdata
->
host_list
);
unmap_persist_bufs
(
hostdata
);
release_event_pool
(
&
hostdata
->
pool
,
hostdata
);
ibmvscsi_release_crq_queue
(
&
hostdata
->
queue
,
hostdata
,
...
...
drivers/scsi/ibmvscsi/ibmvscsi.h
View file @
3eff4c78
...
...
@@ -90,6 +90,7 @@ struct event_pool {
/* all driver data associated with a host adapter */
struct
ibmvscsi_host_data
{
struct
list_head
host_list
;
atomic_t
request_limit
;
int
client_migrated
;
int
reset_crq
;
...
...
drivers/scsi/ufs/ufs-qcom.c
View file @
3eff4c78
...
...
@@ -23,6 +23,7 @@
#include "unipro.h"
#include "ufs-qcom.h"
#include "ufshci.h"
#include "ufs_quirks.h"
#define UFS_QCOM_DEFAULT_DBG_PRINT_EN \
(UFS_QCOM_DBG_PRINT_REGS_EN | UFS_QCOM_DBG_PRINT_TEST_BUS_EN)
...
...
@@ -1031,6 +1032,34 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba,
return
ret
;
}
static
int
ufs_qcom_quirk_host_pa_saveconfigtime
(
struct
ufs_hba
*
hba
)
{
int
err
;
u32
pa_vs_config_reg1
;
err
=
ufshcd_dme_get
(
hba
,
UIC_ARG_MIB
(
PA_VS_CONFIG_REG1
),
&
pa_vs_config_reg1
);
if
(
err
)
goto
out
;
/* Allow extension of MSB bits of PA_SaveConfigTime attribute */
err
=
ufshcd_dme_set
(
hba
,
UIC_ARG_MIB
(
PA_VS_CONFIG_REG1
),
(
pa_vs_config_reg1
|
(
1
<<
12
)));
out:
return
err
;
}
static
int
ufs_qcom_apply_dev_quirks
(
struct
ufs_hba
*
hba
)
{
int
err
=
0
;
if
(
hba
->
dev_quirks
&
UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME
)
err
=
ufs_qcom_quirk_host_pa_saveconfigtime
(
hba
);
return
err
;
}
static
u32
ufs_qcom_get_ufs_hci_version
(
struct
ufs_hba
*
hba
)
{
struct
ufs_qcom_host
*
host
=
ufshcd_get_variant
(
hba
);
...
...
@@ -1194,7 +1223,16 @@ static int ufs_qcom_init(struct ufs_hba *hba)
*/
host
->
generic_phy
=
devm_phy_get
(
dev
,
"ufsphy"
);
if
(
IS_ERR
(
host
->
generic_phy
))
{
if
(
host
->
generic_phy
==
ERR_PTR
(
-
EPROBE_DEFER
))
{
/*
* UFS driver might be probed before the phy driver does.
* In that case we would like to return EPROBE_DEFER code.
*/
err
=
-
EPROBE_DEFER
;
dev_warn
(
dev
,
"%s: required phy device. hasn't probed yet. err = %d
\n
"
,
__func__
,
err
);
goto
out_variant_clear
;
}
else
if
(
IS_ERR
(
host
->
generic_phy
))
{
err
=
PTR_ERR
(
host
->
generic_phy
);
dev_err
(
dev
,
"%s: PHY get failed %d
\n
"
,
__func__
,
err
);
goto
out_variant_clear
;
...
...
@@ -1432,7 +1470,8 @@ static void ufs_qcom_print_hw_debug_reg_all(struct ufs_hba *hba,
reg
=
ufs_qcom_get_debug_reg_offset
(
host
,
UFS_UFS_DBG_RD_PRDT_RAM
);
print_fn
(
hba
,
reg
,
64
,
"UFS_UFS_DBG_RD_PRDT_RAM "
,
priv
);
ufshcd_writel
(
hba
,
(
reg
&
~
UFS_BIT
(
17
)),
REG_UFS_CFG1
);
/* clear bit 17 - UTP_DBG_RAMS_EN */
ufshcd_rmwl
(
hba
,
UFS_BIT
(
17
),
0
,
REG_UFS_CFG1
);
reg
=
ufs_qcom_get_debug_reg_offset
(
host
,
UFS_DBG_RD_REG_UAWM
);
print_fn
(
hba
,
reg
,
4
,
"UFS_DBG_RD_REG_UAWM "
,
priv
);
...
...
@@ -1609,6 +1648,7 @@ static struct ufs_hba_variant_ops ufs_hba_qcom_vops = {
.
hce_enable_notify
=
ufs_qcom_hce_enable_notify
,
.
link_startup_notify
=
ufs_qcom_link_startup_notify
,
.
pwr_change_notify
=
ufs_qcom_pwr_change_notify
,
.
apply_dev_quirks
=
ufs_qcom_apply_dev_quirks
,
.
suspend
=
ufs_qcom_suspend
,
.
resume
=
ufs_qcom_resume
,
.
dbg_register_dump
=
ufs_qcom_dump_dbg_regs
,
...
...
drivers/scsi/ufs/ufs-qcom.h
View file @
3eff4c78
...
...
@@ -142,6 +142,7 @@ enum ufs_qcom_phy_init_type {
UFS_QCOM_DBG_PRINT_TEST_BUS_EN)
/* QUniPro Vendor specific attributes */
#define PA_VS_CONFIG_REG1 0x9000
#define DME_VS_CORE_CLK_CTRL 0xD002
/* bit and mask definitions for DME_VS_CORE_CLK_CTRL attribute */
#define DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT BIT(8)
...
...
drivers/scsi/ufs/ufs_quirks.h
View file @
3eff4c78
...
...
@@ -134,29 +134,17 @@ struct ufs_dev_fix {
*/
#define UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE (1 << 7)
/*
* The max. value PA_SaveConfigTime is 250 (10us) but this is not enough for
* some vendors.
* Gear switch from PWM to HS may fail even with this max. PA_SaveConfigTime.
* Gear switch can be issued by host controller as an error recovery and any
* software delay will not help on this case so we need to increase
* PA_SaveConfigTime to >32us as per vendor recommendation.
*/
#define UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME (1 << 8)
struct
ufs_hba
;
void
ufs_advertise_fixup_device
(
struct
ufs_hba
*
hba
);
static
struct
ufs_dev_fix
ufs_fixups
[]
=
{
/* UFS cards deviations table */
UFS_FIX
(
UFS_VENDOR_SAMSUNG
,
UFS_ANY_MODEL
,
UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM
),
UFS_FIX
(
UFS_VENDOR_SAMSUNG
,
UFS_ANY_MODEL
,
UFS_DEVICE_NO_VCCQ
),
UFS_FIX
(
UFS_VENDOR_SAMSUNG
,
UFS_ANY_MODEL
,
UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS
),
UFS_FIX
(
UFS_VENDOR_SAMSUNG
,
UFS_ANY_MODEL
,
UFS_DEVICE_NO_FASTAUTO
),
UFS_FIX
(
UFS_VENDOR_SAMSUNG
,
UFS_ANY_MODEL
,
UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE
),
UFS_FIX
(
UFS_VENDOR_TOSHIBA
,
UFS_ANY_MODEL
,
UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM
),
UFS_FIX
(
UFS_VENDOR_TOSHIBA
,
"THGLF2G9C8KBADG"
,
UFS_DEVICE_QUIRK_PA_TACTIVATE
),
UFS_FIX
(
UFS_VENDOR_TOSHIBA
,
"THGLF2G9D8KBADG"
,
UFS_DEVICE_QUIRK_PA_TACTIVATE
),
UFS_FIX
(
UFS_VENDOR_SKHYNIX
,
UFS_ANY_MODEL
,
UFS_DEVICE_NO_VCCQ
),
END_FIX
};
#endif
/* UFS_QUIRKS_H_ */
drivers/scsi/ufs/ufshcd.c
View file @
3eff4c78
...
...
@@ -185,6 +185,30 @@ ufs_get_pm_lvl_to_link_pwr_state(enum ufs_pm_level lvl)
return
ufs_pm_lvl_states
[
lvl
].
link_state
;
}
static
struct
ufs_dev_fix
ufs_fixups
[]
=
{
/* UFS cards deviations table */
UFS_FIX
(
UFS_VENDOR_SAMSUNG
,
UFS_ANY_MODEL
,
UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM
),
UFS_FIX
(
UFS_VENDOR_SAMSUNG
,
UFS_ANY_MODEL
,
UFS_DEVICE_NO_VCCQ
),
UFS_FIX
(
UFS_VENDOR_SAMSUNG
,
UFS_ANY_MODEL
,
UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS
),
UFS_FIX
(
UFS_VENDOR_SAMSUNG
,
UFS_ANY_MODEL
,
UFS_DEVICE_NO_FASTAUTO
),
UFS_FIX
(
UFS_VENDOR_SAMSUNG
,
UFS_ANY_MODEL
,
UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE
),
UFS_FIX
(
UFS_VENDOR_TOSHIBA
,
UFS_ANY_MODEL
,
UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM
),
UFS_FIX
(
UFS_VENDOR_TOSHIBA
,
"THGLF2G9C8KBADG"
,
UFS_DEVICE_QUIRK_PA_TACTIVATE
),
UFS_FIX
(
UFS_VENDOR_TOSHIBA
,
"THGLF2G9D8KBADG"
,
UFS_DEVICE_QUIRK_PA_TACTIVATE
),
UFS_FIX
(
UFS_VENDOR_SKHYNIX
,
UFS_ANY_MODEL
,
UFS_DEVICE_NO_VCCQ
),
UFS_FIX
(
UFS_VENDOR_SKHYNIX
,
UFS_ANY_MODEL
,
UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME
),
END_FIX
};
static
void
ufshcd_tmc_handler
(
struct
ufs_hba
*
hba
);
static
void
ufshcd_async_scan
(
void
*
data
,
async_cookie_t
cookie
);
static
int
ufshcd_reset_and_restore
(
struct
ufs_hba
*
hba
);
...
...
@@ -288,10 +312,24 @@ int ufshcd_wait_for_register(struct ufs_hba *hba, u32 reg, u32 mask,
*/
static
inline
u32
ufshcd_get_intr_mask
(
struct
ufs_hba
*
hba
)
{
if
(
hba
->
ufs_version
==
UFSHCI_VERSION_10
)
return
INTERRUPT_MASK_ALL_VER_10
;
else
return
INTERRUPT_MASK_ALL_VER_11
;
u32
intr_mask
=
0
;
switch
(
hba
->
ufs_version
)
{
case
UFSHCI_VERSION_10
:
intr_mask
=
INTERRUPT_MASK_ALL_VER_10
;
break
;
/* allow fall through */
case
UFSHCI_VERSION_11
:
case
UFSHCI_VERSION_20
:
intr_mask
=
INTERRUPT_MASK_ALL_VER_11
;
break
;
/* allow fall through */
case
UFSHCI_VERSION_21
:
default:
intr_mask
=
INTERRUPT_MASK_ALL_VER_21
;
}
return
intr_mask
;
}
/**
...
...
@@ -5199,6 +5237,8 @@ static void ufshcd_tune_unipro_params(struct ufs_hba *hba)
if
(
hba
->
dev_quirks
&
UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE
)
ufshcd_quirk_tune_host_pa_tactivate
(
hba
);
ufshcd_vops_apply_dev_quirks
(
hba
);
}
/**
...
...
@@ -6667,6 +6707,13 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
/* Get UFS version supported by the controller */
hba
->
ufs_version
=
ufshcd_get_ufs_version
(
hba
);
if
((
hba
->
ufs_version
!=
UFSHCI_VERSION_10
)
&&
(
hba
->
ufs_version
!=
UFSHCI_VERSION_11
)
&&
(
hba
->
ufs_version
!=
UFSHCI_VERSION_20
)
&&
(
hba
->
ufs_version
!=
UFSHCI_VERSION_21
))
dev_err
(
hba
->
dev
,
"invalid UFS version 0x%x
\n
"
,
hba
->
ufs_version
);
/* Get Interrupt bit mask per version */
hba
->
intr_mask
=
ufshcd_get_intr_mask
(
hba
);
...
...
drivers/scsi/ufs/ufshcd.h
View file @
3eff4c78
...
...
@@ -266,7 +266,7 @@ struct ufs_pwr_mode_info {
* @setup_task_mgmt: called before any task management request is issued
* to set some things
* @hibern8_notify: called around hibern8 enter/exit
*
to configure some thing
s
*
@apply_dev_quirks: called to apply device specific quirk
s
* @suspend: called during host controller PM callback
* @resume: called during host controller PM callback
* @dbg_register_dump: used to dump controller debug information
...
...
@@ -293,7 +293,8 @@ struct ufs_hba_variant_ops {
void
(
*
setup_xfer_req
)(
struct
ufs_hba
*
,
int
,
bool
);
void
(
*
setup_task_mgmt
)(
struct
ufs_hba
*
,
int
,
u8
);
void
(
*
hibern8_notify
)(
struct
ufs_hba
*
,
enum
uic_cmd_dme
,
enum
ufs_notify_change_status
);
enum
ufs_notify_change_status
);
int
(
*
apply_dev_quirks
)(
struct
ufs_hba
*
);
int
(
*
suspend
)(
struct
ufs_hba
*
,
enum
ufs_pm_op
);
int
(
*
resume
)(
struct
ufs_hba
*
,
enum
ufs_pm_op
);
void
(
*
dbg_register_dump
)(
struct
ufs_hba
*
hba
);
...
...
@@ -839,6 +840,13 @@ static inline void ufshcd_vops_hibern8_notify(struct ufs_hba *hba,
return
hba
->
vops
->
hibern8_notify
(
hba
,
cmd
,
status
);
}
static
inline
int
ufshcd_vops_apply_dev_quirks
(
struct
ufs_hba
*
hba
)
{
if
(
hba
->
vops
&&
hba
->
vops
->
apply_dev_quirks
)
return
hba
->
vops
->
apply_dev_quirks
(
hba
);
return
0
;
}
static
inline
int
ufshcd_vops_suspend
(
struct
ufs_hba
*
hba
,
enum
ufs_pm_op
op
)
{
if
(
hba
->
vops
&&
hba
->
vops
->
suspend
)
...
...
drivers/scsi/ufs/ufshci.h
View file @
3eff4c78
...
...
@@ -72,6 +72,10 @@ enum {
REG_UIC_COMMAND_ARG_1
=
0x94
,
REG_UIC_COMMAND_ARG_2
=
0x98
,
REG_UIC_COMMAND_ARG_3
=
0x9C
,
REG_UFS_CCAP
=
0x100
,
REG_UFS_CRYPTOCAP
=
0x104
,
UFSHCI_CRYPTO_REG_SPACE_SIZE
=
0x400
,
};
/* Controller capability masks */
...
...
@@ -275,6 +279,9 @@ enum {
/* Interrupt disable mask for UFSHCI v1.1 */
INTERRUPT_MASK_ALL_VER_11
=
0x31FFF
,
/* Interrupt disable mask for UFSHCI v2.1 */
INTERRUPT_MASK_ALL_VER_21
=
0x71FFF
,
};
/*
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment