13 #include <linux/slab.h>
14 #include <linux/export.h>
20 #include "../scsi_sas_internal.h"
22 static void sas_host_smp_discover(
struct sas_ha_struct *sas_ha,
u8 *resp_data,
38 memcpy(resp_data + 24, sas_ha->
sas_phy[phy_id]->attached_sas_addr,
45 if (!sas_ha->
sas_phy[phy_id]->port ||
46 !sas_ha->
sas_phy[phy_id]->port->port_dev)
50 resp_data[12] = rphy->
identify.device_type << 4;
51 resp_data[14] = rphy->
identify.initiator_port_protocols;
52 resp_data[15] = rphy->
identify.target_port_protocols;
98 *bit = od & ((1 << 3) - 1);
100 return &data[reg * 4 +
byte];
108 byte = to_sas_gpio_gp_bit(od, data, index, count, &bit);
112 return (*byte >> bit) & 1;
116 static int sas_host_smp_write_gpio(
struct sas_ha_struct *sas_ha,
u8 *resp_data,
117 u8 reg_type,
u8 reg_index,
u8 reg_count,
123 if (i->
dft->lldd_write_gpio ==
NULL) {
128 written = i->
dft->lldd_write_gpio(sas_ha, reg_type, reg_index,
129 reg_count, req_data);
140 static void sas_report_phy_sata(
struct sas_ha_struct *sas_ha,
u8 *resp_data,
154 if (!sas_ha->
sas_phy[phy_id]->port)
159 sas_ha->
sas_phy[phy_id]->port->port_dev->frame_rcvd;
165 memcpy(resp_data + 16, sas_ha->
sas_phy[phy_id]->attached_sas_addr,
173 for (i = 0; i < 20; i += 4) {
213 rates.minimum_linkrate =
min;
214 rates.maximum_linkrate =
max;
222 if (i->
dft->lldd_control_phy(asd_phy, phy_op, &rates))
236 if (blk_rq_bytes(req) < 8 || blk_rq_bytes(rsp) < 8)
239 if (bio_offset(req->bio) + blk_rq_bytes(req) >
PAGE_SIZE ||
240 bio_offset(rsp->bio) + blk_rq_bytes(rsp) >
PAGE_SIZE) {
242 "SMP request/response frame crosses page boundary");
246 req_data = kzalloc(blk_rq_bytes(req),
GFP_KERNEL);
252 if (!req_data || !resp_data) {
259 memcpy(req_data, buf, blk_rq_bytes(req));
272 resp_data[1] = req_data[1];
275 switch (req_data[1]) {
278 rsp->resid_len -= 32;
285 rsp->resid_len -= 64;
289 memcpy(resp_data + 20,
"libsas virt phy",
298 req->resid_len -= 16;
299 if ((
int)req->resid_len < 0) {
304 rsp->resid_len -= 56;
305 sas_host_smp_discover(sas_ha, resp_data, req_data[9]);
314 req->resid_len -= 16;
315 if ((
int)req->resid_len < 0) {
320 rsp->resid_len -= 60;
321 sas_report_phy_sata(sas_ha, resp_data, req_data[9]);
330 const int base_frame_size = 11;
331 int to_write = req_data[4];
333 if (blk_rq_bytes(req) < base_frame_size + to_write * 4 ||
334 req->resid_len < base_frame_size + to_write * 4) {
339 to_write = sas_host_smp_write_gpio(sas_ha, resp_data, req_data[2],
340 req_data[3], to_write, &req_data[8]);
341 req->resid_len -= base_frame_size + to_write * 4;
351 req->resid_len -= 44;
352 if ((
int)req->resid_len < 0) {
358 sas_phy_control(sas_ha, req_data[9], req_data[10],
359 req_data[32] >> 4, req_data[33] >> 4,
374 memcpy(buf, resp_data, blk_rq_bytes(rsp));
375 flush_kernel_dcache_page(bio_page(rsp->bio));