| 1 |
|
| 2 | |
| 3 | * SAS host prototypes and structures header file
|
| 4 | *
|
| 5 | * Copyright (C) 2005 Adaptec, Inc. All rights reserved.
|
| 6 | * Copyright (C) 2005 Luben Tuikov <[email protected]>
|
| 7 |
|
| 8 |
|
| 9 | #ifndef _LIBSAS_H_
|
| 10 | #define _LIBSAS_H_
|
| 11 |
|
| 12 |
|
| 13 | #include <linux/timer.h>
|
| 14 | #include <linux/pci.h>
|
| 15 | #include <scsi/sas.h>
|
| 16 | #include <linux/libata.h>
|
| 17 | #include <linux/list.h>
|
| 18 | #include <scsi/scsi_device.h>
|
| 19 | #include <scsi/scsi_cmnd.h>
|
| 20 | #include <scsi/scsi_transport_sas.h>
|
| 21 | #include <linux/scatterlist.h>
|
| 22 | #include <linux/slab.h>
|
| 23 |
|
| 24 | struct block_device;
|
| 25 |
|
| 26 | enum sas_phy_role {
|
| 27 | PHY_ROLE_NONE = 0,
|
| 28 | PHY_ROLE_TARGET = 0x40,
|
| 29 | PHY_ROLE_INITIATOR = 0x80,
|
| 30 | };
|
| 31 |
|
| 32 | |
| 33 | * so when updating/adding events here, please also
|
| 34 | * update the other file too.
|
| 35 |
|
| 36 | enum port_event {
|
| 37 | PORTE_BYTES_DMAED = 0U,
|
| 38 | PORTE_BROADCAST_RCVD,
|
| 39 | PORTE_LINK_RESET_ERR,
|
| 40 | PORTE_TIMER_EVENT,
|
| 41 | PORTE_HARD_RESET,
|
| 42 | PORT_NUM_EVENTS,
|
| 43 | };
|
| 44 |
|
| 45 | enum phy_event {
|
| 46 | PHYE_LOSS_OF_SIGNAL = 0U,
|
| 47 | PHYE_OOB_DONE,
|
| 48 | PHYE_OOB_ERROR,
|
| 49 | PHYE_SPINUP_HOLD,
|
| 50 | PHYE_RESUME_TIMEOUT,
|
| 51 | PHYE_SHUTDOWN,
|
| 52 | PHY_NUM_EVENTS,
|
| 53 | };
|
| 54 |
|
| 55 | enum discover_event {
|
| 56 | DISCE_DISCOVER_DOMAIN = 0U,
|
| 57 | DISCE_REVALIDATE_DOMAIN,
|
| 58 | DISCE_SUSPEND,
|
| 59 | DISCE_RESUME,
|
| 60 | DISC_NUM_EVENTS,
|
| 61 | };
|
| 62 |
|
| 63 |
|
| 64 |
|
| 65 | enum routing_attribute {
|
| 66 | DIRECT_ROUTING,
|
| 67 | SUBTRACTIVE_ROUTING,
|
| 68 | TABLE_ROUTING,
|
| 69 | };
|
| 70 |
|
| 71 | enum ex_phy_state {
|
| 72 | PHY_EMPTY,
|
| 73 | PHY_VACANT,
|
| 74 | PHY_NOT_PRESENT,
|
| 75 | PHY_DEVICE_DISCOVERED
|
| 76 | };
|
| 77 |
|
| 78 | struct ex_phy {
|
| 79 | int phy_id;
|
| 80 |
|
| 81 | enum ex_phy_state phy_state;
|
| 82 |
|
| 83 | enum sas_device_type attached_dev_type;
|
| 84 | enum sas_linkrate linkrate;
|
| 85 |
|
| 86 | u8 attached_sata_host:1;
|
| 87 | u8 attached_sata_dev:1;
|
| 88 | u8 attached_sata_ps:1;
|
| 89 |
|
| 90 | enum sas_protocol attached_tproto;
|
| 91 | enum sas_protocol attached_iproto;
|
| 92 |
|
| 93 | u8 attached_sas_addr[SAS_ADDR_SIZE];
|
| 94 | u8 attached_phy_id;
|
| 95 |
|
| 96 | int phy_change_count;
|
| 97 | enum routing_attribute routing_attr;
|
| 98 | u8 virtual:1;
|
| 99 |
|
| 100 | int last_da_index;
|
| 101 |
|
| 102 | struct sas_phy *phy;
|
| 103 | struct sas_port *port;
|
| 104 | };
|
| 105 |
|
| 106 | struct expander_device {
|
| 107 | struct list_head children;
|
| 108 |
|
| 109 | int ex_change_count;
|
| 110 | u16 max_route_indexes;
|
| 111 | u8 num_phys;
|
| 112 |
|
| 113 | u8 t2t_supp:1;
|
| 114 | u8 configuring:1;
|
| 115 | u8 conf_route_table:1;
|
| 116 |
|
| 117 | u8 enclosure_logical_id[8];
|
| 118 |
|
| 119 | struct ex_phy *ex_phy;
|
| 120 | struct sas_port *parent_port;
|
| 121 |
|
| 122 | struct mutex cmd_mutex;
|
| 123 | };
|
| 124 |
|
| 125 |
|
| 126 | #define ATA_RESP_FIS_SIZE 24
|
| 127 |
|
| 128 | struct sata_device {
|
| 129 | unsigned int class;
|
| 130 | u8 port_no;
|
| 131 |
|
| 132 | struct ata_port *ap;
|
| 133 | struct ata_host *ata_host;
|
| 134 | struct smp_rps_resp rps_resp ____cacheline_aligned;
|
| 135 | u8 fis[ATA_RESP_FIS_SIZE];
|
| 136 | };
|
| 137 |
|
| 138 | struct ssp_device {
|
| 139 | struct list_head eh_list_node;
|
| 140 | struct scsi_lun reset_lun;
|
| 141 | };
|
| 142 |
|
| 143 | enum {
|
| 144 | SAS_DEV_GONE,
|
| 145 | SAS_DEV_FOUND,
|
| 146 | SAS_DEV_DESTROY,
|
| 147 | SAS_DEV_EH_PENDING,
|
| 148 | SAS_DEV_LU_RESET,
|
| 149 | SAS_DEV_RESET,
|
| 150 | };
|
| 151 |
|
| 152 | struct domain_device {
|
| 153 | spinlock_t done_lock;
|
| 154 | enum sas_device_type dev_type;
|
| 155 |
|
| 156 | enum sas_linkrate linkrate;
|
| 157 | enum sas_linkrate min_linkrate;
|
| 158 | enum sas_linkrate max_linkrate;
|
| 159 |
|
| 160 | int pathways;
|
| 161 |
|
| 162 | struct domain_device *parent;
|
| 163 | struct list_head siblings;
|
| 164 | struct asd_sas_port *port;
|
| 165 | struct sas_phy *phy;
|
| 166 |
|
| 167 | struct list_head dev_list_node;
|
| 168 | struct list_head disco_list_node;
|
| 169 |
|
| 170 | enum sas_protocol iproto;
|
| 171 | enum sas_protocol tproto;
|
| 172 |
|
| 173 | struct sas_rphy *rphy;
|
| 174 |
|
| 175 | u8 sas_addr[SAS_ADDR_SIZE];
|
| 176 | u8 hashed_sas_addr[HASHED_SAS_ADDR_SIZE];
|
| 177 |
|
| 178 | u8 frame_rcvd[32];
|
| 179 |
|
| 180 | union {
|
| 181 | struct expander_device ex_dev;
|
| 182 | struct sata_device sata_dev;
|
| 183 | struct ssp_device ssp_dev;
|
| 184 | };
|
| 185 |
|
| 186 | void *lldd_dev;
|
| 187 | unsigned long state;
|
| 188 | struct kref kref;
|
| 189 | };
|
| 190 |
|
| 191 | struct sas_work {
|
| 192 | struct list_head drain_node;
|
| 193 | struct work_struct work;
|
| 194 | };
|
| 195 |
|
| 196 | static inline bool dev_is_expander(enum sas_device_type type)
|
| 197 | {
|
| 198 | return type == SAS_EDGE_EXPANDER_DEVICE ||
|
| 199 | type == SAS_FANOUT_EXPANDER_DEVICE;
|
| 200 | }
|
| 201 |
|
| 202 | static inline bool dev_parent_is_expander(struct domain_device *dev)
|
| 203 | {
|
| 204 | if (!dev->parent)
|
| 205 | return false;
|
| 206 |
|
| 207 | return dev_is_expander(dev->parent->dev_type);
|
| 208 | }
|
| 209 |
|
| 210 | static inline void INIT_SAS_WORK(struct sas_work *sw, void (*fn)(struct work_struct *))
|
| 211 | {
|
| 212 | INIT_WORK(&sw->work, fn);
|
| 213 | INIT_LIST_HEAD(&sw->drain_node);
|
| 214 | }
|
| 215 |
|
| 216 | struct sas_discovery_event {
|
| 217 | struct sas_work work;
|
| 218 | struct asd_sas_port *port;
|
| 219 | };
|
| 220 |
|
| 221 | static inline struct sas_discovery_event *to_sas_discovery_event(struct work_struct *work)
|
| 222 | {
|
| 223 | struct sas_discovery_event *ev = container_of(work, typeof(*ev), work.work);
|
| 224 |
|
| 225 | return ev;
|
| 226 | }
|
| 227 |
|
| 228 | struct sas_discovery {
|
| 229 | struct sas_discovery_event disc_work[DISC_NUM_EVENTS];
|
| 230 | unsigned long pending;
|
| 231 | u8 fanout_sas_addr[SAS_ADDR_SIZE];
|
| 232 | u8 eeds_a[SAS_ADDR_SIZE];
|
| 233 | u8 eeds_b[SAS_ADDR_SIZE];
|
| 234 | int max_level;
|
| 235 | };
|
| 236 |
|
| 237 |
|
| 238 | struct asd_sas_port {
|
| 239 |
|
| 240 | struct sas_discovery disc;
|
| 241 | struct domain_device *port_dev;
|
| 242 | spinlock_t dev_list_lock;
|
| 243 | struct list_head dev_list;
|
| 244 | struct list_head disco_list;
|
| 245 | struct list_head destroy_list;
|
| 246 | struct list_head sas_port_del_list;
|
| 247 | enum sas_linkrate linkrate;
|
| 248 |
|
| 249 | struct sas_work work;
|
| 250 | int suspended;
|
| 251 |
|
| 252 |
|
| 253 | int id;
|
| 254 |
|
| 255 | u8 sas_addr[SAS_ADDR_SIZE];
|
| 256 | u8 attached_sas_addr[SAS_ADDR_SIZE];
|
| 257 | enum sas_protocol iproto;
|
| 258 | enum sas_protocol tproto;
|
| 259 |
|
| 260 | enum sas_oob_mode oob_mode;
|
| 261 |
|
| 262 | spinlock_t phy_list_lock;
|
| 263 | struct list_head phy_list;
|
| 264 | int num_phys;
|
| 265 | u32 phy_mask;
|
| 266 |
|
| 267 | struct sas_ha_struct *ha;
|
| 268 |
|
| 269 | struct sas_port *port;
|
| 270 |
|
| 271 | void *lldd_port;
|
| 272 | };
|
| 273 |
|
| 274 | struct asd_sas_event {
|
| 275 | struct sas_work work;
|
| 276 | struct asd_sas_phy *phy;
|
| 277 | int event;
|
| 278 | };
|
| 279 |
|
| 280 | static inline struct asd_sas_event *to_asd_sas_event(struct work_struct *work)
|
| 281 | {
|
| 282 | struct asd_sas_event *ev = container_of(work, typeof(*ev), work.work);
|
| 283 |
|
| 284 | return ev;
|
| 285 | }
|
| 286 |
|
| 287 | static inline void INIT_SAS_EVENT(struct asd_sas_event *ev,
|
| 288 | void (*fn)(struct work_struct *),
|
| 289 | struct asd_sas_phy *phy, int event)
|
| 290 | {
|
| 291 | INIT_SAS_WORK(&ev->work, fn);
|
| 292 | ev->phy = phy;
|
| 293 | ev->event = event;
|
| 294 | }
|
| 295 |
|
| 296 | #define SAS_PHY_SHUTDOWN_THRES 1024
|
| 297 |
|
| 298 | |
| 299 | * The class only reads those fields.
|
| 300 |
|
| 301 | struct asd_sas_phy {
|
| 302 |
|
| 303 | atomic_t event_nr;
|
| 304 | int in_shutdown;
|
| 305 | int error;
|
| 306 | int suspended;
|
| 307 |
|
| 308 | struct sas_phy *phy;
|
| 309 |
|
| 310 |
|
| 311 |
|
| 312 | int enabled;
|
| 313 |
|
| 314 | int id;
|
| 315 | enum sas_protocol iproto;
|
| 316 | enum sas_protocol tproto;
|
| 317 |
|
| 318 | enum sas_phy_role role;
|
| 319 | enum sas_oob_mode oob_mode;
|
| 320 | enum sas_linkrate linkrate;
|
| 321 |
|
| 322 | u8 *sas_addr;
|
| 323 | u8 attached_sas_addr[SAS_ADDR_SIZE];
|
| 324 |
|
| 325 | spinlock_t frame_rcvd_lock;
|
| 326 | u8 *frame_rcvd;
|
| 327 | int frame_rcvd_size;
|
| 328 |
|
| 329 | spinlock_t sas_prim_lock;
|
| 330 | u32 sas_prim;
|
| 331 |
|
| 332 | struct list_head port_phy_el;
|
| 333 | struct asd_sas_port *port;
|
| 334 |
|
| 335 | struct sas_ha_struct *ha;
|
| 336 |
|
| 337 | void *lldd_phy;
|
| 338 | };
|
| 339 |
|
| 340 | enum sas_ha_state {
|
| 341 | SAS_HA_REGISTERED,
|
| 342 | SAS_HA_DRAINING,
|
| 343 | SAS_HA_ATA_EH_ACTIVE,
|
| 344 | SAS_HA_FROZEN,
|
| 345 | SAS_HA_RESUMING,
|
| 346 | };
|
| 347 |
|
| 348 | struct sas_ha_struct {
|
| 349 |
|
| 350 | struct list_head defer_q;
|
| 351 | struct mutex drain_mutex;
|
| 352 | unsigned long state;
|
| 353 | spinlock_t lock;
|
| 354 | int eh_active;
|
| 355 | wait_queue_head_t eh_wait_q;
|
| 356 | struct list_head eh_dev_q;
|
| 357 |
|
| 358 | struct mutex disco_mutex;
|
| 359 |
|
| 360 | struct Scsi_Host *shost;
|
| 361 |
|
| 362 |
|
| 363 | char *sas_ha_name;
|
| 364 | struct device *dev;
|
| 365 |
|
| 366 | struct workqueue_struct *event_q;
|
| 367 | struct workqueue_struct *disco_q;
|
| 368 |
|
| 369 | u8 *sas_addr;
|
| 370 | u8 hashed_sas_addr[HASHED_SAS_ADDR_SIZE];
|
| 371 |
|
| 372 | spinlock_t phy_port_lock;
|
| 373 | struct asd_sas_phy **sas_phy;
|
| 374 | struct asd_sas_port **sas_port;
|
| 375 | int num_phys;
|
| 376 |
|
| 377 | int strict_wide_ports; |
| 378 | * their siblings when forming wide ports
|
| 379 |
|
| 380 | void *lldd_ha;
|
| 381 |
|
| 382 | struct list_head eh_done_q;
|
| 383 | struct list_head eh_ata_q;
|
| 384 |
|
| 385 | int event_thres;
|
| 386 | };
|
| 387 |
|
| 388 | #define SHOST_TO_SAS_HA(_shost) (*(struct sas_ha_struct **)(_shost)->hostdata)
|
| 389 |
|
| 390 | static inline struct domain_device *
|
| 391 | starget_to_domain_dev(struct scsi_target *starget) {
|
| 392 | return starget->hostdata;
|
| 393 | }
|
| 394 |
|
| 395 | static inline struct domain_device *
|
| 396 | sdev_to_domain_dev(struct scsi_device *sdev) {
|
| 397 | return starget_to_domain_dev(sdev->sdev_target);
|
| 398 | }
|
| 399 |
|
| 400 | static inline struct ata_device *sas_to_ata_dev(struct domain_device *dev)
|
| 401 | {
|
| 402 | return &dev->sata_dev.ap->link.device[0];
|
| 403 | }
|
| 404 |
|
| 405 | static inline struct domain_device *
|
| 406 | cmd_to_domain_dev(struct scsi_cmnd *cmd)
|
| 407 | {
|
| 408 | return sdev_to_domain_dev(cmd->device);
|
| 409 | }
|
| 410 |
|
| 411 | |
| 412 | * when the link is severed (possibly from its tasklet).
|
| 413 | * The idea is that the Class only reads those, while the LLDD,
|
| 414 | * can R/W these (thus avoiding a race).
|
| 415 |
|
| 416 | static inline void sas_phy_disconnected(struct asd_sas_phy *phy)
|
| 417 | {
|
| 418 | phy->oob_mode = OOB_NOT_CONNECTED;
|
| 419 | phy->linkrate = SAS_LINK_RATE_UNKNOWN;
|
| 420 | }
|
| 421 |
|
| 422 | static inline unsigned int to_sas_gpio_od(int device, int bit)
|
| 423 | {
|
| 424 | return 3 * device + bit;
|
| 425 | }
|
| 426 |
|
| 427 | static inline void sas_put_local_phy(struct sas_phy *phy)
|
| 428 | {
|
| 429 | put_device(&phy->dev);
|
| 430 | }
|
| 431 |
|
| 432 | #ifdef CONFIG_SCSI_SAS_HOST_SMP
|
| 433 | int try_test_sas_gpio_gp_bit(unsigned int od, u8 *data, u8 index, u8 count);
|
| 434 | #else
|
| 435 | static inline int try_test_sas_gpio_gp_bit(unsigned int od, u8 *data, u8 index, u8 count)
|
| 436 | {
|
| 437 | return -1;
|
| 438 | }
|
| 439 | #endif
|
| 440 |
|
| 441 |
|
| 442 | |
| 443 | service_response | SAS_TASK_COMPLETE | SAS_TASK_UNDELIVERED |
|
| 444 | exec_status | | |
|
| 445 | ---------------------+---------------------+-----------------------+
|
| 446 | SAM_... | X | |
|
| 447 | DEV_NO_RESPONSE | X | X |
|
| 448 | INTERRUPTED | X | |
|
| 449 | QUEUE_FULL | | X |
|
| 450 | DEVICE_UNKNOWN | | X |
|
| 451 | SG_ERR | | X |
|
| 452 | ---------------------+---------------------+-----------------------+
|
| 453 |
|
| 454 |
|
| 455 | enum service_response {
|
| 456 | SAS_TASK_COMPLETE,
|
| 457 | SAS_TASK_UNDELIVERED = -1,
|
| 458 | };
|
| 459 |
|
| 460 | enum exec_status {
|
| 461 | |
| 462 | * Values 0..0x7f are used to return the SAM_STAT_* codes. To avoid
|
| 463 | * 'case value not in enumerated type' compiler warnings every value
|
| 464 | * returned through the exec_status enum needs an alias with the SAS_
|
| 465 | * prefix here.
|
| 466 |
|
| 467 | SAS_SAM_STAT_GOOD = SAM_STAT_GOOD,
|
| 468 | SAS_SAM_STAT_BUSY = SAM_STAT_BUSY,
|
| 469 | SAS_SAM_STAT_TASK_ABORTED = SAM_STAT_TASK_ABORTED,
|
| 470 | SAS_SAM_STAT_CHECK_CONDITION = SAM_STAT_CHECK_CONDITION,
|
| 471 |
|
| 472 | SAS_DEV_NO_RESPONSE = 0x80,
|
| 473 | SAS_DATA_UNDERRUN,
|
| 474 | SAS_DATA_OVERRUN,
|
| 475 | SAS_INTERRUPTED,
|
| 476 | SAS_QUEUE_FULL,
|
| 477 | SAS_DEVICE_UNKNOWN,
|
| 478 | SAS_OPEN_REJECT,
|
| 479 | SAS_OPEN_TO,
|
| 480 | SAS_PROTO_RESPONSE,
|
| 481 | SAS_PHY_DOWN,
|
| 482 | SAS_NAK_R_ERR,
|
| 483 | SAS_PENDING,
|
| 484 | SAS_ABORTED_TASK,
|
| 485 | };
|
| 486 |
|
| 487 | |
| 488 | * response:
|
| 489 | * - For an ATA task task_status_struct::stat is set to
|
| 490 | * SAS_PROTO_RESPONSE, and the task_status_struct::buf is set to the
|
| 491 | * contents of struct ata_task_resp.
|
| 492 | * - For SSP tasks, if no data is present or status/TMF response
|
| 493 | * is valid, task_status_struct::stat is set. If data is present
|
| 494 | * (SENSE data), the LLDD copies up to SAS_STATUS_BUF_SIZE, sets
|
| 495 | * task_status_struct::buf_valid_size, and task_status_struct::stat is
|
| 496 | * set to SAM_CHECK_COND.
|
| 497 | *
|
| 498 | * "buf" has format SCSI Sense for SSP task, or struct ata_task_resp
|
| 499 | * for ATA task.
|
| 500 | *
|
| 501 | * "frame_len" is the total frame length, which could be more or less
|
| 502 | * than actually copied.
|
| 503 | *
|
| 504 | * Tasks ending with response, always set the residual field.
|
| 505 |
|
| 506 | struct ata_task_resp {
|
| 507 | u16 frame_len;
|
| 508 | u8 ending_fis[ATA_RESP_FIS_SIZE];
|
| 509 | };
|
| 510 |
|
| 511 | #define SAS_STATUS_BUF_SIZE 96
|
| 512 |
|
| 513 | struct task_status_struct {
|
| 514 | enum service_response resp;
|
| 515 | enum exec_status stat;
|
| 516 | int buf_valid_size;
|
| 517 |
|
| 518 | u8 buf[SAS_STATUS_BUF_SIZE];
|
| 519 |
|
| 520 | u32 residual;
|
| 521 | enum sas_open_rej_reason open_rej_reason;
|
| 522 | };
|
| 523 |
|
| 524 | |
| 525 |
|
| 526 | struct sas_ata_task {
|
| 527 | struct host_to_dev_fis fis;
|
| 528 | u8 atapi_packet[16];
|
| 529 |
|
| 530 | u8 dma_xfer:1;
|
| 531 | u8 use_ncq:1;
|
| 532 | u8 return_fis_on_success:1;
|
| 533 |
|
| 534 | u8 device_control_reg_update:1;
|
| 535 |
|
| 536 | bool force_phy;
|
| 537 | int force_phy_id;
|
| 538 | };
|
| 539 |
|
| 540 |
|
| 541 | enum sas_internal_abort {
|
| 542 | SAS_INTERNAL_ABORT_SINGLE = 0,
|
| 543 | SAS_INTERNAL_ABORT_DEV = 1,
|
| 544 | };
|
| 545 |
|
| 546 | struct sas_internal_abort_task {
|
| 547 | enum sas_internal_abort type;
|
| 548 | unsigned int qid;
|
| 549 | u16 tag;
|
| 550 | };
|
| 551 |
|
| 552 | struct sas_smp_task {
|
| 553 | struct scatterlist smp_req;
|
| 554 | struct scatterlist smp_resp;
|
| 555 | };
|
| 556 |
|
| 557 | enum task_attribute {
|
| 558 | TASK_ATTR_SIMPLE = 0,
|
| 559 | TASK_ATTR_HOQ = 1,
|
| 560 | TASK_ATTR_ORDERED= 2,
|
| 561 | TASK_ATTR_ACA = 4,
|
| 562 | };
|
| 563 |
|
| 564 | struct sas_ssp_task {
|
| 565 | u8 LUN[8];
|
| 566 | enum task_attribute task_attr;
|
| 567 | struct scsi_cmnd *cmd;
|
| 568 | };
|
| 569 |
|
| 570 | struct sas_tmf_task {
|
| 571 | u8 tmf;
|
| 572 | u16 tag_of_task_to_be_managed;
|
| 573 | };
|
| 574 |
|
| 575 | struct sas_task {
|
| 576 | struct domain_device *dev;
|
| 577 |
|
| 578 | spinlock_t task_state_lock;
|
| 579 | unsigned task_state_flags;
|
| 580 |
|
| 581 | enum sas_protocol task_proto;
|
| 582 |
|
| 583 | union {
|
| 584 | struct sas_ata_task ata_task;
|
| 585 | struct sas_smp_task smp_task;
|
| 586 | struct sas_ssp_task ssp_task;
|
| 587 | struct sas_internal_abort_task abort_task;
|
| 588 | };
|
| 589 |
|
| 590 | struct scatterlist *scatter;
|
| 591 | int num_scatter;
|
| 592 | u32 total_xfer_len;
|
| 593 | u8 data_dir:2;
|
| 594 |
|
| 595 | struct task_status_struct task_status;
|
| 596 | void (*task_done)(struct sas_task *);
|
| 597 |
|
| 598 | void *lldd_task;
|
| 599 | void *uldd_task;
|
| 600 | struct sas_task_slow *slow_task;
|
| 601 | struct sas_tmf_task *tmf;
|
| 602 | };
|
| 603 |
|
| 604 | struct sas_task_slow {
|
| 605 | |
| 606 | * internal lldd commands
|
| 607 |
|
| 608 | struct timer_list timer;
|
| 609 | struct completion completion;
|
| 610 | struct sas_task *task;
|
| 611 | };
|
| 612 |
|
| 613 | #define SAS_TASK_STATE_PENDING 1
|
| 614 | #define SAS_TASK_STATE_DONE 2
|
| 615 | #define SAS_TASK_STATE_ABORTED 4
|
| 616 | #define SAS_TASK_NEED_DEV_RESET 8
|
| 617 |
|
| 618 | static inline bool sas_is_internal_abort(struct sas_task *task)
|
| 619 | {
|
| 620 | return task->task_proto == SAS_PROTOCOL_INTERNAL_ABORT;
|
| 621 | }
|
| 622 |
|
| 623 | static inline struct request *sas_task_find_rq(struct sas_task *task)
|
| 624 | {
|
| 625 | struct scsi_cmnd *scmd;
|
| 626 |
|
| 627 | if (task->task_proto & SAS_PROTOCOL_STP_ALL) {
|
| 628 | struct ata_queued_cmd *qc = task->uldd_task;
|
| 629 |
|
| 630 | scmd = qc ? qc->scsicmd : NULL;
|
| 631 | } else {
|
| 632 | scmd = task->uldd_task;
|
| 633 | }
|
| 634 |
|
| 635 | if (!scmd)
|
| 636 | return NULL;
|
| 637 |
|
| 638 | return scsi_cmd_to_rq(scmd);
|
| 639 | }
|
| 640 |
|
| 641 | struct sas_domain_function_template {
|
| 642 |
|
| 643 | void (*lldd_port_formed)(struct asd_sas_phy *);
|
| 644 | void (*lldd_port_deformed)(struct asd_sas_phy *);
|
| 645 |
|
| 646 |
|
| 647 | int (*lldd_dev_found)(struct domain_device *);
|
| 648 | void (*lldd_dev_gone)(struct domain_device *);
|
| 649 |
|
| 650 | int (*lldd_execute_task)(struct sas_task *, gfp_t gfp_flags);
|
| 651 |
|
| 652 |
|
| 653 | int (*lldd_abort_task)(struct sas_task *);
|
| 654 | int (*lldd_abort_task_set)(struct domain_device *, u8 *lun);
|
| 655 | int (*lldd_clear_task_set)(struct domain_device *, u8 *lun);
|
| 656 | int (*lldd_I_T_nexus_reset)(struct domain_device *);
|
| 657 | int (*lldd_ata_check_ready)(struct domain_device *);
|
| 658 | void (*lldd_ata_set_dmamode)(struct domain_device *);
|
| 659 | int (*lldd_lu_reset)(struct domain_device *, u8 *lun);
|
| 660 | int (*lldd_query_task)(struct sas_task *);
|
| 661 |
|
| 662 |
|
| 663 | void (*lldd_tmf_exec_complete)(struct domain_device *dev);
|
| 664 | void (*lldd_tmf_aborted)(struct sas_task *task);
|
| 665 | bool (*lldd_abort_timeout)(struct sas_task *task, void *data);
|
| 666 |
|
| 667 |
|
| 668 | int (*lldd_clear_nexus_port)(struct asd_sas_port *);
|
| 669 | int (*lldd_clear_nexus_ha)(struct sas_ha_struct *);
|
| 670 |
|
| 671 |
|
| 672 | int (*lldd_control_phy)(struct asd_sas_phy *, enum phy_func, void *);
|
| 673 |
|
| 674 |
|
| 675 | int (*lldd_write_gpio)(struct sas_ha_struct *, u8 reg_type,
|
| 676 | u8 reg_index, u8 reg_count, u8 *write_data);
|
| 677 | };
|
| 678 |
|
| 679 | extern int sas_register_ha(struct sas_ha_struct *);
|
| 680 | extern int sas_unregister_ha(struct sas_ha_struct *);
|
| 681 | extern void sas_prep_resume_ha(struct sas_ha_struct *sas_ha);
|
| 682 | extern void sas_resume_ha(struct sas_ha_struct *sas_ha);
|
| 683 | extern void sas_suspend_ha(struct sas_ha_struct *sas_ha);
|
| 684 |
|
| 685 | int sas_phy_reset(struct sas_phy *phy, int hard_reset);
|
| 686 | int sas_phy_enable(struct sas_phy *phy, int enable);
|
| 687 | extern enum scsi_qc_status sas_queuecommand(struct Scsi_Host *host,
|
| 688 | struct scsi_cmnd *cmd);
|
| 689 | extern int sas_target_alloc(struct scsi_target *);
|
| 690 | int sas_sdev_configure(struct scsi_device *dev, struct queue_limits *lim);
|
| 691 | extern int sas_change_queue_depth(struct scsi_device *, int new_depth);
|
| 692 | extern int sas_bios_param(struct scsi_device *, struct gendisk *,
|
| 693 | sector_t capacity, int *hsc);
|
| 694 | int sas_execute_internal_abort_single(struct domain_device *device,
|
| 695 | u16 tag, unsigned int qid,
|
| 696 | void *data);
|
| 697 | int sas_execute_internal_abort_dev(struct domain_device *device,
|
| 698 | unsigned int qid, void *data);
|
| 699 | extern struct scsi_transport_template *
|
| 700 | sas_domain_attach_transport(struct sas_domain_function_template *);
|
| 701 | extern struct device_attribute dev_attr_phy_event_threshold;
|
| 702 |
|
| 703 | void sas_task_abort(struct sas_task *);
|
| 704 | int sas_eh_abort_handler(struct scsi_cmnd *cmd);
|
| 705 | int sas_eh_device_reset_handler(struct scsi_cmnd *cmd);
|
| 706 | int sas_eh_target_reset_handler(struct scsi_cmnd *cmd);
|
| 707 | enum scsi_timeout_action sas_eh_timed_out(struct scsi_cmnd *cmd);
|
| 708 |
|
| 709 | extern void sas_target_destroy(struct scsi_target *);
|
| 710 | extern int sas_sdev_init(struct scsi_device *);
|
| 711 | extern int sas_ioctl(struct scsi_device *sdev, unsigned int cmd,
|
| 712 | void __user *arg);
|
| 713 | extern int sas_drain_work(struct sas_ha_struct *ha);
|
| 714 |
|
| 715 | extern void sas_ssp_task_response(struct device *dev, struct sas_task *task,
|
| 716 | struct ssp_response_iu *iu);
|
| 717 | struct sas_phy *sas_get_local_phy(struct domain_device *dev);
|
| 718 |
|
| 719 | int sas_request_addr(struct Scsi_Host *shost, u8 *addr);
|
| 720 |
|
| 721 | int sas_abort_task_set(struct domain_device *dev, u8 *lun);
|
| 722 | int sas_clear_task_set(struct domain_device *dev, u8 *lun);
|
| 723 | int sas_lu_reset(struct domain_device *dev, u8 *lun);
|
| 724 | int sas_query_task(struct sas_task *task, u16 tag);
|
| 725 | int sas_abort_task(struct sas_task *task, u16 tag);
|
| 726 | int sas_find_attached_phy_id(struct expander_device *ex_dev,
|
| 727 | struct domain_device *dev);
|
| 728 |
|
| 729 | void sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event,
|
| 730 | gfp_t gfp_flags);
|
| 731 | void sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event,
|
| 732 | gfp_t gfp_flags);
|
| 733 |
|
| 734 | #define __LIBSAS_SHT_BASE \
|
| 735 | .module = THIS_MODULE, \
|
| 736 | .name = DRV_NAME, \
|
| 737 | .proc_name = DRV_NAME, \
|
| 738 | .queuecommand = sas_queuecommand, \
|
| 739 | .dma_need_drain = ata_scsi_dma_need_drain, \
|
| 740 | .target_alloc = sas_target_alloc, \
|
| 741 | .change_queue_depth = sas_change_queue_depth, \
|
| 742 | .bios_param = sas_bios_param, \
|
| 743 | .this_id = -1, \
|
| 744 | .eh_device_reset_handler = sas_eh_device_reset_handler, \
|
| 745 | .eh_target_reset_handler = sas_eh_target_reset_handler, \
|
| 746 | .eh_timed_out = sas_eh_timed_out, \
|
| 747 | .target_destroy = sas_target_destroy, \
|
| 748 | .ioctl = sas_ioctl, \
|
| 749 |
|
| 750 | #ifdef CONFIG_COMPAT
|
| 751 | #define _LIBSAS_SHT_BASE __LIBSAS_SHT_BASE \
|
| 752 | .compat_ioctl = sas_ioctl,
|
| 753 | #else
|
| 754 | #define _LIBSAS_SHT_BASE __LIBSAS_SHT_BASE
|
| 755 | #endif
|
| 756 |
|
| 757 | #define LIBSAS_SHT_BASE _LIBSAS_SHT_BASE \
|
| 758 | .sdev_configure = sas_sdev_configure, \
|
| 759 | .sdev_init = sas_sdev_init, \
|
| 760 |
|
| 761 | #define LIBSAS_SHT_BASE_NO_SLAVE_INIT _LIBSAS_SHT_BASE
|
| 762 |
|
| 763 |
|
| 764 | #endif
|