Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi

Pull first round of SCSI updates from James Bottomley:
 "This is the usual grab bag of driver updates (hpsa, storvsc, mp2sas,
  megaraid_sas, ses) plus an assortment of minor updates.

  There's also an update to ufs which adds new phy drivers and finally a
  new logging infrastructure for SCSI"

* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (114 commits)
  scsi_logging: return void for dev_printk() functions
  scsi: print single-character strings with seq_putc
  scsi: merge consecutive seq_puts calls
  scsi: replace seq_printf with seq_puts
  aha152x: replace seq_printf with seq_puts
  advansys: replace seq_printf with seq_puts
  scsi: remove SPRINTF macro
  sg: remove an unused variable
  hpsa: Use local workqueues instead of system workqueues
  hpsa: add in P840ar controller model name
  hpsa: add in gen9 controller model names
  hpsa: detect and report failures changing controller transport modes
  hpsa: shorten the wait for the CISS doorbell mode change ack
  hpsa: refactor duplicated scan completion code into a new routine
  hpsa: move SG descriptor set-up out of hpsa_scatter_gather()
  hpsa: do not use function pointers in fast path command submission
  hpsa: print CDBs instead of kernel virtual addresses for uncommon errors
  hpsa: do not use a void pointer for scsi_cmd field of struct CommandList
  hpsa: return failed from device reset/abort handlers
  hpsa: check for ctlr lockup after command allocation in main io path
  ...
This commit is contained in:
Linus Torvalds
2015-02-11 10:28:45 -08:00
92 changed files with 6296 additions and 2236 deletions

View File

@@ -80,6 +80,8 @@ static const char *scsi_debug_version_date = "20141022";
#define INVALID_FIELD_IN_PARAM_LIST 0x26
#define UA_RESET_ASC 0x29
#define UA_CHANGED_ASC 0x2a
#define TARGET_CHANGED_ASC 0x3f
#define LUNS_CHANGED_ASCQ 0x0e
#define INSUFF_RES_ASC 0x55
#define INSUFF_RES_ASCQ 0x3
#define POWER_ON_RESET_ASCQ 0x0
@@ -91,6 +93,8 @@ static const char *scsi_debug_version_date = "20141022";
#define THRESHOLD_EXCEEDED 0x5d
#define LOW_POWER_COND_ON 0x5e
#define MISCOMPARE_VERIFY_ASC 0x1d
#define MICROCODE_CHANGED_ASCQ 0x1 /* with TARGET_CHANGED_ASC */
#define MICROCODE_CHANGED_WO_RESET_ASCQ 0x16
/* Additional Sense Code Qualifier (ASCQ) */
#define ACK_NAK_TO 0x3
@@ -180,7 +184,10 @@ static const char *scsi_debug_version_date = "20141022";
#define SDEBUG_UA_BUS_RESET 1
#define SDEBUG_UA_MODE_CHANGED 2
#define SDEBUG_UA_CAPACITY_CHANGED 3
#define SDEBUG_NUM_UAS 4
#define SDEBUG_UA_LUNS_CHANGED 4
#define SDEBUG_UA_MICROCODE_CHANGED 5 /* simulate firmware change */
#define SDEBUG_UA_MICROCODE_CHANGED_WO_RESET 6
#define SDEBUG_NUM_UAS 7
/* for check_readiness() */
#define UAS_ONLY 1 /* check for UAs only */
@@ -326,6 +333,7 @@ static int resp_write_same_10(struct scsi_cmnd *, struct sdebug_dev_info *);
static int resp_write_same_16(struct scsi_cmnd *, struct sdebug_dev_info *);
static int resp_xdwriteread_10(struct scsi_cmnd *, struct sdebug_dev_info *);
static int resp_comp_write(struct scsi_cmnd *, struct sdebug_dev_info *);
static int resp_write_buffer(struct scsi_cmnd *, struct sdebug_dev_info *);
struct opcode_info_t {
u8 num_attached; /* 0 if this is it (i.e. a leaf); use 0xff
@@ -480,8 +488,9 @@ static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEMENT + 1] = {
{0, 0x53, 0, F_D_IN | F_D_OUT | FF_DIRECT_IO, resp_xdwriteread_10,
NULL, {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7,
0, 0, 0, 0, 0, 0} },
{0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* WRITE_BUFFER */
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
{0, 0x3b, 0, F_D_OUT_MAYBE, resp_write_buffer, NULL,
{10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0,
0, 0, 0, 0} }, /* WRITE_BUFFER */
{1, 0x41, 0, F_D_OUT_MAYBE | FF_DIRECT_IO, resp_write_same_10,
write_same_iarr, {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff,
0xff, 0xc7, 0, 0, 0, 0, 0, 0} },
@@ -782,6 +791,22 @@ static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
/* return -ENOTTY; // correct return but upsets fdisk */
}
static void clear_luns_changed_on_target(struct sdebug_dev_info *devip)
{
struct sdebug_host_info *sdhp;
struct sdebug_dev_info *dp;
spin_lock(&sdebug_host_list_lock);
list_for_each_entry(sdhp, &sdebug_host_list, host_list) {
list_for_each_entry(dp, &sdhp->dev_info_list, dev_list) {
if ((devip->sdbg_host == dp->sdbg_host) &&
(devip->target == dp->target))
clear_bit(SDEBUG_UA_LUNS_CHANGED, dp->uas_bm);
}
}
spin_unlock(&sdebug_host_list_lock);
}
static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only,
struct sdebug_dev_info * devip)
{
@@ -817,6 +842,36 @@ static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only,
if (debug)
cp = "capacity data changed";
break;
case SDEBUG_UA_MICROCODE_CHANGED:
mk_sense_buffer(SCpnt, UNIT_ATTENTION,
TARGET_CHANGED_ASC, MICROCODE_CHANGED_ASCQ);
if (debug)
cp = "microcode has been changed";
break;
case SDEBUG_UA_MICROCODE_CHANGED_WO_RESET:
mk_sense_buffer(SCpnt, UNIT_ATTENTION,
TARGET_CHANGED_ASC,
MICROCODE_CHANGED_WO_RESET_ASCQ);
if (debug)
cp = "microcode has been changed without reset";
break;
case SDEBUG_UA_LUNS_CHANGED:
/*
* SPC-3 behavior is to report a UNIT ATTENTION with
* ASC/ASCQ REPORTED LUNS DATA HAS CHANGED on every LUN
* on the target, until a REPORT LUNS command is
* received. SPC-4 behavior is to report it only once.
* NOTE: scsi_debug_scsi_level does not use the same
* values as struct scsi_device->scsi_level.
*/
if (scsi_debug_scsi_level >= 6) /* SPC-4 and above */
clear_luns_changed_on_target(devip);
mk_sense_buffer(SCpnt, UNIT_ATTENTION,
TARGET_CHANGED_ASC,
LUNS_CHANGED_ASCQ);
if (debug)
cp = "reported luns data has changed";
break;
default:
pr_warn("%s: unexpected unit attention code=%d\n",
__func__, k);
@@ -3033,6 +3088,55 @@ resp_write_same_16(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
return resp_write_same(scp, lba, num, ei_lba, unmap, ndob);
}
/* Note the mode field is in the same position as the (lower) service action
* field. For the Report supported operation codes command, SPC-4 suggests
* each mode of this command should be reported separately; for future. */
static int
resp_write_buffer(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
{
u8 *cmd = scp->cmnd;
struct scsi_device *sdp = scp->device;
struct sdebug_dev_info *dp;
u8 mode;
mode = cmd[1] & 0x1f;
switch (mode) {
case 0x4: /* download microcode (MC) and activate (ACT) */
/* set UAs on this device only */
set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
set_bit(SDEBUG_UA_MICROCODE_CHANGED, devip->uas_bm);
break;
case 0x5: /* download MC, save and ACT */
set_bit(SDEBUG_UA_MICROCODE_CHANGED_WO_RESET, devip->uas_bm);
break;
case 0x6: /* download MC with offsets and ACT */
/* set UAs on most devices (LUs) in this target */
list_for_each_entry(dp,
&devip->sdbg_host->dev_info_list,
dev_list)
if (dp->target == sdp->id) {
set_bit(SDEBUG_UA_BUS_RESET, dp->uas_bm);
if (devip != dp)
set_bit(SDEBUG_UA_MICROCODE_CHANGED,
dp->uas_bm);
}
break;
case 0x7: /* download MC with offsets, save, and ACT */
/* set UA on all devices (LUs) in this target */
list_for_each_entry(dp,
&devip->sdbg_host->dev_info_list,
dev_list)
if (dp->target == sdp->id)
set_bit(SDEBUG_UA_MICROCODE_CHANGED_WO_RESET,
dp->uas_bm);
break;
default:
/* do nothing for this command for other mode values */
break;
}
return 0;
}
static int
resp_comp_write(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
{
@@ -3229,6 +3333,7 @@ static int resp_report_luns(struct scsi_cmnd * scp,
unsigned char arr[SDEBUG_RLUN_ARR_SZ];
unsigned char * max_addr;
clear_luns_changed_on_target(devip);
alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
shortish = (alloc_len < 4);
if (shortish || (select_report > 2)) {
@@ -4369,10 +4474,27 @@ static ssize_t max_luns_store(struct device_driver *ddp, const char *buf,
size_t count)
{
int n;
bool changed;
if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
changed = (scsi_debug_max_luns != n);
scsi_debug_max_luns = n;
sdebug_max_tgts_luns();
if (changed && (scsi_debug_scsi_level >= 5)) { /* >= SPC-3 */
struct sdebug_host_info *sdhp;
struct sdebug_dev_info *dp;
spin_lock(&sdebug_host_list_lock);
list_for_each_entry(sdhp, &sdebug_host_list,
host_list) {
list_for_each_entry(dp, &sdhp->dev_info_list,
dev_list) {
set_bit(SDEBUG_UA_LUNS_CHANGED,
dp->uas_bm);
}
}
spin_unlock(&sdebug_host_list_lock);
}
return count;
}
return -EINVAL;