89 lines · c
1/* SPDX-License-Identifier: GPL-2.0-only */2/* 3 * Transport specific attributes.4 *5 * Copyright (c) 2003 Silicon Graphics, Inc. All rights reserved.6 */7#ifndef SCSI_TRANSPORT_H8#define SCSI_TRANSPORT_H9 10#include <linux/transport_class.h>11#include <linux/blkdev.h>12#include <linux/bug.h>13#include <scsi/scsi_host.h>14#include <scsi/scsi_device.h>15 16struct scsi_transport_template {17 /* the attribute containers */18 struct transport_container host_attrs;19 struct transport_container target_attrs;20 struct transport_container device_attrs;21 22 /*23 * If set, called from sysfs and legacy procfs rescanning code.24 */25 int (*user_scan)(struct Scsi_Host *, uint, uint, u64);26 27 /* The size of the specific transport attribute structure (a28 * space of this size will be left at the end of the29 * scsi_* structure */30 int device_size;31 int device_private_offset;32 int target_size;33 int target_private_offset;34 int host_size;35 /* no private offset for the host; there's an alternative mechanism */36 37 /*38 * True if the transport wants to use a host-based work-queue39 */40 unsigned int create_work_queue : 1;41 42 /*43 * Allows a transport to override the default error handler.44 */45 void (* eh_strategy_handler)(struct Scsi_Host *);46};47 48#define transport_class_to_shost(tc) \49 dev_to_shost((tc)->parent)50 51 52/* Private area maintenance. The driver requested allocations come53 * directly after the transport class allocations (if any). The idea54 * is that you *must* call these only once. The code assumes that the55 * initial values are the ones the transport specific code requires */56static inline void57scsi_transport_reserve_target(struct scsi_transport_template * t, int space)58{59 BUG_ON(t->target_private_offset != 0);60 t->target_private_offset = ALIGN(t->target_size, sizeof(void *));61 t->target_size = t->target_private_offset + space;62}63static inline void64scsi_transport_reserve_device(struct scsi_transport_template * t, int space)65{66 BUG_ON(t->device_private_offset != 0);67 t->device_private_offset = ALIGN(t->device_size, sizeof(void *));68 t->device_size = t->device_private_offset + space;69}70static inline void *71scsi_transport_target_data(struct scsi_target *starget)72{73 struct Scsi_Host *shost = dev_to_shost(&starget->dev);74 return (u8 *)starget->starget_data75 + shost->transportt->target_private_offset;76 77}78static inline void *79scsi_transport_device_data(struct scsi_device *sdev)80{81 struct Scsi_Host *shost = sdev->host;82 return (u8 *)sdev->sdev_data83 + shost->transportt->device_private_offset;84}85 86void scsi_init_limits(struct Scsi_Host *shost, struct queue_limits *lim);87 88#endif /* SCSI_TRANSPORT_H */89