> +#define STORVSC_MIN_BUF_NR                           64

What about a comment explaining what this is for?

> +#define STORVSC_RING_BUFFER_SIZE                     (20*PAGE_SIZE)
> +static int storvsc_ringbuffer_size = STORVSC_RING_BUFFER_SIZE;

I don't think you need the #define here.

> +/* to alert the user that structure sizes may be mismatched even though the 
> */
> +/* protocol versions match. */
> +
> +
> +#define REVISION_STRING(REVISION_) #REVISION_
> +#define FILL_VMSTOR_REVISION(RESULT_LVALUE_)                         \
> +     do {                                                            \
> +             char *revision_string                                   \
> +                     = REVISION_STRING($Rev : 6 $) + 6;              \
> +             RESULT_LVALUE_ = 0;                                     \
> +             while (*revision_string >= '0'                          \
> +                     && *revision_string <= '9') {                   \
> +                     RESULT_LVALUE_ *= 10;                           \
> +                     RESULT_LVALUE_ += *revision_string - '0';       \
> +                     revision_string++;                              \
> +             }                                                       \
> +     } while (0)
> +

How can these macros work?  I don't think git ever expans $Rev, and in
either case I really don't get how this is supposed to work.

> +/* Major/minor macros.  Minor version is in LSB, meaning that earlier flat */
> +/* version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1). */

Please use comment formats like this:

/*
 * Blah ....
 * .....
 */

(this also applies to a few other places).

> +#define VMSTOR_PROTOCOL_MAJOR(VERSION_)              (((VERSION_) >> 8) & 
> 0xff)
> +#define VMSTOR_PROTOCOL_MINOR(VERSION_)              (((VERSION_))      & 
> 0xff)
> +#define VMSTOR_PROTOCOL_VERSION(MAJOR_, MINOR_)      ((((MAJOR_) & 0xff) << 
> 8) | \
> +                                              (((MINOR_) & 0xff)))

All these should be inline functions.

> +#define VMSTOR_INVALID_PROTOCOL_VERSION              (-1)

Not used.

> + * Platform neutral description of a scsi request -
> + * this remains the same across the write regardless of 32/64 bit
> + * note: it's patterned off the SCSI_PASS_THROUGH structure
> + */
> +#define CDB16GENERIC_LENGTH                  0x10
> +
> +#ifndef SENSE_BUFFER_SIZE
> +#define SENSE_BUFFER_SIZE                    0x12
> +#endif
> +
> +#define MAX_DATA_BUF_LEN_WITH_PADDING                0x14

Please don't conditionally re-use the SCSI-layer SENSE_BUFFER_SIZE for
your on the wire packets, but define your own.  Please also give all
theses constants a VMSCSI_ or similar prefix.

> +struct vmscsi_request {
> +     unsigned short length;
> +     unsigned char srb_status;
> +     unsigned char scsi_status;
> +
> +     unsigned char port_number;
> +     unsigned char path_id;
> +     unsigned char target_id;
> +     unsigned char lun;
> +
> +     unsigned char cdb_length;
> +     unsigned char sense_info_length;
> +     unsigned char data_in;
> +     unsigned char reserved;
> +
> +     unsigned int data_transfer_length;
> +
> +     union {
> +             unsigned char cdb[CDB16GENERIC_LENGTH];
> +             unsigned char sense_data[SENSE_BUFFER_SIZE];
> +             unsigned char reserved_array[MAX_DATA_BUF_LEN_WITH_PADDING];
> +     };
> +} __attribute((packed));

Please use fixed size u8/16/32/etc types for all the on-wire defintions.

I'd also really recommend splitting the actual protocol defintion in
a header separate from the driver implementation to make it clear what
is part of the protocol and what's internal to the driver.

> +/*  This is the set of flags that the vsc can set in any packets it sends */
> +#define VSC_LEGAL_FLAGS              (REQUEST_COMPLETION_FLAG)

unused.

> +#define STORVSC_MAX_CMD_LEN                          16

This seems to duplicate the CDB16GENERIC_LENGTH define used above,
please make sure you only have one #define for this constant.

> +
> +/* Matches Windows-end */
> +enum storvsc_request_type {
> +     WRITE_TYPE,
> +     READ_TYPE,
> +     UNKNOWN_TYPE,
> +};

For enums specifying the protocol please always use explicit values.


> +struct hv_storvsc_request {
> +     struct hv_device *device;
> +
> +     /* Synchronize the request/response if needed */
> +     struct completion wait_event;
> +
> +     unsigned char *sense_buffer;
> +     void *context;

This always is a struct storvsc_cmd_request, and should be typed as
such.

> +     void (*on_io_completion)(struct hv_storvsc_request *request);

This always points to storvsc_command_completion, so please remove the
indirect call and use it directly.

> +     struct hv_multipage_buffer data_buffer;
> +
> +     struct vstor_packet vstor_packet;
> +};


Btw, what is the reason that storvsc_cmd_request and hv_storvsc_request
are separate structures and not merged into one?  This wastes a tiny
amount of memory for the init/reset requests, but keeps the code
a lot simpler.


> +static inline struct storvsc_device *get_out_stor_device(
> +                                     struct hv_device *device)

> +static inline struct storvsc_device *get_in_stor_device(
> +                                     struct hv_device *device)

I'm pretty sure you defended this odd reference counting scheme last
time the discussion came up, but please write up a long comment in
the code explaning it so that the question doesn't come up again
all the time.


> +     /*
> +      * The current SCSI handling on the host side does
> +      * not correctly handle:
> +      * INQUIRY command with page code parameter set to 0x80
> +      * MODE_SENSE command with cmd[2] == 0x1c
> +      *
> +      * Setup srb and scsi status so this won't be fatal.
> +      * We do this so we can distinguish truly fatal failues
> +      * (srb status == 0x4) and off-line the device in that case.
> +      */
> +
> +     if ((stor_pkt->vm_srb.cdb[0] == INQUIRY) ||
> +             (stor_pkt->vm_srb.cdb[0] == MODE_SENSE)) {

This should be:

        if (stor_pkt->vm_srb.cdb[0] == INQUIRY ||
            stor_pkt->vm_srb.cdb[0] == MODE_SENSE) {

or even better use a switch statement to clarify what's going on.


> +static int storvsc_remove(struct hv_device *dev)
> +{
> +     struct storvsc_device *stor_device = hv_get_drvdata(dev);
> +     struct Scsi_Host *host = stor_device->host;
> +
> +     scsi_remove_host(host);
> +
> +     scsi_host_put(host);
> +
> +     storvsc_dev_remove(dev);
> +
> +     return 0;
> +}

Why isn't this near storvcs_probe at the end of the file given that
they logically belong together?  Also please only do the scsi_host_put
once you are fully done with it, that is after storvsc_dev_remove.

> +/*
> + * storvsc_host_reset_handler - Reset the scsi HBA
> + */
> +static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
> +{
> +     struct hv_host_device *host_dev = shost_priv(scmnd->device->host);
> +     struct hv_device *dev = host_dev->dev;
> +
> +     return storvsc_host_reset(dev);
> +}

Why is storvsc_host_reset split from this function?  Also the comment
really doesn't tell us anything, I'd rather leave it away.


> +/*
> + * storvsc_command_completion - Command completion processing
> + */
> +static void storvsc_command_completion(struct hv_storvsc_request *request)

I really don't see how this comment adds any value over the pure
function name.


> +     if (vm_srb->srb_status == 0x4)

> +     if (vm_srb->srb_status == 0x20) {

Please add defines for the vm_srb->srb_status values.

> +static bool storvsc_check_scsi_cmd(struct scsi_cmnd *scmnd)

Please call this storvsc_ignore_command or similar to make the use more
obvious.

> +     /* If retrying, no need to prep the cmd */
> +     if (scmnd->host_scribble) {
> +
> +             cmd_request =
> +                     (struct storvsc_cmd_request *)scmnd->host_scribble;
> +
> +             goto retry_request;
> +     }

I don't think this can ever happen given that you make sure to always
clear ->host_scribble when returning SCSI_MLQUEUE_*_BUSY.

> +     request_size = sizeof(struct storvsc_cmd_request);
> +
> +     cmd_request = mempool_alloc(memp->request_mempool,
> +                                    GFP_ATOMIC);
> +     if (!cmd_request)
> +             return SCSI_MLQUEUE_DEVICE_BUSY;

The point of the mempool allocator is that it will never return NULL.

> +
> +     memset(cmd_request, 0, sizeof(struct storvsc_cmd_request));
> +
> +     /* Setup the cmd request */
> +     cmd_request->bounce_sgl_count = 0;
> +     cmd_request->bounce_sgl = NULL;
> +     cmd_request->cmd = scmnd;

Either use memset for the whole structure, or set the fields that need
it to 0 explicitly, but not both.  I doubt it's more efficient to only
initialise the fields that need it.

> +                     if (!cmd_request->bounce_sgl) {
> +                             scmnd->host_scribble = NULL;
> +                             mempool_free(cmd_request,
> +                                             memp->request_mempool);
> +
> +                             return SCSI_MLQUEUE_HOST_BUSY;
> +                     }



> +             if (cmd_request->bounce_sgl_count)
> +                     destroy_bounce_buffer(cmd_request->bounce_sgl,
> +                                     cmd_request->bounce_sgl_count);
> +
> +             mempool_free(cmd_request, memp->request_mempool);
> +
> +             scmnd->host_scribble = NULL;
> +
> +             ret = SCSI_MLQUEUE_DEVICE_BUSY;

Please use goto labels and a single error exit for unwindining on
failure.

> +/* Scsi driver */

Not a useful comment, just remove it.

> +/*
> + * storvsc_probe - Add a new device for this driver
> + */

Not a very useful comment, just remove it.

> +     if (dev_is_ide)
> +             storvsc_get_ide_info(device, &target, &path);

path is never used, so drop that argument from storvsc_get_ide_info
please.  Target is only used in the next dev_is_ide block, so please
move this call to it.

> +     /* max # of devices per target */
> +     host->max_lun = STORVSC_MAX_LUNS_PER_TARGET;
> +     /* max # of targets per channel */
> +     host->max_id = STORVSC_MAX_TARGETS;
> +     /* max # of channels */
> +     host->max_channel = STORVSC_MAX_CHANNELS - 1;
> +     /* max cmd length */
> +     host->max_cmd_len = STORVSC_MAX_CMD_LEN;

Any reason these aren't set directly in the host template?

> +     if (!dev_is_ide) {
> +             scsi_scan_host(host);
> +             return 0;
> +     }
> +     ret = scsi_add_device(host, 0, target, 0);
> +     if (ret) {
> +             scsi_remove_host(host);
> +             goto err_out2;
> +     }
> +     return 0;

I'd write this as an if/else block to be be more clear.


> +/* The one and only one */

this isn't an overly useful comment.
_______________________________________________
devel mailing list
[email protected]
http://driverdev.linuxdriverproject.org/mailman/listinfo/devel

Reply via email to