mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-01 10:45:49 +00:00
firewire: fw-sbp2: expose module parameter for workarounds
On rare occasions, the ability to set one of the workaround flags at runtime may save the day. People who experience I/O errors with firewire-sbp2 while the old sbp2 driver worked for them should try workarounds=1 and report to the devel mailinglist whether that improves things. Firewire-sbp2 defaults to the SCSI stack's maximum transfer size per command, while sbp2 limits them to 128 kBytes. Flag 1 accomplishes just that. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
This commit is contained in:
parent
5a3c2be6c9
commit
2df222b8f8
@ -37,6 +37,7 @@
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/stringify.h>
|
||||
#include <linux/timer.h>
|
||||
|
||||
#include <scsi/scsi.h>
|
||||
@ -60,6 +61,46 @@ module_param_named(exclusive_login, sbp2_param_exclusive_login, bool, 0644);
|
||||
MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device "
|
||||
"(default = Y, use N for concurrent initiators)");
|
||||
|
||||
/*
|
||||
* Flags for firmware oddities
|
||||
*
|
||||
* - 128kB max transfer
|
||||
* Limit transfer size. Necessary for some old bridges.
|
||||
*
|
||||
* - 36 byte inquiry
|
||||
* When scsi_mod probes the device, let the inquiry command look like that
|
||||
* from MS Windows.
|
||||
*
|
||||
* - skip mode page 8
|
||||
* Suppress sending of mode_sense for mode page 8 if the device pretends to
|
||||
* support the SCSI Primary Block commands instead of Reduced Block Commands.
|
||||
*
|
||||
* - fix capacity
|
||||
* Tell sd_mod to correct the last sector number reported by read_capacity.
|
||||
* Avoids access beyond actual disk limits on devices with an off-by-one bug.
|
||||
* Don't use this with devices which don't have this bug.
|
||||
*
|
||||
* - override internal blacklist
|
||||
* Instead of adding to the built-in blacklist, use only the workarounds
|
||||
* specified in the module load parameter.
|
||||
* Useful if a blacklist entry interfered with a non-broken device.
|
||||
*/
|
||||
#define SBP2_WORKAROUND_128K_MAX_TRANS 0x1
|
||||
#define SBP2_WORKAROUND_INQUIRY_36 0x2
|
||||
#define SBP2_WORKAROUND_MODE_SENSE_8 0x4
|
||||
#define SBP2_WORKAROUND_FIX_CAPACITY 0x8
|
||||
#define SBP2_WORKAROUND_OVERRIDE 0x100
|
||||
|
||||
static int sbp2_param_workarounds;
|
||||
module_param_named(workarounds, sbp2_param_workarounds, int, 0644);
|
||||
MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0"
|
||||
", 128kB max transfer = " __stringify(SBP2_WORKAROUND_128K_MAX_TRANS)
|
||||
", 36 byte inquiry = " __stringify(SBP2_WORKAROUND_INQUIRY_36)
|
||||
", skip mode page 8 = " __stringify(SBP2_WORKAROUND_MODE_SENSE_8)
|
||||
", fix capacity = " __stringify(SBP2_WORKAROUND_FIX_CAPACITY)
|
||||
", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE)
|
||||
", or a combination)");
|
||||
|
||||
/* I don't know why the SCSI stack doesn't define something like this... */
|
||||
typedef void (*scsi_done_fn_t)(struct scsi_cmnd *);
|
||||
|
||||
@ -122,13 +163,6 @@ struct sbp2_target {
|
||||
#define SBP2_CSR_LOGICAL_UNIT_NUMBER 0x14
|
||||
#define SBP2_CSR_LOGICAL_UNIT_DIRECTORY 0xd4
|
||||
|
||||
/* Flags for detected oddities and brokeness */
|
||||
#define SBP2_WORKAROUND_128K_MAX_TRANS 0x1
|
||||
#define SBP2_WORKAROUND_INQUIRY_36 0x2
|
||||
#define SBP2_WORKAROUND_MODE_SENSE_8 0x4
|
||||
#define SBP2_WORKAROUND_FIX_CAPACITY 0x8
|
||||
#define SBP2_WORKAROUND_OVERRIDE 0x100
|
||||
|
||||
/* Management orb opcodes */
|
||||
#define SBP2_LOGIN_REQUEST 0x0
|
||||
#define SBP2_QUERY_LOGINS_REQUEST 0x1
|
||||
@ -751,8 +785,15 @@ static void sbp2_init_workarounds(struct sbp2_target *tgt, u32 model,
|
||||
u32 firmware_revision)
|
||||
{
|
||||
int i;
|
||||
unsigned w = sbp2_param_workarounds;
|
||||
|
||||
tgt->workarounds = 0;
|
||||
if (w)
|
||||
fw_notify("Please notify linux1394-devel@lists.sourceforge.net "
|
||||
"if you need the workarounds parameter for %s\n",
|
||||
tgt->unit->device.bus_id);
|
||||
|
||||
if (w & SBP2_WORKAROUND_OVERRIDE)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sbp2_workarounds_table); i++) {
|
||||
|
||||
@ -764,15 +805,16 @@ static void sbp2_init_workarounds(struct sbp2_target *tgt, u32 model,
|
||||
sbp2_workarounds_table[i].model != ~0)
|
||||
continue;
|
||||
|
||||
tgt->workarounds |= sbp2_workarounds_table[i].workarounds;
|
||||
w |= sbp2_workarounds_table[i].workarounds;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tgt->workarounds)
|
||||
out:
|
||||
if (w)
|
||||
fw_notify("Workarounds for %s: 0x%x "
|
||||
"(firmware_revision 0x%06x, model_id 0x%06x)\n",
|
||||
tgt->unit->device.bus_id,
|
||||
tgt->workarounds, firmware_revision, model);
|
||||
w, firmware_revision, model);
|
||||
tgt->workarounds = w;
|
||||
}
|
||||
|
||||
static struct scsi_host_template scsi_driver_template;
|
||||
|
Loading…
Reference in New Issue
Block a user